# Routes & how to test (dev) The front end picks what to render from the URL (see `src/main.tsx`). Vite dev server runs on `http://localhost:5173`. | URL | Renders | For | |---|---|---| | `/` | Splash → campaign (walks the story graph: cutscene → dialogue → hands off to the board) | Narrative / player flow | | `/node/` | **Dev/admin teleport** to a story node; a *level* node lands you on that level's board clone | Jumping around the tree while testing | | `/level/` | A level board directly (add `?edit=1` to author) | Board work / editing | | `/admin` | Admin panel (mysteries, NPCs, assets, graph editor) | Authoring | | `/?phone=1` | 3D clamshell phone dialer spike | Phone prototype | ## Game state (demo) A player's whole state is two things on their **playthrough**: - `playthroughs.current_node_id` — *where* they are (which node; a level node also has `current_level_id`, the board clone). - `achievements` — *what* they've earned (`(playthrough_id, flag_key, awarded_by_node_id)`). Normal play resolves position via `GET /api/playthroughs/current`. `/node/:id` is just the dev override that *writes* `current_node_id` (the `goto` teleport). ## Quick test recipes **Play the campaign:** open `/` → New Game → click through the intro/briefing → you land on the board. **Jump straight to a node:** `/node/`. List the current node ids: ```bash docker exec osint-board-db psql postgres://osint:osint_secret@localhost:5432/osint_dev -At -F' | ' \ -c "SELECT n.id,n.node_type,n.label FROM osint.story_nodes n JOIN osint.mysteries m ON m.id=n.mystery_id WHERE m.slug='glass-harbor' ORDER BY n.ypos;" ``` (The `level` row is the board.) **Phone seam (achievements):** `/?phone=1` → dial `55501` (Elias) → voicemail → click **grant elias_number_callable** → the handset glows → dial `55501` again → connects. Voss `55502` stays voicemail; other numbers = unobtainable. **Reset to a clean slate:** `docker exec osint-board-db psql postgres://osint:osint_secret@localhost:5432/osint_dev -c "TRUNCATE osint.playthroughs CASCADE;"` then reload (playthroughs + achievements are wiped; `/` shows the splash again). ## Dev-only endpoints Both are gated to `NODE_ENV !== 'production'` (swap for the admin JWT when we want them in a deployed build): - `POST /api/playthroughs/:id/goto` `{ nodeId }` — teleport (powers `/node/:id`). - `POST /api/playthroughs/:id/achievements` `{ flagKey }` — grant an achievement (stand-in until the server-side rule engine fires them from play). `GET` the same path lists earned achievements. Backend changes need a container rebuild: `docker compose -f docker-compose.dev.yml up -d --build app`. The Vite front end is live on 5173.