Registration gate: open on 16 March 2026 at 19:00 with countdown + confetti #2
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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:All gating logic imports from this one file. No env vars, no feature flags — just a const.
2.
useRegistrationOpenhookCreate
apps/web/src/lib/useRegistrationOpen.ts:{ isOpen: boolean; secondsLeft: number }.setInterval(1 s tick) that comparesDate.now()toREGISTRATION_OPENS_AT.isOpenbecomestrue.3.
CountdownBannercomponentCreate
apps/web/src/components/homepage/CountdownBanner.tsx:!isOpen.DDdays,HHhours,MMminutes,SSseconds (each in its own labelled box).#214e51, white text,Introtypeface).isOpenflips totrue.4. Gate the
EventRegistrationFormIn
apps/web/src/components/homepage/EventRegistrationForm.tsx:useRegistrationOpen.!isOpen: render theCountdownBannerin place of the entire registration form body. Keep the section wrapper and heading visible so the page anchor still works and context is clear.isOpen: render the existing form exactly as today.5. Gate account signup on the login page
In
apps/web/src/routes/login.tsx:useRegistrationOpen.!isOpenand 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.6. Gate the inline account-creation modal in
WatcherFormWatcherFormcontains anAccountModalcomponent that callsauthClient.signUp.email(...). BecauseWatcherFormitself is already behind theEventRegistrationFormgate (§4), this modal is implicitly protected. No additional change is strictly needed, but for defence-in-depth theAccountModal's submit handler can checkisOpenand show a toast if somehow triggered while closed.7. Confetti
canvas-confettipackage (bun add canvas-confetti+bun add -D @types/canvas-confettiinapps/web).CountdownBanner, whenisOpentransitions fromfalsetotrue(detected viauseEffectdependency onisOpen), call a short multi-burst confetti animation.useRefflag).Files to create / modify
apps/web/src/lib/opening.tsapps/web/src/lib/useRegistrationOpen.tsapps/web/src/components/homepage/CountdownBanner.tsxapps/web/src/components/homepage/EventRegistrationForm.tsxapps/web/src/routes/login.tsxapps/web/src/components/registration/WatcherForm.tsxapps/web/package.jsonWhat is explicitly not in scope
Implemented — commit
cf47f25All changes from the plan have been applied:
New files
apps/web/src/lib/opening.ts— exportsREGISTRATION_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; firescanvas-confetti(3 bursts in brand colours) the momentisOpenflips totrueModified 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 tooltipWatcherForm.tsx—AccountModal.handleSignupchecksisOpenand toasts an error as defence-in-depthapps/web/package.json/bun.lock— addedcanvas-confetti@1.9.4+@types/canvas-confetti@1.9.0To change the opening date in the future, edit the single constant in
apps/web/src/lib/opening.ts.