Chapters Quick start

Chapter 2 of 13

Quick start

Scaffold a project, run it behind a tunnel, play every seat in the Inspector, and see what each file of the project is for.

pnpm create camtable-addon my-game            # host mode: static files only, free to host
pnpm create camtable-addon my-game --engine   # engine mode: one Worker serves the pages and your engine
cd my-game
pnpm install
pnpm dev                                      # then open the Inspector link it prints

(npm create camtable-addon@latest my-game and npx create-camtable-addon my-game work too.)

pnpm dev puts your addon behind a temporary https tunnel and prints an Inspector link with its manifest address filled in: a page on the CamTable website where you sign in with Discord and play every seat of a match in a real room, without a Discord call or the extension (section 11: Testing locally). It also prints an Install Link, for trying the game in a real call. There is no offline way to try a game. To share it, deploy it and give out the https manifest URL (section 9: Hosting and section 10: Installing, sharing and updating).

The project contains:

File Purpose
src/game.ts The rules, a pure reducer (tapRace). The same object runs in both modes. Also the race’s Game Settings (RACE_SETTINGS, the number of taps to win), which the reducer reads.
src/addon.ts The manifest and every protocol route, built from a few constants. Change ADDON_ID first.
index.html, src/main.ts, src/ui.ts The game page: “Tap Race”, first to ten taps wins. In host mode main.ts calls createHostAuthority(tapRace, { sdk }).
vite-plugin-addon.ts, vite.config.ts Serve the protocol routes in development (with CORS) and write them as static files on build.
scripts/dev.mjs pnpm dev: the addon behind a temporary https tunnel, with the Inspector link and the Install Link for it (section 11: Testing locally).
public/_headers, public/404.html CORS and cache headers, and a real 404, for Cloudflare (other hosts: section 9: Hosting).
src/engine/worker.ts, wrangler.json, scripts/serve-worker.mjs (--engine) The one Worker: static assets from dist/, and your rules behind signed /engine/* routes; pnpm dev runs it locally.
tests/ The reducer, a whole match through it, and every route against the protocol; (--engine) the engine refusing an unsigned request and accepting a signed one. None needs a network.

The scaffolded README covers the daily commands.