Skip to main content
Version: 2.0 PartyKit

Networking URLs

Sommelier Arena exposes two WebSocket-capable endpoints depending on how you run the stack. Understanding the difference is useful when debugging or setting up a new environment.

The two URLs​

URLWhat it is
ws://localhost:1999/parties/main/{code}Direct PartyKit dev server
ws://localhost:4321/parties/main/{code}Proxied β€” browser β†’ nginx β†’ PartyKit

Both reach the same Durable Object and the same game logic. The difference is purely in the network path.


Mode A β€” Local development (no Docker)​

npx partykit dev --port 1999        # PartyKit listens on 1999
cd front && npm run dev # Astro dev server on 4321

front/.env.local (copied from front/.env.example) sets:

PUBLIC_PARTYKIT_HOST=localhost:1999

The browser connects directly to ws://localhost:1999/parties/main/{code}. No proxy is involved. The Astro dev server and PartyKit are two separate processes on two separate ports.

Use localhost:1999 for:

  • Rapid frontend iteration with Vite HMR
  • Debugging PartyKit logs directly in your terminal

Mode B β€” Docker (docker-compose up)​

docker-compose up --build -d
# front (nginx) β†’ localhost:4321
# back (PartyKit) β†’ localhost:1999 (exposed directly to the browser)
# docs (Docusaurus) β†’ localhost:3002

In this mode, the Astro static site is built into nginx. At build time, the env var is baked in:

PUBLIC_PARTYKIT_HOST=localhost:1999   ← set via Docker build arg

The browser connects directly to ws://localhost:1999/parties/main/{code} β€” the same URL as Mode A. nginx serves only static HTML/JS/CSS files and handles SPA routing; it does not proxy WebSocket traffic.

Browser  ──ws://localhost:1999/parties/main/1234──►  PartyKit (back:1999) [exposed on host port 1999]

Use Mode B for:

  • Beta testing the full stack in Docker
  • Running E2E tests against the production-like build

Production β€” Cloudflare​

In production the PartyKit server is deployed to Cloudflare Workers via npx partykit deploy. The game URL becomes:

wss://sommelier-arena.USERNAME.partykit.dev/parties/main/{code}

The Cloudflare Pages frontend is built with:

PUBLIC_PARTYKIT_HOST=sommelier-arena.USERNAME.partykit.dev

The browser connects directly to the PartyKit Workers URL β€” no nginx proxy is needed because Cloudflare handles TLS, routing, and WebSocket upgrades natively.

Browser  ──wss://sommelier-arena.USERNAME.partykit.dev/parties/main/1234──►  Cloudflare Workers (PartyKit DO)

Summary​

ModePUBLIC_PARTYKIT_HOSTWho proxies?
Mode A β€” local devlocalhost:1999None β€” direct
Mode B β€” Dockerlocalhost:1999None β€” direct (back exposed on host port 1999)
Productionsommelier-arena.USERNAME.partykit.devCloudflare (native)

The PartyKit WebSocket path is always /parties/main/{sessionCode} β€” main matches the "main" entry point in partykit.json, and {sessionCode} is the 4-digit room ID.


Port reference​

EnvironmentFrontend URLPartyKit/WebSocketWine Answers Worker
Mode A (local dev)http://localhost:4321localhost:1999 (direct)http://localhost:1998 (optional)
Mode B (Docker)http://localhost:4321localhost:1999 (direct β€” back exposed on host port 1999)http://localhost:1998 (wine-answers container)
Productionhttps://your-domain.com<project>.partykit.devhttps://<wine-answers-worker>.workers.dev

Environment variables​

VariableWhere to setValue
PUBLIC_PARTYKIT_HOSTfront/.env.local (Mode A)localhost:1999
PUBLIC_PARTYKIT_HOSTdocker-compose.yml build arg (Mode B)localhost:1999
PUBLIC_PARTYKIT_HOSTCloudflare Pages dashboard (Production)<project>.partykit.dev
PUBLIC_WINE_ANSWERS_URLfront/.env.local (Mode A)http://localhost:1998
PUBLIC_WINE_ANSWERS_URLdocker-compose.yml build arg (Mode B)http://localhost:1998
PUBLIC_WINE_ANSWERS_URLCloudflare Pages dashboard (Production)https://<wine-answers-worker>.workers.dev

Mode B note: In Docker, the browser connects directly to localhost:1999 for WebSocket traffic (the back container is exposed on host port 1999). nginx in the front container only serves static files and handles SPA routing β€” no WebSocket proxy needed.

Mode A and Mode B use the same PUBLIC_PARTYKIT_HOST: Both modes set PUBLIC_PARTYKIT_HOST=localhost:1999. The browser always connects to ws://localhost:1999/parties/main/{code} directly. The app code is identical in both modes.