Authentication
The boilerplate uses Better Auth for authentication, running inside the Convex backend.
Supported Methods
- Email/Password — With email verification and password reset
- Google OAuth — One-click Google sign-in
- GitHub OAuth — Sign in with GitHub
How It Works
Authentication uses a cross-domain setup where:
- The auth client runs in the browser (
src/shared/auth-client.ts) - Auth endpoints are hosted on the Convex site domain (
.convex.site) - Sessions are stored in
localStorage(not cookies)
This means auth is client-side only — the server cannot verify auth state during SSR.
Auth Guard
Protected pages use an auth guard state machine with these states:
| State | Meaning |
|---|---|
| idle | Initial state |
| checking | Waiting for auth to resolve |
| ott_exchange | OAuth callback in progress |
| authenticated | User is logged in |
| unauthenticated | No session found |
The guard handles edge cases like OAuth One-Time Token exchanges and prevents infinite loading states with a 10-second timeout.
Team Context
After authentication, the team context loads automatically:
- First team is selected by default
- Selection persists in
localStorage - Team switcher appears in the sidebar when user has multiple teams