Deployment
Where each BabyMart app is hosted, how to configure it for production, and the checklist to run before going live.
Every web app deploys from the same repository. The storefront, admin dashboard and API each run as their own Vercel project. MongoDB Atlas holds the data, and the docs are a plain static site that any host can serve.
flowchart LR
subgraph Vercel
W["Storefront<br/>apps/web"]
A["Admin<br/>apps/admin"]
API["API<br/>apps/api serverless"]
end
W -->|NEXT_PUBLIC_API_URL| API
A -->|VITE_NEXT_PUBLIC_API_URL| API
M[Mobile app] --> API
API --> DB[(MongoDB Atlas)]
ST[Stripe] -->|webhooks| W
ST -->|webhooks| API
D["Docs<br/>apps/docs/dist"] -.static.- CDN[Any static host]
Storefront (apps/web)
Section titled “Storefront (apps/web)”- In Vercel, import the repository and set Root Directory to
apps/web. The root vercel.json sets the install command topnpm install, so the workspace packages are linked. - Add the storefront’s variables from
Environment variables.
Point
NEXT_PUBLIC_API_URLandAPI_ENDPOINTat the production API, and setNEXT_PUBLIC_SITE_URLto the storefront’s own domain. - Deploy. After that,
.github/workflows/deploy.ymlredeploys on every push tomainthat touchesapps/web, once theVERCEL_ORG_ID,VERCEL_PROJECT_IDandVERCEL_TOKENrepository secrets are set.
Admin dashboard (apps/admin)
Section titled “Admin dashboard (apps/admin)”apps/admin/vercel.json already sets everything up. It
installs from the monorepo root, runs
pnpm turbo run build --filter=@babyshop/admin, serves dist, rewrites
every path to index.html (so React Router can handle deep links), and adds
security headers. Create a Vercel project with Root Directory
apps/admin, then add VITE_NEXT_PUBLIC_API_URL and the VITE_FIREBASE_*
keys.
API (apps/api)
Section titled “API (apps/api)”apps/api/vercel.json builds server.ts with
@vercel/node and sends every path to it. server.ts exports the Express
app, and when NODE_ENV=production it skips app.listen(), so Vercel calls
the exported app as a serverless function.
- Create a Vercel project with Root Directory
apps/api. - Set
NODE_ENV=production,MONGO_URI, aJWT_SECRETof at least 32 characters,CLIENT_URL(the storefront domain) andADMIN_URL(the admin domain). The last two make up the CORS allowlist. - Add the Stripe, SSLCommerz, Cloudinary/S3, SMTP and OAuth variables you
use, and set
SERVER_URLto the API’s public URL so SSLCommerz callbacks reach it.
MongoDB Atlas
Section titled “MongoDB Atlas”Create a cluster and a database user, and copy the connection string into
MONGO_URI. Vercel functions don’t have fixed IP addresses, so the Atlas
network access list must allow 0.0.0.0/0. Make up for that with a strong,
unique database password. Seed the catalogue with
Demo data if you want a starting point.
Stripe in live mode
Section titled “Stripe in live mode”- Switch the dashboard to live mode and use live keys everywhere: the publishable key in the storefront and mobile app, and the secret key in the storefront and the API.
- Add two webhook endpoints, one per receiver, and copy each signing secret
into that app’s
STRIPE_WEBHOOK_SECRET:https://<storefront>/api/stripe-webhook:checkout.session.completed,checkout.session.async_payment_succeededhttps://<api>/api/payments/webhook:checkout.session.completed,payment_intent.succeeded
- Place one real order and check that it becomes
paid.
The payment flow is explained on Payments.
Docs (apps/docs)
Section titled “Docs (apps/docs)”pnpm --filter @babyshop/docs buildThis writes a static site to apps/docs/dist/. Serve it from Vercel
(Root Directory apps/docs, output dist), Netlify, Cloudflare Pages or
GitHub Pages. Set site in apps/docs/astro.config.mjs to the public URL to
turn on the sitemap.
Mobile app
Section titled “Mobile app”Before a store build, change the release API URL in
apps/mobile/src/config/environment.ts, the Stripe key in App.tsx and the
Google client IDs in src/services/googleAuthService.ts. Also replace the
iOS bundle identifier: it is still the template value
org.reactjs.native.example.*, while Android uses com.babymart.app. See
Mobile app.
Go-live checklist
Section titled “Go-live checklist”-
JWT_SECRETis a long random string (32+ characters, enforced in production). - Every API URL points at production, not
localhost:NEXT_PUBLIC_API_URL,API_ENDPOINT,VITE_NEXT_PUBLIC_API_URL, and the mobile release URL. -
CLIENT_URLandADMIN_URLon the API match the real domains (CORS). - Stripe live keys and live webhook secrets are set, and a real order reached
paid. -
SSLCOMMERZ_IS_LIVE=trueif you take SSLCommerz payments. - Firebase → Authentication → Authorized domains includes the storefront and admin domains.
- Demo and read-only accounts (
preview@gmail.com,demo@gmail.com,test@gmail.com) are removed or have new passwords. - Any
.envfile that was ever committed is removed from git, and every secret in it is rotated. - Images are re-uploaded to your own Cloudinary account (
pnpm reimage), and demo photos are replaced with ones you have the rights to. -
apps/web/public/robots.txtand the sitemap use your domain.next-sitemap.config.jsholds the site URL. - The admin CSP
connect-srcincludes your API’s origin.