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
./deploy.sh

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.

The script builds the wiki, checks for a clean worktree containing current main, and uses the monorepo's pinned Wrangler to deploy the wiki project from its own directory. Install the wiki and admin workspace dependencies before running it.

Deployment Summary ​

PortalProject NameBuild CommandDeploy Directory
Customermuse-customer./deploy.shdist/
Adminmuse-admin./deploy.shdist/
Wikimuse-wiki./deploy.shdocs/.vitepress/dist

Database Migrations ​

Database migrations are SQL files in muse-customer/migrations/ (the staff portal shares the same D1 database). They modify the D1 database schema (create tables, add columns, etc.).

Running a Migration ​

bash
cd muse-customer
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 pages secret put SECRET_NAME --project-name=muse-customer   # or muse-admin

wrangler secret put (without pages) is the Workers command and does not reach a Pages project.

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_KEYYes--Stripe API key
STRIPE_WEBHOOK_SECRETYes--Stripe webhook signing secret
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEYYesYesAWS SES credentials for email
AWS_SES_FROM, AWS_REGIONYesYesSES sender and region
JWT_SECRETYesYesSigns staff and customer session tokens
CRON_SECRETYesYesShared with the cron workers; must match on both sides
POS_SYNC_SECRET--YesMachine token for the FrontTab sync (muse-fronttab-sync)
PHONE_SHIFT_API_KEYYes--Bearer key for GET /api/phone/on-shift and the /api/phone/staff staff-menu and /api/phone/staff/list directory endpoints; must equal the phone engine's SHIFT_API_KEY. Set with npx wrangler pages secret put PHONE_SHIFT_API_KEY --project-name=muse-customer

TIP

When rotating a secret, update it in all projects that use it. Use pnpm exec wrangler pages secret put SECRET_NAME --project-name=<project> for each project.

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 pages 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