Registration gate: open on 16 March 2026 at 19:00 with countdown + confetti #2

Closed
opened 2026-03-10 11:44:00 +00:00 by zias · 1 comment
Owner

Context

The Mollie payment provider integration is still being set up. Until both the payment provider and the signup opening date arrive, the registration form and the account-creation flow on the login page must remain disabled. Everything opens on Monday 16 March 2026 at 19:00 (CET).

While the site is in the pre-open state, visitors should see a live countdown. When the countdown reaches zero, confetti fires and registration becomes available without a page reload.


Scope

1. Add a single source-of-truth constant

Create apps/web/src/lib/opening.ts:

// Change this date to move the opening gate.
export const REGISTRATION_OPENS_AT = new Date("2026-03-16T19:00:00+01:00");

All gating logic imports from this one file. No env vars, no feature flags — just a const.


2. useRegistrationOpen hook

Create apps/web/src/lib/useRegistrationOpen.ts:

  • Returns { isOpen: boolean; secondsLeft: number }.
  • Uses setInterval (1 s tick) that compares Date.now() to REGISTRATION_OPENS_AT.
  • Clears the interval once isOpen becomes true.
  • This hook is the only place that reads the constant; all UI consumes it.

3. CountdownBanner component

Create apps/web/src/components/homepage/CountdownBanner.tsx:

  • Renders only when !isOpen.
  • Displays DD days, HH hours, MM minutes, SS seconds (each in its own labelled box).
  • Styled to match the site palette (dark teal background #214e51, white text, Intro typeface).
  • Fires confetti (see §5) at the moment isOpen flips to true.

4. Gate the EventRegistrationForm

In apps/web/src/components/homepage/EventRegistrationForm.tsx:

  • Import useRegistrationOpen.
  • When !isOpen: render the CountdownBanner in place of the entire registration form body. Keep the section wrapper and heading visible so the page anchor still works and context is clear.
  • When isOpen: render the existing form exactly as today.
  • No other logic changes; no API routes touched.

5. Gate account signup on the login page

In apps/web/src/routes/login.tsx:

  • Import useRegistrationOpen.
  • When !isOpen and the page is in signup mode (isSignup === true): show a "Registratie opent op 16 maart om 19:00" message and disable / hide the signup form. Login for existing accounts remains fully functional.
  • The toggle "Nog geen account? Registreer" link should also be hidden / non-functional while closed.

6. Gate the inline account-creation modal in WatcherForm

WatcherForm contains an AccountModal component that calls authClient.signUp.email(...). Because WatcherForm itself is already behind the EventRegistrationForm gate (§4), this modal is implicitly protected. No additional change is strictly needed, but for defence-in-depth the AccountModal's submit handler can check isOpen and show a toast if somehow triggered while closed.


7. Confetti

  • Add the canvas-confetti package (bun add canvas-confetti + bun add -D @types/canvas-confetti in apps/web).
  • In CountdownBanner, when isOpen transitions from false to true (detected via useEffect dependency on isOpen), call a short multi-burst confetti animation.
  • Confetti only fires once (guard with a useRef flag).

Files to create / modify

Action File
Create apps/web/src/lib/opening.ts
Create apps/web/src/lib/useRegistrationOpen.ts
Create apps/web/src/components/homepage/CountdownBanner.tsx
Modify apps/web/src/components/homepage/EventRegistrationForm.tsx
Modify apps/web/src/routes/login.tsx
Modify (optional defence-in-depth) apps/web/src/components/registration/WatcherForm.tsx
Modify (add dep) apps/web/package.json

What is explicitly not in scope

  • No backend / API changes.
  • No database migrations.
  • No Mollie integration work (tracked separately).
  • No environment variable or feature-flag infrastructure — the opening date is a compile-time constant, easy to change before the next deploy.
## Context The Mollie payment provider integration is still being set up. Until both the payment provider **and** the signup opening date arrive, the registration form and the account-creation flow on the login page must remain disabled. Everything opens on **Monday 16 March 2026 at 19:00 (CET)**. While the site is in the pre-open state, visitors should see a live countdown. When the countdown reaches zero, confetti fires and registration becomes available without a page reload. --- ## Scope ### 1. Add a single source-of-truth constant Create `apps/web/src/lib/opening.ts`: ```ts // Change this date to move the opening gate. export const REGISTRATION_OPENS_AT = new Date("2026-03-16T19:00:00+01:00"); ``` All gating logic imports from this one file. No env vars, no feature flags — just a const. --- ### 2. `useRegistrationOpen` hook Create `apps/web/src/lib/useRegistrationOpen.ts`: - Returns `{ isOpen: boolean; secondsLeft: number }`. - Uses `setInterval` (1 s tick) that compares `Date.now()` to `REGISTRATION_OPENS_AT`. - Clears the interval once `isOpen` becomes `true`. - This hook is the only place that reads the constant; all UI consumes it. --- ### 3. `CountdownBanner` component Create `apps/web/src/components/homepage/CountdownBanner.tsx`: - Renders only when `!isOpen`. - Displays `DD` days, `HH` hours, `MM` minutes, `SS` seconds (each in its own labelled box). - Styled to match the site palette (dark teal background `#214e51`, white text, `Intro` typeface). - Fires confetti (see §5) at the moment `isOpen` flips to `true`. --- ### 4. Gate the `EventRegistrationForm` In `apps/web/src/components/homepage/EventRegistrationForm.tsx`: - Import `useRegistrationOpen`. - When `!isOpen`: render the `CountdownBanner` in place of the entire registration form body. Keep the section wrapper and heading visible so the page anchor still works and context is clear. - When `isOpen`: render the existing form exactly as today. - No other logic changes; no API routes touched. --- ### 5. Gate account signup on the login page In `apps/web/src/routes/login.tsx`: - Import `useRegistrationOpen`. - When `!isOpen` and the page is in signup mode (`isSignup === true`): show a "Registratie opent op 16 maart om 19:00" message and disable / hide the signup form. Login for existing accounts remains fully functional. - The toggle "Nog geen account? Registreer" link should also be hidden / non-functional while closed. --- ### 6. Gate the inline account-creation modal in `WatcherForm` `WatcherForm` contains an `AccountModal` component that calls `authClient.signUp.email(...)`. Because `WatcherForm` itself is already behind the `EventRegistrationForm` gate (§4), this modal is implicitly protected. No additional change is strictly needed, but for defence-in-depth the `AccountModal`'s submit handler can check `isOpen` and show a toast if somehow triggered while closed. --- ### 7. Confetti - Add the `canvas-confetti` package (`bun add canvas-confetti` + `bun add -D @types/canvas-confetti` in `apps/web`). - In `CountdownBanner`, when `isOpen` transitions from `false` to `true` (detected via `useEffect` dependency on `isOpen`), call a short multi-burst confetti animation. - Confetti only fires once (guard with a `useRef` flag). --- ## Files to create / modify | Action | File | |--------|------| | **Create** | `apps/web/src/lib/opening.ts` | | **Create** | `apps/web/src/lib/useRegistrationOpen.ts` | | **Create** | `apps/web/src/components/homepage/CountdownBanner.tsx` | | **Modify** | `apps/web/src/components/homepage/EventRegistrationForm.tsx` | | **Modify** | `apps/web/src/routes/login.tsx` | | **Modify** (optional defence-in-depth) | `apps/web/src/components/registration/WatcherForm.tsx` | | **Modify** (add dep) | `apps/web/package.json` | --- ## What is explicitly **not** in scope - No backend / API changes. - No database migrations. - No Mollie integration work (tracked separately). - No environment variable or feature-flag infrastructure — the opening date is a compile-time constant, easy to change before the next deploy.
Author
Owner

Implemented — commit cf47f25

All changes from the plan have been applied:

New files

  • apps/web/src/lib/opening.ts — exports REGISTRATION_OPENS_AT = new Date("2026-03-16T19:00:00+01:00")
  • apps/web/src/lib/useRegistrationOpen.ts — hook that ticks every second, returns { isOpen, days, hours, minutes, seconds }
  • apps/web/src/components/homepage/CountdownBanner.tsx — DD:HH:MM:SS display in site palette; fires canvas-confetti (3 bursts in brand colours) the moment isOpen flips to true

Modified files

  • EventRegistrationForm.tsx — shows <CountdownBanner /> in place of the form body while closed; switches to the full form the instant the gate opens (no reload needed)
  • login.tsx — signup tab replaced with a "Registratie opent op [date] om [time]" notice while closed; login for existing accounts is always available; signup toggle greyed out with tooltip
  • WatcherForm.tsxAccountModal.handleSignup checks isOpen and toasts an error as defence-in-depth
  • apps/web/package.json / bun.lock — added canvas-confetti@1.9.4 + @types/canvas-confetti@1.9.0

To change the opening date in the future, edit the single constant in apps/web/src/lib/opening.ts.

## Implemented — commit `cf47f25` All changes from the plan have been applied: ### New files - `apps/web/src/lib/opening.ts` — exports `REGISTRATION_OPENS_AT = new Date("2026-03-16T19:00:00+01:00")` - `apps/web/src/lib/useRegistrationOpen.ts` — hook that ticks every second, returns `{ isOpen, days, hours, minutes, seconds }` - `apps/web/src/components/homepage/CountdownBanner.tsx` — DD:HH:MM:SS display in site palette; fires `canvas-confetti` (3 bursts in brand colours) the moment `isOpen` flips to `true` ### Modified files - `EventRegistrationForm.tsx` — shows `<CountdownBanner />` in place of the form body while closed; switches to the full form the instant the gate opens (no reload needed) - `login.tsx` — signup tab replaced with a "Registratie opent op [date] om [time]" notice while closed; login for existing accounts is always available; signup toggle greyed out with tooltip - `WatcherForm.tsx` — `AccountModal.handleSignup` checks `isOpen` and toasts an error as defence-in-depth - `apps/web/package.json` / `bun.lock` — added `canvas-confetti@1.9.4` + `@types/canvas-confetti@1.9.0` To change the opening date in the future, edit the single constant in `apps/web/src/lib/opening.ts`.
zias closed this issue 2026-03-10 12:17:46 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: zias/kunstenkamp#2