Cloudflare Dashboard Setup
Step-by-step guide for setting up Sommelier Arena through the Cloudflare web UI. Note: Wrangler CLI is required to publish the TypeScript proxy worker (proxy-worker/index.ts) because the Cloudflare Dashboard editor cannot build TypeScript or run the project's build step. Keep wrangler available locally or in CI (see examples below).
1. Create the KV namespace (precise steps)β
Goal: create a Cloudflare KV namespace and bind it to the worker as HOSTS_KV so the backend can store cross-session host lists.
Two equivalent ways: (A) Cloudflare Dashboard (GUI) β easiest; (B) Wrangler CLI β scriptable. Choose one.
A) Dashboard (GUI) β recommended
- Open https://dash.cloudflare.com and sign in to the Cloudflare account that will host the Pages / Workers.
- Select the account (top-left) and click Workers & Pages in the left nav.
- Click the KV tab near the top.
- Click Create namespace (top-right).
- For the Name enter: SOMMELIER_HOSTS and click Add.
- The new namespace will appear in the list. Click it and copy the shown Namespace ID value.
B) Wrangler CLI (scriptable)
-
Install wrangler if you don't have it:
npm install -g wrangler(or usenpx wrangler). -
Authenticate:
npx wrangler loginand follow the browser flow. -
Create the namespace (returns an ID):
npx wrangler kv:namespace create "SOMMELIER_HOSTS"
The CLI will print the Namespace ID; copy it.
Bind the namespace to the project
-
The repository contains
partykit.jsoncommitted in the repo. This file should include the KV binding forHOSTS_KVwith the Namespace ID already populated. -
Local developers who need to perform a manual deploy (rare) can edit
partykit.jsondirectly or use a local copy. If you do modifypartykit.jsonlocally, ensure you intend to commit changes back to the repo.
CI & deploy notes
- This repo uses two GitHub Actions workflows:
docs-ci.ymlβ docs-only workflow. Runs when files underdocs-site/**change. It builds the Docusaurus site and uploads thedocs-site/buildartifact.app-ci.ymlβ app-focused workflow. Responsible for E2E, PartyKit deploy, and Proxy Publication with Wrangler. It is triggered on pushes tomain.
Example app-ci.yml deploy snippet (no template manipulation):
- name: Deploy PartyKit
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: |
npm ci
npx partykit deploy
- name: Publish proxy worker via Wrangler (required for TypeScript)
if: ${{ secrets.CF_API_TOKEN != '' }}
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: |
# Ensure wrangler is available and authenticated (CI should provide CF_API_TOKEN)
npx wrangler whoami || true
# Recommended: add a wrangler.toml to the repo and run 'npx wrangler deploy'.
# Pass DOCS_ORIGIN to the worker via --var (example uses an env var set earlier in the job)
npx wrangler deploy proxy-worker/index.ts --var DOCS_ORIGIN=$DOCS_ORIGIN
Manual local deploys (rare)
If you must deploy from a local machine, edit partykit.json directly in the repo root (or use a local copy) and run:
cd /path/to/SommelierArena
# edit partykit.json as needed (e.g. set HOSTS_KV id)
npx partykit deploy
Where npx partykit deploy runs (locally vs CI)
- CI (recommended): The preferred approach is to let
app-ci.ymlperformnpx partykit deployin GitHub Actions after tests pass. The app workflow usespartykit.json. - Locally (for manual deploys): Run from the repository root where
partykit.jsonlives:
cd /path/to/SommelierArena
cp partykit.json.template partykit.json
# Edit partykit.json and replace PASTE_NAMESPACE_ID_HERE with your Namespace ID
npx partykit deploy
Before running deploy (CI or local)
- Ensure the KV namespace exists (you created it earlier and have its Namespace ID).
- Ensure you are authenticated with Cloudflare locally (
npx wrangler login) or have a validCF_API_TOKENstored in GitHub Secrets for CI.
Why this order matters
- The KV namespace must exist before deploy so PartyKit can bind the namespace ID to
HOSTS_KVduring deployment. partykit.jsoncontains the binding information used by the deploy step. The CI flow injects the Namespace ID into the template at runtime so the repo never contains environment-specific files.
Verification
- After
npx partykit deploysucceeds (CI or local), open Cloudflare Dashboard β Workers & Pages β your Worker and confirm the bindingHOSTS_KVappears under Settings / Variables & Bindings. - In CI logs you should see the deploy command run; inspect output for binding confirmation or errors.
Troubleshooting
- If
npx partykit deployerrors with authentication issues, runnpx wrangler loginand retry. - If you accidentally created the namespace in a different Cloudflare account, delete and recreate it in the intended account, then update
partykit.jsonand re-deploy.
Security note
- Do not commit secrets or account tokens to git. The namespace ID is non-secret (safe to commit), but API keys or account tokens must not be committed.
2. Deploy the frontend to Cloudflare Pagesβ
Workers & Pages β Create application β Pages
- Click Workers & Pages β Create application β Pages tab β Connect to Git
- Authorize Cloudflare to access your GitHub account if prompted
- Select your repository β click Begin setup
- Configure:
- Project name:
sommelier-arena - Production branch:
cloudflare-migration - Root directory:
front - Framework preset: None (Astro builds to static)
- Build command:
npm run build - Build output directory:
dist
- Project name:
- Click Environment variables (advanced) β Add variable:
- Variable name:
PUBLIC_PARTYKIT_HOST - Value: the PartyKit project URL (see note below). This must be the hostname only (no protocol or trailing slash), for example:
sommelier-arena.<your-account>.partykit.dev.
- Variable name:
- Click Save and Deploy
Note about PUBLIC_PARTYKIT_HOST and CI
-
In this repository
app-ci.ymlrunsnpx partykit deployas part of the CI deploy job. That command produces the PartyKit project URL (the value you must set forPUBLIC_PARTYKIT_HOST). The simplest ways to ensure the Pages project receives the correct value are:-
Manual one-time: run
npx partykit deploylocally, copy the printed URL, and setPUBLIC_PARTYKIT_HOSTin the Pages project's Environment variables. Then trigger a redeploy. -
Automated CI (recommended): have the app CI capture the PartyKit URL from the deploy output and update the Pages project's environment variable before or after the Pages build. Example capture snippet (add to app-ci.yml before or after the partykit deploy step):
-
# Capture the PartyKit URL produced by the deploy
PARTYKIT_URL=$(npx partykit deploy 2>&1 | grep -Eo 'https?://[^ ]+partykit.dev' | head -n1)
# Normalise to hostname only (strip protocol)
PUBLIC_PARTYKIT_HOST=${PARTYKIT_URL#https://}
echo "PUBLIC_PARTYKIT_HOST=$PUBLIC_PARTYKIT_HOST"
To apply PUBLIC_PARTYKIT_HOST to Cloudflare Pages automatically you can either:
- Build the frontend in CI using the captured
PUBLIC_PARTYKIT_HOSTand then publish the built static site to Pages. This approach avoids mutating Pages project environment variables: the CI build bakes the correct host into the static assets and then runsnpx wrangler pages publishto deploy them. Required secrets:CF_API_TOKENandCF_PAGES_PROJECT_NAME.
CI example (build + publish with wrangler):
- name: Deploy PartyKit
if: ${{ secrets.CF_API_TOKEN != '' }}
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: |
PARTYKIT_OUTPUT=$(npx partykit deploy 2>&1)
echo "$PARTYKIT_OUTPUT"
PARTYKIT_URL=$(echo "$PARTYKIT_OUTPUT" | grep -Eo 'https?://[^ ]+partykit.dev' | head -n1 || true)
if [ -n "$PARTYKIT_URL" ]; then
HOSTNAME=${PARTYKIT_URL#https://}
echo "PUBLIC_PARTYKIT_HOST=$HOSTNAME" >> $GITHUB_ENV
fi
- name: Build frontend and publish to Pages
if: ${{ secrets.CF_API_TOKEN != '' && secrets.CF_PAGES_PROJECT_NAME != '' }}
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: |
npm --prefix front ci
PUBLIC_PARTYKIT_HOST=$PUBLIC_PARTYKIT_HOST npm --prefix front run build
npx wrangler pages publish front/dist --project-name ${{ secrets.CF_PAGES_PROJECT_NAME }} --branch main
- Or, if you prefer to update the Pages project environment variable (
PUBLIC_PARTYKIT_HOST) directly via the Pages API, add theCF_ACCOUNT_IDandCF_PAGES_PROJECT_NAMEsecrets and use the Pages REST API to upsert the variable. This requires additional Pages API permissions for theCF_API_TOKEN. The build+publish approach is simpler and idempotent.
See the CI snippets above for a working example.
To apply PUBLIC_PARTYKIT_HOST to Cloudflare Pages automatically you can:
-
Use the Cloudflare Pages REST API to set environment variables for the project (requires CF_API_TOKEN and the account + project identifiers). Add a CI step that calls the Pages API to update or create the
PUBLIC_PARTYKIT_HOSTvariable and then trigger a Pages redeploy; or -
Build the frontend within the same CI job after capturing
PUBLIC_PARTYKIT_HOSTby invoking the front build using the env var in-process (e.g.PUBLIC_PARTYKIT_HOST=$PUBLIC_PARTYKIT_HOST npm --prefix front run build) and then deploy that built artifact to Pages via the Pages Deployments API (more complex). -
If you want the repository to perform this automatically, I can add a small, safe CI step that:
- Captures the PartyKit URL (as above)
- Calls the Pages API to upsert
PUBLIC_PARTYKIT_HOSTusingCF_API_TOKEN+CF_ACCOUNT_ID+CF_PAGES_PROJECT_NAME(these need adding as GitHub Secrets) - Optionally triggers a Pages redeploy or builds the front artifact inline and uploads via the Pages Deployments API.
-
Let me know if you want me to implement the automated Pages env var update (I will add the snippet to
app-ci.ymland document the required secrets).
3. Deploy the docs to Cloudflare Pagesβ
Repeat Step 2 with different settings:
- Project name:
sommelier-arena-docs - Root directory:
docs-site - Build command:
npm run build - Build output directory:
build - No environment variables needed
4. Add a custom domainβ
Cloudflare Pages β sommelier-arena β Custom domains
- Click your
sommelier-arenaPages project - Click Custom domains tab
- Click Set up a custom domain
- Enter:
sommelier-arena.ducatillon.netβ click Continue - Cloudflare will add the required DNS CNAME automatically (since
ducatillon.netis already managed on Cloudflare) - Wait for Active status (usually < 1 minute)
5. Deploy the proxy Worker β step-by-step (recommended)β
This section documents a minimal, repeatable flow to publish the proxy Worker that routes /docs/* to the Docusaurus Pages site. Two flows are shown: Manual (wrangler) and CI (non-interactive) β CI (app-ci.yml) is recommended for production.
Prerequisites
CF_API_TOKENstored in GitHub Secrets (scoped Account token with Workers:Edit and Zones:Edit).CF_HOSTS_NAMESPACE_IDin GitHub Secrets only if you want CI to inject the KV namespace intopartykit.json(optional; the worker itself does not need this unless it references KV).- Cloudflare Account ID and Zone ID (for API route creation; optional if using the Dashboard GUI).
proxy-worker/index.tspresent in the repo (it is).
Setting DOCS_ORIGIN (Manual one-shot β recommended)
DOCS_ORIGIN is the full origin (protocol + host) where the docs Pages project is served (for example: https://sommelier-arena.ducatillon.net). In most cases this is a one-time value created when you first deploy the Docusaurus site, so the simplest, lowest-risk approach is to set it manually once.
Manual one-shot steps:
-
Deploy the Docusaurus docs to Cloudflare Pages (see Section 3 β Deploy the frontend to Cloudflare Pages):
- Workers & Pages β Create application β Pages β Connect to Git
- Project name:
sommelier-arena-docs - Root directory:
docs-site - Build command:
npm run build - Output directory:
build - Save and deploy.
-
Copy the Pages URL (pages.dev):
- After deployment, open the Pages project Overview or Settings β Domains.
- Copy the default domain, e.g.
https://sommelier-arena.ducatillon.net.
-
Set DOCS_ORIGIN in the Worker (one-time):
-
Recommended: set
DOCS_ORIGINin the Worker using the Dashboard Variables & Bindings after you have published the worker with Wrangler. Note: publishing the TypeScript worker requires Wrangler because the Dashboard cannot build TypeScript projects.- Cloudflare Dashboard β Workers & Pages β Workers β select
sommelier-arena-proxyβ Settings β Variables & Bindings β Add variable:- Name:
DOCS_ORIGIN - Value: the pages.dev URL you copied (include protocol)
- Name:
- Save. No git changes required.
- Cloudflare Dashboard β Workers & Pages β Workers β select
-
Option B (one-time wrangler deploy):
- Create a temporary local copy of
proxy-worker/index.tsand replace the placeholderDOCS_ORIGIN_PLACEHOLDERwith the Pages URL. - Run:
npx wrangler deploy temp/proxy-worker/index.ts(or use awrangler.tomlandnpx wrangler deploy). - This publishes the worker with the correct DOCS_ORIGIN baked in. Do not commit the temporary file.
- Create a temporary local copy of
-
Verification
- Open https://sommelier-arena.ducatillon.net/docs and confirm the docs site loads.
- Inspect the worker in Dashboard: Settings β Variables & Bindings should show DOCS_ORIGIN (if set via Dashboard).
Rationale
- DOCS_ORIGIN is rarely changed. A manual one-shot avoids added CI complexity and keeps the deploy footprint minimal. If you later prefer automation, a small workflow_dispatch job can be implemented to run on-demand.
A) Manual (local) publish β check/create worker, set DOCS_ORIGIN, then add route
- Inspect whether
sommelier-arena-proxyalready exists
- Dashboard β Workers & Pages β Workers β search for
sommelier-arena-proxy. - If present: proceed to step 2 (Set DOCS_ORIGIN and add route).
- If not present: create the worker in step 1.
- Create / publish the worker (two options)
Recommended (Wrangler, reproducible):
cd /path/to/SommelierArena
npx wrangler whoami # verify auth
# Quick one-shot (manual): set DOCS_ORIGIN to the pages URL you copied
npx wrangler deploy proxy-worker/index.ts --var DOCS_ORIGIN=https://sommelier-arena.ducatillon.net
- Wrangler compiles TypeScript and publishes the named worker; this is the recommended, reproducible path.
Dashboard UI (editor):
- The Dashboard editor does not run a build and therefore cannot compile TypeScript projects. If you have a plain compiled JS worker you may paste it into the editor, but for this repository's TypeScript
proxy-worker/index.tsuse Wrangler (recommended). To use the Dashboard with this repo you'd need to compile/bundle to plain JS locally and paste that JS into the editor (not recommended).
- Set DOCS_ORIGIN (one-time)
Dashboard (recommended):
- Dashboard β Workers & Pages β Workers β select
sommelier-arena-proxyβ Settings β Variables & Bindings β Add variable- Name:
DOCS_ORIGIN - Value:
https://sommelier-arena.ducatillon.net(include protocol)
- Name:
- Save.
Alternative (one-time local publish):
- Make a temp copy of
proxy-worker/index.ts, replaceDOCS_ORIGIN_PLACEHOLDERwith your Pages URL, and publish that file with Wrangler; do not commit the temp file.
- Add the route (if missing)
- Dashboard β Workers & Pages β Workers β select
sommelier-arena-proxyβ Triggers / Routes β Add route- Route:
sommelier-arena.ducatillon.net/docs* - Zone:
ducatillon.net
- Route:
- Save.
- Verify
- Visit https://sommelier-arena.ducatillon.net/docs β docs should load.
- Confirm in Dashboard: Worker β Settings shows DOCS_ORIGIN and Triggers shows the route.
- Quick check:
curl -I https://sommelier-arena.ducatillon.net/docs
Troubleshooting
- If
npx wrangler deploydoesn't create the worker, ensurenpx wrangler whoamireturns the correct account and your CF API token has Workers:Edit permission. - If the worker exists but route is missing, add the route via Dashboard or create it programmatically (requires
CF_ZONE_ID). - Dashboard variable bindings are recommended for DOCS_ORIGIN to avoid committing environment-specific values.
B) Non-interactive (CI) publish β recommended for production
Use the app-ci.yml workflow to publish the worker automatically after E2E tests pass. The workflow must have CF_API_TOKEN in repository secrets.
Example job step (YAML snippet):
- name: Publish proxy worker via Wrangler
if: ${{ secrets.CF_API_TOKEN != '' }}
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: |
# Ensure wrangler can run non-interactively in CI and authenticate using CF_API_TOKEN
# Recommended: commit a wrangler.toml and run 'npx wrangler deploy' from the repo root
npx wrangler deploy proxy-worker/index.ts --var DOCS_ORIGIN=$DOCS_ORIGIN
Notes for CI:
- Wrangler reads
CF_API_TOKENfrom the environment for non-interactive auth. Nonpx wrangler loginis needed in CI. - If you need to create/update routes from CI, use the Cloudflare REST API (requires
CF_API_TOKENandZONE_ID) or manage routes inwrangler.tomland letnpx wrangler deployapply them.
C) Programmatic route creation (optional)
Use the Cloudflare REST API to add the /docs* route for your zone. Example (replace placeholders):
CF_API_TOKEN=...
ZONE_ID=ducatillon_net_zone_id
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"}'
You can also automate route creation from CI. Add CF_ZONE_ID (the Zone ID for ducatillon.net) as a GitHub secret, then add a step to app-ci.yml after the worker publish step:
- name: Create /docs route (Cloudflare API)
if: ${{ secrets.CF_API_TOKEN != '' && secrets.CF_ZONE_ID != '' }}
env:
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
ZONE_ID: ${{ secrets.CF_ZONE_ID }}
run: |
set -euo pipefail
curl -s -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"}' \
| jq -r '.success'
echo "Route creation finished"
Notes:
- Secret names used:
CF_API_TOKEN(already required),CF_ZONE_ID(new β set to the Zone ID forducatillon.net). - If you prefer to manage routes in
wrangler.toml,npx wrangler deploycan apply them as well (see Wrangler docs).
D) Verification steps (after publish + route)
- Browser test: open https://sommelier-arena.ducatillon.net/docs β pages should load and assets must be served.
- Curl test (checks HTTP 200 and content-type):
curl -I https://sommelier-arena.ducatillon.net/docs | head -n 10
# Expect: HTTP/2 200, Content-Type: text/html
-
Worker logs: Cloudflare Dashboard β Workers β View logs (or use
wrangler tailwithCF_API_TOKENto stream logs locally). -
CI logs: verify the
npx wrangler deploystep succeeded and API output shows the correct script name.
E) Rollback guidance
- Cloudflare does not expose a one-click "rollback" for Workers. To rollback:
- Identify the previous commit/tag that contained the last-known-good worker code.
- In CI or locally,
git checkout <good-commit>and runnpx wrangler deploy proxy-worker/index.ts(or use awrangler.tomlandnpx wrangler deploy). - Alternatively, if using a CI artifact store, republish the saved artifact from the previous successful run.
F) Bindings & Secrets for the Worker
- If the proxy worker requires any KV or other bindings, declare them in
wrangler.tomlor in the Dashboard's Variables & Bindings for the worker. Document bindings as needed.
G) Security & minimal perms
- Use a scoped
CF_API_TOKENwith minimal permissions: Account β Workers Scripts: Edit and Zone β Zone:Edit (or specific zone permissions). Do not use Global API keys in CI.
H) Example troubleshooting checklist
- 403 or 401 on publish β verify
CF_API_TOKENpermissions and that the token is set in GitHub Secrets. - 404 on route β verify route pattern (
sommelier-arena.ducatillon.net/docs*) and that it is attached tosommelier-arena-proxy. - Broken assets / CORS issues β ensure Pages site is accessible directly and worker forwards requests correctly.
Workers & Pages β Create application β Worker
There are two repeatable ways to deploy the proxy worker from the repository: (A) Cloudflare Dashboard (manual GUI) β already documented above; (B) Wrangler CLI (scriptable). The Wrangler approach is shown here so deployments can be automated from your machine or CI.
Prerequisites (for CLI)
wrangleravailable via npx (no global install required): npx wrangler- A Cloudflare API token (recommended) or global API key with permissions to edit Workers and Routes
- Your Cloudflare Account ID (can be found on the Cloudflare dashboard)
A) Publish the worker script with Wrangler (CLI)
-
Authenticate with Cloudflare if not already authenticated:
npx wrangler login
This opens a browser to authenticate and grants wrangler access to your account.
-
From the repository root, publish the worker script located at
proxy-worker/index.tsand give it the namesommelier-arena-proxy:cd /Users/mac-FDUCAT18/Workspace/FDUCAT/SommelierArena npx wrangler deploy proxy-worker/index.ts
Successful output will include the worker URL and script name.
B) Create a route for the worker (two options)
Option 1 β Dashboard (manual, reliable)
- After publishing, go to Cloudflare Dashboard β Workers & Pages β your Worker β Triggers and add a route with:
- Route:
sommelier-arena.ducatillon.net/docs* - Zone:
ducatillon.net
- Route:
Option 2 β API (scriptable)
- Use the Cloudflare REST API to create a route programmatically. You need:
- CF_ACCOUNT_ID (your Cloudflare account id)
- CF_API_TOKEN (a scoped API token with
Workers:EditandZone:Editon the target zone)
Example (replace placeholders):
# Create a route that sends /docs* to the worker
CF_ACCOUNT_ID=your_account_id
CF_API_TOKEN=your_api_token
ZONE_ID=ducatillon_net_zone_id # find this on Cloudflare dashboard under the domain
WORKER_SCRIPT_NAME=sommelier-arena-proxy
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"}'
# Verify the route was created (response.ok === true)
# Example: list routes for the zone and grep for the pattern
curl -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/workers/routes" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json" | jq '.result[] | select(.pattern=="sommelier-arena.ducatillon.net/docs*")'
# If you prefer to bind routes to a Worker via wrangler TOML, you can also manage routes in wrangler.toml and use `npx wrangler deploy` from the worker directory. See Wrangler docs for `routes` configuration.
---
## 6. Verify DNS records
**ducatillon.net β DNS**
1. In the Cloudflare dashboard, click `ducatillon.net` in your domain list
2. Click **DNS** β **Records**
3. You should see a CNAME record: `sommelier-arena` β `sommelier-arena.pages.dev`
4. Proxy status should be **Proxied** (orange cloud icon)
---
## 7. Set environment variables in Pages
If you need to update `PUBLIC_PARTYKIT_HOST` after initial deploy:
- How to obtain `PUBLIC_PARTYKIT_HOST` (PartyKit project URL):
1. Run `npx partykit deploy` from the repository root. The CLI prints a deploy summary that includes the project URL. Example:
Project 'sommelier-arena' deployed at: https://sommelier-arena.<your-account>.partykit.dev
You can extract it programmatically in CI or locally:
npx partykit deploy 2>&1 | grep -Eo 'https?://[^ ]+partykit.dev' | head -n1
2. Alternatively, open the PartyKit web dashboard for your account and go to Projects β `sommelier-arena` to find the project URL in the project details.
- Once you have the URL, set `PUBLIC_PARTYKIT_HOST` in Pages settings to the hostname only (no trailing slash), e.g. `sommelier-arena.<your-account>.partykit.dev`. Then trigger a redeploy to apply the env var.
1. Pages β `sommelier-arena` β **Settings** β **Environment variables**
2. Click **Add variable** or edit the existing one
3. Save β then go to **Deployments** β click **β―** next to the latest deploy β **Retry deployment** to apply the new variable
---
## Checklist
- [ ] KV namespace `SOMMELIER_HOSTS` created; ID in `partykit.json`
- [ ] `npx partykit deploy` completed (no errors)
- [ ] Frontend Pages project deployed (`sommelier-arena`)
- [ ] Docs Pages project deployed (`sommelier-arena-docs`)
- [ ] Custom domain `sommelier-arena.ducatillon.net` active (green)
- [ ] Proxy Worker deployed with `/docs*` route
- [ ] `PUBLIC_PARTYKIT_HOST` env var set in Pages to your partykit.dev URL
- [ ] Navigate to `https://sommelier-arena.ducatillon.net/host` β dashboard loads
- [ ] Navigate to `https://sommelier-arena.ducatillon.net/docs` β docs load