





The hard part
A story game with spoken dialogue normally needs a server producing lines for each player, so every new player adds cost and every outage stops the game. The alternative is to do that work once, before release. It sounds simple, but it means designing the whole game so that nothing is ever called at runtime.
Every line of voice and text is generated ahead of time and shipped as static files, including more than 41,000 voice clips streamed from storage at the edge, on servers close to the player. Saves live on the player's device, with optional cloud sync, so the network is a convenience rather than a dependency. Pages are served from Cloudflare's edge, audio from its R2 storage and optional saves from its D1 database, and a modest phone still gets a smooth crossing.
584 commits on 39 working days; more than 41,000 voice clips served from the edge; live at ship-voyage-4zn.pages.dev.
What the measurements mean
Only what is unusual for this project. Every sentence names the field it came from; nothing here is asserted that cannot be checked against the data.
- At 80,937 authored lines it is one of the larger things here, roughly 10x the median project in this estate. authored_linesfrom authored_lines
- It serves 5 HTTP endpoints and declares ports 5174, 8000, 8009, 8888, so it runs as a service rather than a script.see the evidencefrom assets.routes, assets.ports
- The code defines 104 functions, 0 methods and 3 classes.see the evidencefrom pythonAst.counts, pythonAst.coverage
- It grades A, weakest on runnability at 71.4%. runnability coveragesee the evidencefrom grades
How it works
A narrative game with spoken dialogue normally needs a server and generation for each player, so every new player adds cost and every outage takes the game down. The alternative is to do that work once, at build time, and ship the result. It sounds obvious until a whole game has to be restructured around never calling anything while it runs. Every line of voice and text is generated ahead of time and shipped as static files. Saves are kept locally first, with optional cloud sync, so the network is an addition rather than a dependency. The game is live at ship-voyage-4zn.pages.dev, served from the edge, with the voice audio in R2 object storage and D1 holding optional saves, accounts and a leaderboard. Later changes were measured before they were made. Tests showed the warships in a battle all ran one AI routine, so they were split into distinct doctrines and formations. Wages and a bank that works only in port put pressure on gold, and cargo value grows with the distance sailed. The page also gained metadata that crawlers can read, because AI answer engines do not run its JavaScript.
What it is built from
Each bar is one of this project's own modules, sized by how many times the rest of the project imports it. The counts are measured, not estimated, and the module at the top is the one the rest of the project leans on most.
What kind of engineering this is
Six signals counted from the source: files that run models locally, that act without being asked each time, that check their own output, that survive failure, that touch parsers and protocols, and that were measured then improved. Every axis carries its file count.
What it is written in
Share of code bytes. Vendored bundles and generated output are set aside before this is computed, which is why it differs from a simple file count.
What stands out
- No game server and no AI at runtime: every line of voice and text is generated at build time
- Saves are local first, with optional cloud sync
- Live on Cloudflare Pages, with audio from R2 and saves and a leaderboard in D1
- Sailing physics in which the ship does not simply go where it points
- Warships were given distinct doctrines after tests showed they all ran one routine
- The layout was measured on a phone held sideways rather than assumed to fit
Capabilities
- Ports of Call
- What you do
- If you liked
- Playing it
- Develop
- Build & deploy
- Assets
- Structure
- Load
- Forget key
Grade
Every check names the field it measured. Checks that cannot apply are excluded, never counted as failures.
- provenance100.0%
- documentation100.0%
- runnability71.4%
- maintenance100.0%
- integrity100.0%
Not met
- environment none
python -m venv .venv (in the project folder
Architecture
Directories carrying real modules, largest first.
tools19 modulessrc7 modulesfunctions5 modules(root)1 module
HTTP surface
5 endpoints in total.
POST /api/v1/auth/loginPOST /api/v1/generateGET /api/v1/audio/{clip_id}GET /api/v1/voicesGET /api/v1/health
Data model
Typed structures and tables found in the source.
- voices
- lines
- clips
- LoginRequest
- LoginResponse
- GenerateRequest
Vulnerable dependencies
1 declared dependency matches a published advisory. Checked offline against the OSV database; only pinned versions can be checked, so anything unpinned here is unknown rather than clean.
- Act now.
undici7.29.1→ 7.30.1GHSA-2m5v-pch6-74hx, GHSA-4qv8-2p9j-2685, GHSA-4w7w-5xrc-9h26
Vocabulary
Parsed 19 of 19 Python file(s).
Classes
LoginRequesttools/tts-server.py:170LoginResponsetools/tts-server.py:174GenerateRequesttools/tts-server.py:178
Functions
is_en_onlytools/content.py:43existing_bankstools/content.py:47build_dbtools/content.py:52cmd_statustools/content.py:89cmd_buildtools/content.py:120cmd_tstools/content.py:166safe_filenametools/revoice.py:29clip_nametools/revoice.py:33speed_fortools/revoice.py:39build_taskstools/revoice.py:44maintools/revoice.py:83synth_openaitools/tts_pool.py:34synth_localtools/tts_pool.py:44healthtools/tts_pool.py:56healthy_workerstools/tts_pool.py:69run_pooltools/tts_pool.py:80worker_looptools/tts_pool.py:96maintools/tts_pool.py:134needs_text_fixtools/tts_text.py:23clean_tts_texttools/tts_text.py:28clienttools/r2_upload.py:31existing_keystools/r2_upload.py:42maintools/r2_upload.py:57puttools/r2_upload.py:76
Command line
- --root
- --bitrate
- --replace
- --regenerate
- --application
- --no-loudnorm
- --no-manifest
- --dry-run
- --dest
- --max-per-category
Depth
Signals counted from the code, not asserted.
584 commits across 39 separate working days over 4.4 months, 86 of them revising existing behaviour
Built from scratch
- Concurrency primitives
Closes its own loop
- Memory / accumulated state
Proves itself
- Benchmarks
- Golden / baseline files
Survives failure
- Fallback paths
- Timeouts
- Retry / backoff
- Logging / observability
- Rate limiting
- Recovery / restore
Local inference
- Local TTS
- LM Studio
Systems
Distributed systems
- Worker orchestration
- Health / heartbeat
Working within limits
- Timeout budgets
- Context-window budgeting
Environment engineering
- Virtual environments
Languages
- TypeScript42,071
- JavaScript32,684
- Python4,110
- Batchfile325
- SQL100
- Shell21
Built with
- FastAPI
- Uvicorn
- NumPy
- Playwright
- Pydantic
- React
- Vite
- Tailwind CSS
- Cloudflare Pages
- Cloudflare Workers
- npm
Recurring themes in the commit history
- you
- gate
- see
- her
- sea
- three
- battle
- game
- screen
- log
Evidence
Taken from the code itself: a module docstring or the opening of the README.
Bake battle HAILS PER VOICE so each enemy's seeded voice has a clip, named for the game to play directly: bhail_{context}_{token}_{id}.opus. Each translated line is baked in EVERY Kokoro voice of its language; the runtime picks one via seededVoiceToken(...kokoroOnly) and uses it for the WHOLE fight. Also emits the English-subtitle table the game shows over the ship. Idempotent. See .claude/voice-c
At a glance
- Status
- active
- Primary language
- TypeScript
- First commit
- 2026-06-13
- Last activity
- 2026-10-25
- Domain
- Automation & scraping
- Agent docs
- CLAUDE.md, AGENTS.md, PROJECT_KNOWLEDGE.md, .claude