Deployment
Deploy Prood applications to Vercel with Neon Postgres, Upstash Redis, and per-app configuration.
Prood deploys as separate Vercel projects sharing a single Neon Postgres database. Each app has its own environment variables and build configuration.
Production URL map (Prood)
| URL | App |
|---|---|
prood.com | Marketing (apps/web) |
dashboard.prood.com | Merchant admin |
api.prood.com | Commerce API |
checkout.prood.com | Hosted checkout |
docs.prood.com | Documentation |
admin.prood.com | Platform super-admin |
{slug}.prood.app | Storefront (wildcard on storefront project) |
shop.client.com | Store custom domain (per merchant) |
Set NEXT_PUBLIC_PLATFORM_DOMAIN=prood.app for storefront subdomain resolution only. Platform services use *.prood.com via each app's BETTER_AUTH_URL and public URL env vars.
Deployment architecture
Drag to pan · Scroll to zoom
Prerequisites
- Vercel account with team/project access
- Neon Postgres provisioned (Vercel marketplace integration)
- Upstash Redis provisioned (Vercel marketplace integration)
- Payment provider accounts (Stripe, Easypay, and/or Ifthenpay)
- Domain names configured
Step 1 — Database setup
Run migrations against the production database once:
# Set DATABASE_URL to production Neon connection string
DATABASE_URL="postgresql://..." pnpm db:setupThis creates commerce schema + RLS + seed data, and pushes auth tables.
Step 2 — Deploy the API
The API must be deployed first — other apps depend on it.
| Setting | Value |
|---|---|
| Framework | Next.js |
| Root directory | apps/api |
| Build command | cd ../.. && pnpm build --filter=api |
| Node.js version | 24 |
Environment variables
DATABASE_URL=postgresql://...
BETTER_AUTH_SECRET=<openssl rand -base64 32>
BETTER_AUTH_URL=https://api.prood.com
AUTH_COOKIE_DOMAIN=.prood.com
NEXT_PUBLIC_DASHBOARD_URL=https://dashboard.prood.com
API_PUBLIC_URL=https://api.prood.com
COMMERCE_CURRENCY=EUR
DEFAULT_PAYMENT_PROVIDER=stripe
STORAGE_PROVIDER=vercel-blob
BLOB_READ_WRITE_TOKEN=...
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
CHECKOUT_API_SECRET=<shared secret>
INTEGRATION_ENCRYPTION_KEY=<openssl rand -base64 32>
RESEND_API_KEY=re_...
RESEND_FROM_EMAIL="Prood <noreply@prood.com>"
NEXT_PUBLIC_PLATFORM_DOMAIN=prood.appStep 3 — Deploy the storefront
| Setting | Value |
|---|---|
| Root directory | apps/storefront |
| Build command | cd ../.. && pnpm build --filter=storefront |
Environment variables
DATABASE_URL=postgresql://...
COMMERCE_API_URL=https://api.prood.com/v1
BETTER_AUTH_SECRET=<same as API>
BETTER_AUTH_URL=https://storefront.example.com
CHECKOUT_URL=https://checkout.prood.com
CHECKOUT_API_SECRET=<same as API>
RESEND_API_KEY=re_...
RESEND_FROM_EMAIL="Prood <noreply@merchant-domain.com>"
DEFAULT_TENANT_ORG_ID= # leave empty for multi-tenant
NEXT_PUBLIC_PLATFORM_DOMAIN=prood.appCustom domains are added per-merchant via the dashboard Domains page.
Step 4 — Deploy the checkout app
| Setting | Value |
|---|---|
| Root directory | apps/checkout |
| Build command | cd ../.. && pnpm build --filter=checkout |
Environment variables
UPSTASH_REDIS_REST_URL=https://...
UPSTASH_REDIS_REST_TOKEN=...
CHECKOUT_API_SECRET=<same as API>
CHECKOUT_URL=https://checkout.prood.com
COMMERCE_API_URL=https://api.prood.com/v1
STOREFRONT_URL=https://storefront.example.com
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_SECRET_KEY=sk_live_...
# Payment provider keys as fallbacksConfigure payment webhooks to: https://checkout.prood.com/api/webhooks/{provider}/{orgId}
Step 5 — Deploy the dashboard
| Setting | Value |
|---|---|
| Root directory | apps/dashboard |
| Build command | cd ../.. && pnpm build --filter=dashboard |
Environment variables
DATABASE_URL=postgresql://...
COMMERCE_API_URL=https://api.prood.com/v1
BETTER_AUTH_SECRET=<same as API>
NEXT_PUBLIC_AUTH_URL=https://api.prood.com
INTEGRATION_ENCRYPTION_KEY=<same as API>
VERCEL_TOKEN=<for domain provisioning>
STOREFRONT_VERCEL_PROJECT_ID=<storefront project ID>
VERCEL_TEAM_ID=<team ID>
NEXT_PUBLIC_PLATFORM_DOMAIN=prood.appDashboard auth (sign-in, sign-up, organization ops) is issued by apps/api but proxied through the dashboard at /api/auth/* so session cookies stay on the dashboard origin. This is required on separate *.vercel.app preview URLs; with custom domains, set AUTH_COOKIE_DOMAIN=.prood.com on the API project so cookies are also shared across subdomains.
Step 6 — Deploy the platform admin
| Setting | Value |
|---|---|
| Root directory | apps/admin |
| Build command | cd ../.. && pnpm build --filter=admin |
Environment variables
DATABASE_URL=postgresql://...
BETTER_AUTH_SECRET=<same as API>
BETTER_AUTH_URL=https://api.prood.com
NEXT_PUBLIC_AUTH_URL=https://api.prood.com
NEXT_PUBLIC_ADMIN_URL=https://admin.prood.com
ADMIN_USER_IDS=<comma-separated Better Auth user IDs>apps/admin is for platform operations only. Keep it on a restricted domain and set ADMIN_USER_IDS before exposing it outside local development.
Step 7 — Deploy docs and web
| App | Root directory | Notes |
|---|---|---|
docs | apps/docs | Runs sync:openapi at build time |
web | apps/web | Static marketing site |
# Docs
NEXT_PUBLIC_DOCS_URL=https://docs.prood.com
# Web
NEXT_PUBLIC_WEB_URL=https://prood.com
NEXT_PUBLIC_DOCS_URL=https://docs.prood.com
NEXT_PUBLIC_DASHBOARD_URL=https://dashboard.prood.com
NEXT_PUBLIC_API_URL=https://api.prood.com
NEXT_PUBLIC_STOREFRONT_URL=https://demo-store.prood.appShared secrets
These must be identical across projects:
| Secret | Apps |
|---|---|
BETTER_AUTH_SECRET | API, dashboard (SSR session validation), storefront |
CHECKOUT_API_SECRET | API, storefront, checkout |
INTEGRATION_ENCRYPTION_KEY | API, dashboard |
DATABASE_URL | API, storefront, dashboard, admin |
Caching in production
The storefront uses Next.js Cache Components:
- Catalog pages:
'use cache'with per-tenant tags - Cart/checkout/account: dynamic (cookie/session dependent)
- Cache invalidation: dashboard product updates trigger
revalidateTagvia API
Production checklist
- Strong secrets generated for
BETTER_AUTH_SECRET,CHECKOUT_API_SECRET,INTEGRATION_ENCRYPTION_KEY -
DEFAULT_TENANT_ORG_IDunset (multi-tenant) or set (single-tenant) -
NEXT_PUBLIC_PLATFORM_DOMAINconfigured - Upstash Redis provisioned for checkout
- Payment webhooks pointed to checkout domain
- Resend sender uses a verified production domain
-
pnpm db:setuprun against production database - Custom domains verified for at least one merchant
- SSL certificates active on all domains
-
ADMIN_USER_IDSset before deployingapps/admin