Live demo of the Whirlwind template, as shippedStripe test mode: card 4242 4242 4242 4242, any future date, any CVCGet Whirlwind →

Magic Link

How the passwordless sign-in and the post-purchase claim link are wired.

How it is wired

The sign-in modal sends the link with a redirect back to /auth/confirm, carrying the path the user wanted:
const { error } = await supabase.auth.signInWithOtp({
  email,
  options: {
    emailRedirectTo: `${window.location.origin}/auth/confirm?next=${encodeURIComponent(nextPath)}`,
  },
});

Supabase settings that matter

- Authentication → URL Configuration: add your production URL and http://localhost:3000 to Redirect URLs, or links will bounce - Authentication → Email Templates → Magic Link: edit the wording and sender - Rate limits on the Auth page apply to how often one address can request a link
💡

npm run deploy lists the Supabase redirect URL among the production switches it checks.

After purchase

Checkout is email-first: a buyer pays on Stripe before they have an account. The Stripe webhook records a pending purchase and emails a magic link. When that link is used, the purchase is claimed automatically. /api/claim/send-link resends the link if the first one is lost.