Auth Overview
Magic-link sign-in, sessions, and the middleware that guards the dashboard.
What ships
Supabase Auth with magic links. There are no passwords to store and no OAuth apps to register before you can sign in.
- Sign-in modal: components/marketing/ButtonSignin.jsx calls signInWithOtp
- Link handling: app/auth/confirm exchanges the token, app/auth/callback finishes the session in the browser
- Session: cookies, read on the server by lib/auth.js
- Protected routes: middleware.js guards /dashboard/*
Flow
1. The user enters an email in the sign-in modal
2. Supabase emails a magic link
3. The link lands on /auth/confirm, which creates the session
4. The user is sent to the page they asked for (the next parameter)
5. On first sign-in, a public.users row and a public.usage row are created by database triggers, and any pending purchase for that email is claimed
Protected routes
middleware.js runs on every /dashboard request. Without a session it redirects to the home page with the sign-in modal open and the original path preserved. If Supabase keys are not configured it redirects too, instead of throwing.
// middleware.js (abridged)
export const config = { matcher: ["/dashboard/:path*"] };
function redirectToSignin(request) {
const url = new URL("/", request.url);
url.searchParams.set("signin", "1");
url.searchParams.set("next", request.nextUrl.pathname);
return NextResponse.redirect(url);
}Reading the user
On the client, useSupabaseAuth() from components/providers/SupabaseAuthProvider.jsx gives you the session. In API routes, getAuthenticatedUser(req) and getAppUser() from lib/auth.js verify the token and load the public.users row.