Auth and store resolution
Customer authentication and host-based tenant resolution in the storefront.
The storefront handles two cross-cutting concerns: customer authentication (Better Auth) and tenant resolution (which merchant store to display).
Customer authentication
Setup
Better Auth is configured in lib/auth/server.ts:
| Setting | Value |
|---|---|
| Provider | Email/password only |
| Database | Neon via Drizzle (lib/auth/db.ts, lib/auth/schema.ts) |
| Tables | user, session, account, verification |
| Organization plugin | Not enabled — buyers are not org members |
Auth seam
lib/auth/index.ts exposes getSession() and getCurrentUser() as thin Better Auth wrappers for pages and server actions.
Commerce identity
Logged-in buyers map to customers.id (internal UUID) via customers.auth_user_id. Orders and carts never store Better Auth user.id or email. See Privacy & data.
On sign-up, ensure a commerce customer row exists for the tenant (ensureCustomerForAuthUser).
Protected routes
Account pages check for an active session:
const session = await getSession()
if (!session) redirect('/login')The API resolves the session → customers.id and filters orders server-side.
API routes
Better Auth handler at /api/auth/[...all] handles sign-up, sign-in, sign-out, and session cookies.
Tenant resolution
How it works
lib/tenant.ts → resolveTenantId():
- Custom domain lookup (
tenant_domain, verified) - Subdomain
{slug}.{NEXT_PUBLIC_PLATFORM_DOMAIN}→ organization by slug - Otherwise redirect to the marketing site (
NEXT_PUBLIC_WEB_URL)
There is no fallback tenant.
Resolution priority
| Priority | Source | Example |
|---|---|---|
| 1 | Custom domain (verified) | shop.example.com |
| 2 | Platform subdomain | merchant.prood.app |
| 3 | Unknown host | Redirect to marketing site |
Database lookup
lookupTenantByHost() from @prood/platform (re-exported in lib/tenant-db.ts).
Forwarding to API
The storefront API client forwards x-storefront-host and the session cookie to the Commerce API for tenant-scoped routes.
Development setup
- Run
pnpm db:migrateandpnpm db:seed - With
NEXT_PUBLIC_PLATFORM_DOMAIN=localhost, open http://prood-demo.localhost:3000 (the seededorg_demostore, slugprood-demo)