Skip to content

Cloudflare Pages Deployment

All three Muse & Co portals are hosted on Cloudflare Pages. This guide covers how to deploy each one, run database migrations, and manage secrets.

Portal Deployment Commands

Customer Portal (ncmuse.co)

bash
cd muse-customer
./deploy.sh

The checked-in script is the only supported customer deployment path. It builds, copies Pages Functions, deploys dist/ to production, and verifies the live source commit and APIs.

Admin Portal (staff.ncmuse.co)

bash
cd muse-admin
./deploy.sh

INFO

The admin deployment script owns its build and production safety checks.

Wiki (wiki.ncmuse.co)

bash
cd muse-wiki
pnpm run build
pnpm exec wrangler pages deploy docs/.vitepress/dist --project-name=muse-wiki --branch=main

WARNING

Note the different output directory for VitePress. The wiki build output is at docs/.vitepress/dist, not dist/. Deploying the wrong directory will result in a broken site.

Deployment Summary

PortalProject NameBuild CommandDeploy Directory
Customermuse-customer./deploy.shdist/
Adminmuse-admin./deploy.shdist/
Wikimuse-wikipnpm run builddocs/.vitepress/dist

Database Migrations

Database migrations are SQL files stored in the migrations/ directory. They modify the D1 database schema (create tables, add columns, etc.).

Running a Migration

bash
pnpm exec wrangler d1 execute muse-and-co-db --remote --file=migrations/XXXX_migration_name.sql

WARNING

Always use the --remote flag when running migrations against the production database. Without it, the migration only runs against your local D1 copy and production will not be updated.

Checking Migration Status

To see what tables exist in production:

bash
pnpm exec wrangler d1 execute muse-and-co-db --remote --command="SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"

Migration Best Practices

  • Name migration files with a sequential number prefix: 0001_create_users.sql, 0002_add_events_table.sql
  • Always test migrations locally first (without --remote)
  • Migrations should be idempotent when possible (use CREATE TABLE IF NOT EXISTS, ALTER TABLE ... ADD COLUMN IF NOT EXISTS)
  • Never modify a migration file that has already been run in production -- create a new migration instead

Managing Secrets

Secrets (API keys, credentials, signing keys) are set per-project and are not stored in code.

Setting a Secret

bash
pnpm exec wrangler secret put SECRET_NAME

You will be prompted to enter the value. The secret is encrypted and stored by Cloudflare.

Secrets via Dashboard

Alternatively, set secrets in the Cloudflare dashboard:

  1. Go to dash.cloudflare.com
  2. Select the Pages project
  3. Go to Settings > Environment Variables
  4. Add or update the variable

Required Secrets by Portal

SecretCustomerAdminNotes
STRIPE_SECRET_KEYYesYesStripe API key
STRIPE_WEBHOOK_SECRETYes--Stripe webhook signing secret
AWS_SES_ACCESS_KEYYes--AWS SES credentials for email
AWS_SES_SECRET_KEYYes--AWS SES credentials for email
SESSION_SECRETYesYesCookie signing key

TIP

When rotating a secret, update it in all projects that use it. Use pnpm exec wrangler secret put SECRET_NAME in each project directory.

Custom Domains

Custom domains (ncmuse.co, staff.ncmuse.co, wiki.ncmuse.co) are configured in the Cloudflare dashboard under each Pages project's Custom domains tab. DNS records are managed in the Cloudflare DNS dashboard.

If a custom domain stops working:

  1. Check the Pages project's Custom domains tab for any errors
  2. Verify the DNS record points to the Pages project (should be a CNAME)
  3. Check that the SSL/TLS certificate is active

Deployment Checklist

Before deploying any portal to production:

  • [ ] Code builds successfully through the owning deploy script, or pnpm run build for the wiki
  • [ ] TypeScript has no errors (pnpm exec tsc --noEmit)
  • [ ] Tested locally with pnpm exec wrangler pages dev
  • [ ] Any new database migrations have been run with --remote
  • [ ] Any new secrets have been set via pnpm exec wrangler secret put
  • [ ] Verified the correct deploy directory (dist/ or docs/.vitepress/dist)

Multiple Cloudflare Accounts

If Wrangler reports that more than one account is available, set CLOUDFLARE_ACCOUNT_ID to the account that owns the target Pages project before deploying. Resolve the owner using a read-only project listing. Never hard-code the account ID or an API token in this repository.

Rollback

If a deployment causes issues, you can roll back to a previous deployment in the Cloudflare dashboard:

  1. Go to the Pages project
  2. Find the previous successful deployment in the deployment list
  3. Click on it and select Rollback to this deployment

This instantly reverts the live site to the selected deployment without needing to rebuild or redeploy.


Last updated: August 2026

Internal documentation for Muse & Co staff only