Waitlist
Turn your Nuxt app into a pre-launch email capture with one config flag. Waitlist mode rewires the hero, navbar, and auth using Better Auth magic links.
Waitlist mode turns the public app into a pre-launch email capture, governed by the config.waitlist flag in @repo/config. The flow is built on Better Auth magic links plus the waitlist-confirmation template from @repo/mail.
The flag
config.waitlist lives at the top level of packages/config/src/index.ts.
| Key | Type | Default | Description |
|---|---|---|---|
waitlist | boolean | false | Pre-launch email capture instead of open sign-up |
// packages/config/src/index.ts
export const config: AppConfig = {
waitlist: false,
// …
};What flips when waitlist: true
The flag rewires the hero, the email, the auto-sign-in step, and the route guards - all from one boolean.
| Surface | File | false (default) | true |
|---|---|---|---|
| Hero CTA | app/components/landing/hero/Hero.vue | Pricing / sign-up buttons | Inline email capture form |
| Form submit | Hero.vue | - | authClient.signIn.magicLink |
| Verification email | packages/auth/src/config.ts | email-verification | waitlist-confirmation |
| Magic-link email | packages/auth/src/config.ts | magic-link | waitlist-confirmation |
autoSignInAfterVerification | packages/auth/src/config.ts | true | false (!config.waitlist) |
| Navbar | app/components/layout/navbar/Navbar.vue | Sign-in / dashboard | Single Join button → /#hero |
| Route guards | app/middleware/auth.ts, guest.ts | Normal redirects | navigateTo(localePath("/")) (all protected routes go home) |
How a join works
The hero form posts the email through authClient.signIn.magicLink. When config.captcha.enabled is true (provider turnstile), the token rides along in the x-captcha-response header.
Better Auth's sendMagicLink detects config.waitlist and sends the waitlist-confirmation email instead of the normal magic link (packages/auth/src/config.ts).
The visitor confirms via the link. Because autoSignInAfterVerification is false in waitlist mode, they stay on the list rather than landing in the dashboard.
The confirmation email
The waitlist-confirmation template lives at packages/mail/src/templates/waitlist-confirmation.tsx and takes a single verificationUrl prop.
export interface WaitlistConfirmationEmailProps {
verificationUrl: string;
}The confirmation email only sends when a mail provider is configured. Wire up your provider in Email before flipping the flag, or joins are captured with no confirmation sent.
Enabling it
Set waitlist: true in packages/config/src/index.ts.
Confirm a mail provider is configured so waitlist-confirmation can send - see Email.
Edit the email copy in packages/mail/src/templates/waitlist-confirmation.tsx and the waitlist.* i18n keys for the hero form.
Restart apps/web-nuxt and verify the hero shows the capture form and the navbar shows Join.
Frequently asked questions
Does the visitor get an account?
Joining goes through magic link, so a user row exists, but autoSignInAfterVerification is off in waitlist mode - they aren't signed in and every protected route redirects home until you launch.
How do I launch?
Set waitlist: false and redeploy. The hero, navbar, and route guards revert to the normal flow, and confirmed users can sign in as usual.
Can I keep the captcha on the waitlist form?
Yes. When config.captcha.enabled is true (provider turnstile), the hero mounts an invisible Turnstile widget (appearance="interaction-only", screen-reader-only) and sends the token in the x-captcha-response header - see Authentication.