Deployment
Taking the three apps to production — Vercel for Next, a Node host for the API.
Both frontends are Next.js App Router apps — deploy each as its own Next project (Vercel is the path of least resistance). DEPLOYMENT.md in the package is the full walkthrough; this page is the outline. The API is a plain Node server — Vercel serverless via the included vercel.json, or Render, Railway, Fly or a VPS running the compiled dist/.
Order of operations
- 01DatabaseCreate the Atlas cluster and user. Allow your hosts' IPs (or
0.0.0.0/0while testing). Put the string inMONGO_URI. - 02API firstDeploy
apps/api. Set every server-side variable from Configuration. Note its public URL. - 03FrontendsDeploy
apps/webandapps/adminwith root directory set to the app folder. Fill each app's.env.production(or the host's environment) and setNEXT_PUBLIC_API_URLto the API URL before the first build. - 04Cross-linkBack on the API, set
CLIENT_URLandADMIN_URLto the deployed frontend origins — that is the CORS allowlist — and redeploy. - 05ProvidersRegister
https://<api>/api/auth/oauth/<provider>/callbackwith each sign-in provider; point the Stripe webhook athttps://<api>/api/payments/webhook. - 06First administratorOpen the dashboard immediately and complete
/setup, or runcreate:admin. - 07Demo store (optional)From a machine whose
.envpoints at the production database and image provider, runpnpm run seed -- --dry-run, thenpnpm run seed.
Vercel — Next apps
| Setting | Value |
|---|---|
| Root directory | apps/web (or apps/admin) |
| Framework | Next.js (auto-detected) |
| Install command | pnpm install --frozen-lockfile from the repo root (Vercel handles the workspace) |
| Environment | Everything in the app's .env.production: NEXT_PUBLIC_API_URL, NEXT_PUBLIC_WEB_URL, NEXT_PUBLIC_ADMIN_URL, INTERNAL_API_KEY, SESSION_*, JWT_EXPIRES_IN |
| Package manager | pnpm 11 — set ENABLE_EXPERIMENTAL_COREPACK=1 so Vercel uses the pinned version |
NEXT_PUBLIC_* URL is missing or still points at localhost — so a mistake shows up at build time, not in front of customers.The API
apps/api/vercel.json builds server.ts with @vercel/node and routes everything to it. Verify a preview deploy actually boots before relying on it — the API is NodeNext ESM with .js import extensions. For a long-running host:
pnpm --filter api run build # swagger.json + dist/
cd apps/api && node dist/server.jsEvery-route-is-dynamic
The storefront layout fetches live sale promos with revalidate: 0, so no page prerenders — not even /privacy. That is a product choice; if you would rather have static pages, set revalidate: 60 on that one fetch in apps/web/src/data/sale-promo.ts.
Run the live check against staging
API_URL=https://api-staging.example.com pnpm --filter api run check:api