Skip to content

Deployment

Utsha Basak edited this page Oct 2, 2026 · 3 revisions

Deployment

The live site, https://bookstorebd-loum.onrender.com, is one Render web service in Singapore. It serves both the API and the built site, and its database is a MongoDB Atlas cluster in the same region.

How a change goes live

  1. Push to master, or merge a pull request into it.
  2. Render builds automatically: it installs both packages and runs npm run build.
  3. It starts npm start, waits for /health to answer, and switches traffic over.

A deploy takes a few minutes. On GitHub at the same time, CI runs the checks, CodeQL scans the code, and a Docker image of the same build is published to GitHub Packages. The service runs on Node.js 24.

Settings

The service is described in render.yaml. Secrets are set on the service's Environment page in Render:

Variable What
MONGO The Atlas connection string
ADMIN_EMAILS Who becomes an administrator
SMTP_USER The Gmail address e-mails come from
GMAIL_CLIENT_ID, GMAIL_CLIENT_SECRET, GMAIL_REFRESH_TOKEN Gmail's web API, used because Render's free plan blocks SMTP
CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET Image hosting
DATA_ENCRYPTION_KEY Encrypts phone numbers, addresses and bKash numbers. Make one with openssl rand -base64 32 and keep a copy: without it those fields cannot be read
TURNSTILE_SITE_KEY, TURNSTILE_SECRET_KEY The bot check on sign-in and sign-up, from Cloudflare Turnstile. Off until both are set
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET Continue with Google: a "Web application" OAuth client whose redirect URI is https://bookstorebd-loum.onrender.com/api/auth/google/callback

Render generates JWT_SECRET. Change settings on the Environment page, not with a Blueprint sync: the service was renamed, so a sync would create a second service.

Things to know

  • Encrypting existing records. After setting DATA_ENCRYPTION_KEY, new and updated records are encrypted. To encrypt the ones already there, run npm run encrypt:existing in server/ once, with the same MONGO and key. Records are read correctly either way.

  • Cold starts. On the free plan the service sleeps after about 15 idle minutes, and the next visit can take up to a minute while it wakes.

  • E-mail goes through Gmail's web API, since SMTP ports are blocked.

  • Separate databases. The team's original MernBookstore must never share this database: at start-up this version drops any index its schemas do not define.

Checking a build before it goes out

export JWT_SECRET=$(openssl rand -hex 48)
docker compose -f docker-compose.prod.yml up --build

This serves a real production build on http://localhost:8080.

Clone this wiki locally