Deployment Guide
This is the canonical deployment reference for Sommelier Arena. It covers all services, CLI-first deployment commands, and a full CI workflow example.
Rule of thumb: use Wrangler CLI and
npx partykit deployfor all deployments; avoid the Cloudflare Dashboard except for one-off manual tasks.
Architectureβ
flowchart LR
Browser -->|HTTPS| Pages[Cloudflare Pages - Frontend]
Browser -->|WSS| PartyKit[PartyKit - Cloudflare Workers DO]
Pages --> Proxy[Proxy Worker]
Proxy --> Docs[Docs - Docusaurus on Pages]
PartyKit --> KV[Cloudflare KV - HOSTS_KV]
PartyKit --> SQLite[SQLite - Worker DO storage]
Summary of servicesβ
- Frontend: Cloudflare Pages (front/)
- Backend: PartyKit (Cloudflare Workers Durable Objects) β deployed with
npx partykit deploy - Docs: Cloudflare Pages (docs-site/)
- Proxy Worker: Cloudflare Worker (proxy-worker/index.ts) β deploy with Wrangler
Recommended automated flow (CI)β
- Build frontend artifact (
npm --prefix front run build) and upload to Pages via API or Git push. - Build docs (
npm --prefix docs-site run build) and upload to Pages as a separate Pages project. - After Pages projects are deployed, capture their pages.dev URLs and publish the proxy worker with
DOCS_ORIGINand other env vars injected via Wrangler or the Pages API.
PartyKit (backend)β
Deploy:
# From repo root
npx partykit login # authenticate (first time)
npx partykit deploy
Notes:
- PartyKit publishes Durable Objects to a project-specific domain:
sommelier-arena.<your-username>.partykit.dev. - Ensure
partykit.jsoncontains KV namespace bindings where required.
Cloudflare KV (HOSTS_KV)β
Create a KV namespace and bind it to PartyKit/Worker deployments. Using Wrangler (scriptable):
# Create namespace via Wrangler (requires CF_API_TOKEN)
npx wrangler kv:namespace create "SOMMELIER_HOSTS" --account-id $CF_ACCOUNT_ID
# Wrangler prints the namespace id: add it to partykit.json bindings
Cloudflare Pages (Frontend & Docs)β
Frontend (Pages project)
- Root dir:
front - Build command:
npm run build - Output dir:
dist - Env:
PUBLIC_PARTYKIT_HOST=sommelier-arena.<username>.partykit.dev
Docs (Pages project)
- Root dir:
docs-site - Build command:
npm run build - Output dir:
buildor as configured in docusaurus
Proxy Worker (wrangler)β
Use Wrangler to build & publish the TypeScript proxy worker (recommended):
# wrangler.toml (example)
name = "sommelier-arena-proxy"
main = "proxy-worker/index.ts"
compatibility_date = "2026-03-24"
Publish (example):
npx wrangler whoami
# Deploy with DOCS_ORIGIN injected (replace with actual pages.dev domain)
npx wrangler deploy --var DOCS_ORIGIN=https://sommelier-arena.ducatillon.net
To create a route for /docs* programmatically, use the Cloudflare REST API:
curl -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/workers/routes" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
--data '{ "pattern": "sommelier-arena.ducatillon.net/docs*", "script": "sommelier-arena-proxy" }'
Verificationβ
- Visit
https://sommelier-arena.ducatillon.net/docsand confirm the docs load. - Confirm frontend loads at configured custom domain and connects to PartyKit via
PUBLIC_PARTYKIT_HOST.
Rollbackβ
- Cloudflare Pages: rollback via Pages β Deployments.
- Workers: re-deploy previous bundle via Wrangler with the previous commit.
Notes & CI recommendationsβ
- Do not hard-code
DOCS_ORIGIN; inject via CI or Wrangler--var. - Store
CF_API_TOKEN,CF_ACCOUNT_ID,ZONE_IDin GitHub Actions secrets and use them in CI steps. PUBLIC_PARTYKIT_HOSTis baked into the frontend at build time. Capture the PartyKit URL after deploy and pass it as an env var when runningnpm run buildin CI.
CI/CD deployment workflowβ
The deployment sequence is the same regardless of your hosting provider:
- Deploy backend (PartyKit / Cloudflare Workers) and capture the published host URL.
- Build and deploy docs site.
- Build frontend with
PUBLIC_PARTYKIT_HOSTbaked in, then deploy to your static host. - Deploy proxy worker (if applicable) with the docs origin URL injected.
The example below uses Cloudflare (Pages + Workers + Wrangler). Adapt the deploy commands for your provider β the build steps and environment variable injection are identical.
Other providers: Replace
npx wrangler pages publishwithvercel --prod(Vercel),netlify deploy --prod(Netlify), or your provider's CLI. The PartyKit deploy step (npx partykit deploy) is the same everywhere.
Save as .github/workflows/deploy.yml (manual trigger β adapt for push-to-main):
name: CI/CD Deployment
on:
workflow_dispatch: # run manually; change to push: {branches: [main]} for auto-deploy
jobs:
deploy:
runs-on: ubuntu-latest
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
CF_PAGES_PROJECT_NAME: ${{ secrets.CF_PAGES_PROJECT_NAME }}
ZONE_ID: ${{ secrets.ZONE_ID }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install root dependencies
run: npm ci
# 1. Deploy PartyKit backend and capture the published host
- name: Deploy PartyKit backend
run: |
set -euo pipefail
PARTYKIT_OUTPUT=$(npx partykit deploy 2>&1)
echo "$PARTYKIT_OUTPUT"
PARTYKIT_URL=$(echo "$PARTYKIT_OUTPUT" | grep -oE "https?://[a-zA-Z0-9.-]+\.partykit\.dev" || true)
if [ -z "$PARTYKIT_URL" ]; then echo "PartyKit deploy did not return a URL"; exit 1; fi
PARTYKIT_HOST=${PARTYKIT_URL#https://}
echo "PARTYKIT_HOST=$PARTYKIT_HOST" >> $GITHUB_ENV
# 2. Build and deploy docs site
- name: Build docs
run: npm --prefix docs-site ci && npm --prefix docs-site run build
- name: Deploy docs to Cloudflare Pages
# Replace with: vercel --prod ./docs-site/build OR netlify deploy --prod --dir docs-site/build
run: npx wrangler pages deploy ./docs-site/build --project-name sommelier-arena-docs
# 3. Build frontend with baked-in PartyKit host, then deploy
- name: Build frontend
run: |
npm --prefix front ci
PUBLIC_PARTYKIT_HOST=$PARTYKIT_HOST npm --prefix front run build
- name: Deploy frontend to Cloudflare Pages
# Replace with: vercel --prod ./front/dist OR netlify deploy --prod --dir front/dist
run: npx wrangler pages deploy ./front/dist --project-name $CF_PAGES_PROJECT_NAME
# 4. Deploy proxy worker with docs origin injected (Cloudflare-specific)
- name: Deploy proxy worker
run: |
npx wrangler deploy proxy-worker/index.ts \
--account-id $CF_ACCOUNT_ID \
--var DOCS_ORIGIN=https://sommelier-arena.ducatillon.net
Required GitHub Secrets:
| Secret | Value |
|---|---|
CF_API_TOKEN | Cloudflare API token (Workers:Edit, Pages:Edit, Zone:Edit) |
CF_ACCOUNT_ID | Your Cloudflare account ID |
CF_PAGES_PROJECT_NAME | Pages project name for the frontend (e.g. sommelier-arena) |
ZONE_ID | Zone ID for ducatillon.net (needed only for custom routes) |