fuzzyworld

dm / files / README.md

README.md

5.8 KB ยท history ยท blame

๐ŸŽฒ Solo Dungeon Master

An AI-powered solo tabletop RPG app that runs entirely in your browser, using the Cypher System rules. Your API key never leaves your device โ€” all requests go directly from your browser to the Anthropic API.

Live: apps.fuzzyworld.net/dm/


How it works

On your first visit you'll be asked for an Anthropic API key. The key is saved to your browser's localStorage (AES-GCM encrypted) so you only enter it once. After that, the game UI appears immediately on every return visit, resuming your previous adventure automatically.

The game is powered by claude-haiku-4-5-20251001 and uses Claude's tool-use API to maintain a structured character sheet (Might/Speed/Intellect pools, XP, cyphers, equipment) while generating freeform narrative. Costs roughly a few cents per session.

Features

Running locally

npm run dev   # serves public/ on http://localhost:3000

Requires Node.js. No build step โ€” the entire app is a single public/index.html.

Architecture

Concern Approach
AI backend Anthropic Messages API, streaming SSE
Key storage AES-GCM + PBKDF2 (Web Crypto API); falls back to XOR stream cipher on plain HTTP
Share links AES-GCM encrypted blob in the URL hash (#k=); hash is never sent to the server
Session state localStorage โ€” character sheet, conversation history, rendered HTML
Analytics metadata.user_id in each API request carries p_<playerId>:g_<gameId> for Anthropic Console
Deployment apps.fuzzyworld.net โ€” npm run deploy publishes public/

Why a single file?

public/index.html is currently ~3,500 lines of vanilla JS โ€” no build step, no bundler, no TypeScript. This is intentional. The constraint keeps the CI pipeline trivial (push public/ โ†’ GitLab Pages deploys it) and makes the project easy to fork and self-host without a Node.js toolchain beyond the dev server.

The tradeoffs are real โ€” no type safety, no module splitting, global state everywhere โ€” but acceptable for a project of this size and pace. If the file grows significantly or type errors become a recurring problem, the natural upgrade path is Vite + TypeScript: split index.html into modules, add a vite.config.ts, update the CI script: step to run vite build, and point GitLab Pages at dist/ instead of public/. That migration is well-understood and can be done incrementally.

Reporting issues

Use the ๐Ÿ› Report button in the top bar โ€” it collects debug info automatically.

License

The source code is licensed under the GNU Affero General Public License v3.0. If you run a modified version of this app as a network service, you must publish the modified source under the same license.

The game rules content (Cypher System types, descriptors, foci, mechanics) is used under the Cypher System Open License ยฉ Monte Cook Games. The CSRD is free for use in digital products; see the CSOL for full terms.

ยฉ 2026 Pavel Safronov

About

This game is written by Pavel asking Claude to implement features. This paragraph - written by Pavel - is the only hand-written code in this repo. Part of the experiment here is being able to create a complex RPG game with Claude, while also utilizing Claude in the game itself. Let's see how this goes. Enjoy!

Source
1# ๐ŸŽฒ Solo Dungeon Master
2
3An AI-powered solo tabletop RPG app that runs entirely in your browser, using the **Cypher System** rules. Your API key never leaves your device โ€” all requests go directly from your browser to the Anthropic API.
4
5**Live:** [apps.fuzzyworld.net/dm/](https://apps.fuzzyworld.net/dm/)
6
7---
8
9## How it works
10
11On your first visit you'll be asked for an [Anthropic API key](https://console.anthropic.com/). The key is saved to your browser's `localStorage` (AES-GCM encrypted) so you only enter it once. After that, the game UI appears immediately on every return visit, resuming your previous adventure automatically.
12
13The game is powered by `claude-haiku-4-5-20251001` and uses Claude's tool-use API to maintain a structured character sheet (Might/Speed/Intellect pools, XP, cyphers, equipment) while generating freeform narrative. Costs roughly a few cents per session.
14
15## Features
16
17- **Cypher System character creation** โ€” pick a Descriptor (34 options), Type (Warrior, Adept, Explorer, Speaker), and Focus (69 options) to form the sentence *"I am a Clever Warrior who Hunts."*
18- **Setting selector** โ€” choose Classic Fantasy, Ninth World (Numenera), Modern Thriller, or Science Fiction at character creation; adjusts currency, tone, special-ability vocabulary, and available Foci
19- **Three stat pools** โ€” Might, Speed, and Intellect each with current/max and Edge displayed; colour-coded bars shift green โ†’ amber โ†’ red as pools deplete
20- **Damage track** โ€” one pool at 0 โ†’ Impaired; two at 0 โ†’ Debilitated; all at 0 โ†’ Dead
21- **Skills** โ€” starting skills populated from Type and Descriptor; sidebar section shows each skill with a colour-coded rank badge (green Trained / gold Specialized / red Inability); overlapping trained skills automatically promote to Specialized
22- **Cyphers** โ€” one-use items found during play; displayed in the sidebar with Cypher Limit enforcement
23- **Advancement modal** โ€” spending 4 XP opens a choice dialog: increase a pool max by 4, add +1 Edge to a stat, train a new skill, specialize in a trained skill, or describe a custom improvement; four improvements advance your Tier (max Tier 6)
24- **Session persistence** โ€” adventure state and conversation history saved to `localStorage`; reloading the page resumes mid-scene; save version guard offers Markdown export before discarding incompatible sessions
25- **Cost display** โ€” per-turn and session cost estimates shown in the sidebar (based on token counts from the SSE stream)
26- **Dice roller** โ€” d4 through d100, configurable count
27- **World Notes** โ€” orange-bordered GM meta-context panel for providing background lore, world physics, and house rules that Claude treats as absolute truth
28- **Share links** โ€” generate an encrypted `#k=โ€ฆ` URL so someone else can use the app with your API key; they enter a passphrase you share separately; the key is never in the URL
29- **Report Issue** โ€” in-game button that collects debug info (character state, recent errors, session cost) and opens a pre-filled bug-report email
30
31## Running locally
32
33```bash
34npm run dev # serves public/ on http://localhost:3000
35```
36
37Requires Node.js. No build step โ€” the entire app is a single `public/index.html`.
38
39## Architecture
40
41| Concern | Approach |
42| ------------- | ---------------------------------------------------------------------------------------------- |
43| AI backend | Anthropic Messages API, streaming SSE |
44| Key storage | AES-GCM + PBKDF2 (Web Crypto API); falls back to XOR stream cipher on plain HTTP |
45| Share links | AES-GCM encrypted blob in the URL hash (`#k=`); hash is never sent to the server |
46| Session state | `localStorage` โ€” character sheet, conversation history, rendered HTML |
47| Analytics | `metadata.user_id` in each API request carries `p_<playerId>:g_<gameId>` for Anthropic Console |
48| Deployment | apps.fuzzyworld.net โ€” `npm run deploy` publishes `public/` |
49
50### Why a single file?
51
52`public/index.html` is currently ~3,500 lines of vanilla JS โ€” no build step, no bundler, no TypeScript. This is intentional. The constraint keeps the CI pipeline trivial (push `public/` โ†’ GitLab Pages deploys it) and makes the project easy to fork and self-host without a Node.js toolchain beyond the dev server.
53
54The tradeoffs are real โ€” no type safety, no module splitting, global state everywhere โ€” but acceptable for a project of this size and pace. If the file grows significantly or type errors become a recurring problem, the natural upgrade path is **Vite + TypeScript**: split `index.html` into modules, add a `vite.config.ts`, update the CI `script:` step to run `vite build`, and point GitLab Pages at `dist/` instead of `public/`. That migration is well-understood and can be done incrementally.
55
56## Reporting issues
57
58Use the **๐Ÿ› Report** button in the top bar โ€” it collects debug info automatically.
59
60## License
61
62The **source code** is licensed under the [GNU Affero General Public License v3.0](LICENSE). If you run a modified version of this app as a network service, you must publish the modified source under the same license.
63
64The **game rules content** (Cypher System types, descriptors, foci, mechanics) is used under the [Cypher System Open License](https://www.montecookgames.com/cypher-system-open-license/) ยฉ Monte Cook Games. The CSRD is free for use in digital products; see the CSOL for full terms.
65
66ยฉ 2026 Pavel Safronov
67
68## About
69
70This game is written by Pavel asking Claude to implement features. This paragraph - written by Pavel - is the only hand-written code in this repo. Part of the experiment here is being able to create a complex RPG game with Claude, while also utilizing Claude in the game itself. Let's see how this goes. Enjoy!