Sessions
Understand how session data flows through StarterApp
BetterAuth stores sessions in secure cookies; Convex keeps the user document and organisation state in sync. StarterApp exposes the result through a few predictable helpers so you can read session information wherever you are working.
One concept, three touchpoints
Use getCurrentSession() on the server, useSession() on the client, and auth.api.getSession() inside API routes. They all describe the same signed-in user.
Server-side access
getCurrentSession()(frompackages/app-shell/src/lib/auth/server.ts) returns the current user ornull. Use it when you want to show different content to guests.requireUser()redirects unauthenticated visitors to/sign-in. Reach for it in protected layouts and pages.- Both helpers automatically fetch the richer Convex user record, including active organisation details.
Remember: protected layouts and pages must export the cache killers:
export const revalidate = 0;
export const dynamic = "force-dynamic";
export const fetchCache = "force-no-store";
These exports prevent Next.js from caching personalised data.
Client-side access
- Wrap the dashboard in
ConvexBetterAuthProvider(already done inapps/dashboard/app/providers.tsx). - Call
useSession()to get{ data, isPending }. WhileisPendingistrue, the hook is still resolving the session. - Prefer
useQuery(api.auth.getCurrentUser)when you need live updates (for example, switching organisations or editing profile data).
API routes and server actions
- Import
authfrom@workspace/auth/serverand callauth.api.getSession({ headers: await headers() }). - Combine it with CSRF checks (
assertOrigin,assertFetchMetadata) before writing data. - Use
secureUserJsonfor successful responses andsecureErrorJsonfor errors so security headers stay consistent.
Session lifecycle (behind the scenes)
- User signs in through Google or the credential form. BetterAuth creates an HttpOnly cookie.
- Convex triggers ensure the user record exists, create a personal workspace if necessary, and store the active organisation on the user document.
- The
/auth/afterroute waits until Convex reports the setup is complete, then redirects to the requested page. - Subsequent requests read session data through the helpers listed above. Sessions refresh automatically after 24 hours of activity and expire after seven days of inactivity.
Quick troubleshooting checklist
-
getCurrentSession()returnsnulleven after sign-in
→ Check that/auth/afteris reachable (no ad blockers) and that the Convex deployment has matching BetterAuth env vars. -
useSession()stays in a loading state
→ Confirm the dashboard is wrapped inConvexBetterAuthProviderand that the Convex client URL is configured (NEXT_PUBLIC_CONVEX_URL). -
API route sees no session
→ Ensure you forward headers in tests (const headersList = await headers()) and the route exports the standard cache killers.