Skip to main content

Environment map

Note on API domains: Render’s free plan does not support custom domains. The api.muzemus.online and stage-api.muzemus.online records only resolve once the backend services are on a paid Render plan (Starter or higher) with the custom domain attached. Until then, the frontend can point at the .onrender.com URLs instead (see Domains).

Deployment architecture

Development workflow

  1. Create branch — feature branches off main (e.g. feat/..., fix/...).
  2. Implement — code changes in backend/ and/or frontend/.
  3. Test locallypnpm dev, pnpm --filter backend test, pnpm --filter frontend test.
  4. Push branch — the ci.yml workflow runs the quality gate on every push/PR.
  5. Deploy to stage — merge the branch into staging (or push directly); deploy.yml migrates the staging database, deploys the staging backend to Render, then the staging frontend to Firebase.
  6. Verify stage — check stage.muzemus.online and the staging health endpoint.
  7. Merge to main — open a PR from staging (or the feature branch) into main.
  8. Productiondeploy.yml migrates the production database, deploys the production backend, frontend, and landing page.

CI/CD pipelines

ci.yml — pull request verification

Runs on every pull request and every push to a non-main/staging branch:
  • Format check, typecheck, lint, build, and unit tests for backend and frontend.

deploy.yml — staging and production

Triggered on push to staging or main. Jobs are gated by the shared quality gate and use GitHub Environments (staging / production) so the same secret names hold environment-specific values. After each backend deploy, the pipeline polls GET /api/v1/health until the service responds.

Backend deployment (Render)

Service configuration

Two services are defined in backend/render.yaml:
  • muze-uniform-backend — production
  • muze-uniform-backend-stage — staging

Build and start commands

Migrations are applied by the CI pipeline before the new backend version is activated, so the database schema is always current when a new version deploys.

Database connections

The backend uses two connection strings against Neon: Staging uses its own Neon database with its own DATABASE_URL / DIRECT_URL (stored in the staging GitHub Environment and the staging Render service).

Frontend deployment (Firebase Hosting)

Firebase sites

The frontend firebase.json declares "site": "muze-mus"; CI passes the explicit site name to firebase deploy --only hosting:<site>.

Landing page

The landing page is a static site in landing/ (plain HTML/CSS, no build step). It is deployed to the muze-mus-landing Firebase site on every push to main.

Deployment checklist

Before deploying:
  • All tests pass locally
  • No TypeScript errors
  • Environment variables are set in the Render dashboard and GitHub Environments
  • Database migrations are compatible with running code
  • No secrets in committed code
After deploying:
  • Backend health check returns 200 (GET /api/v1/health)
  • Frontend loads and login works
  • API calls from the frontend succeed with no CORS errors
  • Staging verified before merging to main

Rollback