Documentation Index
Fetch the complete documentation index at: https://docs.vertz.dev/llms.txt
Use this file to discover all available pages before exploring further.
AuthProvider gives your app session management: sign-in, sign-up, sign-out, token refresh, MFA, and SSR hydration. Wrap your app, use useAuth() to read state, and use form(auth.signIn) for login — same patterns as the rest of the framework.
Quick start
1. Wrap your app
2. Build a login form
3. Read auth state anywhere
auth.signIn is an SdkMethod — form() works with it directly for validation, submission, and error handling. No manual fetch calls, no state wiring.
How it works
Auth state machine
| Status | Meaning |
|---|---|
idle | Initial state before any auth check (SSR/Node only) |
loading | Auth operation in progress |
authenticated | Valid session, auth.user is populated |
unauthenticated | No valid session |
mfa_required | Sign-in succeeded but MFA verification needed |
error | Auth operation failed, auth.error has details |
JWT session lifecycle
Vertz uses httpOnly cookies for JWT tokens — the client never reads the token directly. The server returnsexpiresAt in the response body, and the client schedules proactive refresh:
- Scheduled 10 seconds before expiry
- Deduplicated (concurrent calls share one in-flight request)
- Deferred when the tab is hidden (refreshes on focus if stale)
- Deferred when offline (refreshes on reconnect)
API reference
AuthProvider
Wraps your app with auth context. AlluseAuth() calls must be inside an AuthProvider.
| Prop | Type | Default | Description |
|---|---|---|---|
basePath | string | '/api/auth' | Base URL for auth endpoints |
accessControl | boolean | false | Enable automatic access set management |
children | unknown | — | App content |
useAuth()
Returns reactive auth state. All signal properties are auto-unwrapped by the compiler — no.value needed.
| Property | Type | Description |
|---|---|---|
user | User | null | Current user or null |
status | AuthStatus | Current auth state |
isAuthenticated | boolean | true when status is 'authenticated' |
isLoading | boolean | true when status is 'loading' |
error | AuthClientError | null | Last auth error |
signIn | SdkMethod | Sign in with email/password |
signUp | SdkMethod | Create account with email/password |
signOut | () => Promise<void> | Clear session and cookies |
refresh | () => Promise<void> | Manually refresh the token |
mfaChallenge | SdkMethod | Submit MFA TOTP code |
forgotPassword | SdkMethod | Request password reset email |
resetPassword | SdkMethod | Reset password with token |
AuthGate
Gates rendering on auth state resolution. Shows fallback while auth is loading, children once resolved.ProtectedRoute
Route guard that handles loading, authentication, entitlements, and redirect — all in one component. WrapsuseAuth(), the router, and can() so you don’t have to.
| Prop | Type | Default | Description |
|---|---|---|---|
loginPath | string | '/login' | Where to redirect unauthenticated users |
fallback | () => unknown | null | Rendered while auth is resolving |
children | unknown | — | Rendered when authenticated |
requires | Entitlement[] | — | Entitlements the user must have (checked via can()). Type-safe when codegen is active. |
forbidden | () => unknown | null | Rendered when authenticated but lacking entitlements |
returnTo | boolean | true | Append ?returnTo=<currentPath> to the login redirect |
| Auth state | Result |
|---|---|
idle / loading | Renders fallback |
authenticated (entitlements met) | Renders children |
authenticated (entitlements denied) | Renders forbidden (no redirect) |
unauthenticated / error / mfa_required | Navigates to loginPath |
ProtectedRoute does NOT redirect when entitlements fail — it renders forbidden instead. This
avoids redirect loops where a logged-in user is sent to login but still lacks permissions after
signing in.AuthProvider in the tree, ProtectedRoute renders children and logs a dev-mode warning. This matches AuthGate’s fail-open behavior.
SSR: During server rendering, ProtectedRoute renders the fallback. The redirect fires client-side after hydration.
Auth methods as SdkMethods
Every auth method (signIn, signUp, mfaChallenge, forgotPassword, resetPassword) is an SdkMethod. This means:
form()works directly — validation, submission, field errors, all automatic.urland.methodare available for<form action={...} method={...}>.meta.bodySchemaprovides the validation schema
Input types
| Method | Required fields |
|---|---|
signIn | { email: string, password: string } |
signUp | { email: string, password: string } |
mfaChallenge | { code: string } |
forgotPassword | { email: string } |
resetPassword | { token: string, password: string } |
MFA flow
When the server requires MFA,signIn transitions to mfa_required instead of authenticated:
Password reset flow
Request reset email
Reset with token
SSR hydration
When using SSR, the server injects the session into the page so the client doesn’t need an initial/api/auth/session fetch.
Server side
What happens on the client
- Server injects
window.__VERTZ_SESSION__with{ user, expiresAt } AuthProviderreads it on initialization — no fetch needed- Auth state is
'authenticated'immediately — no loading flicker - Token refresh is scheduled from the hydrated
expiresAt
AuthProvider transitions to 'unauthenticated' immediately.
Access control integration
WhenaccessControl is enabled, AuthProvider automatically manages the access set:
- Wraps children in
AccessContext.Provider - Fetches the access set from
${basePath}/access-setafter successful auth - Clears the access set on sign out
- Hydrates from
window.__VERTZ_ACCESS_SET__during SSR
can() anywhere inside the provider:
can(), AccessGate, and entity-scoped checks.
Error handling
Auth errors are available viaauth.error:
Error codes
| Code | When |
|---|---|
INVALID_CREDENTIALS | Wrong email/password |
USER_EXISTS | Email already registered |
MFA_REQUIRED | MFA verification needed (status transitions to mfa_required) |
INVALID_MFA_CODE | Wrong MFA code |
RATE_LIMITED | Too many attempts (retryAfter is set) |
NETWORK_ERROR | Fetch failed (offline, DNS, etc.) |
SERVER_ERROR | Unexpected server error |
Common patterns
Logout button
Conditional rendering based on auth
Sign-up with extra fields
signUp input accepts { email, password, ...extra }, but reserved auth fields such as
role, plan, emailVerified, id, and timestamps are ignored by the auth handler.
Next steps
Multi-Tenancy
TenantProvider, useTenant(), and TenantSwitcher for multi-tenant apps.
Server-Side Auth
Configure JWT sessions, RBAC, plans, and usage limits.
Access Control
Use
can() and AccessGate in your UI components.Forms
Deep dive into
form() — validation, fields, progressive enhancement.SSR
Server-side rendering setup and hydration.