Repository navigation
Add the website: a guide for people, with running games and compiled snippets - #61
Merged
Merged
Conversation
…snippets The root README was the only human doc. The website (Astro, MDX) explains the library with the brand's palette and assets, embeds the top-down game running in the page, and compiles every `ts twoslash` snippet against the workspace source, so its types, JSDoc, and errors are the compiler's and a broken example fails the build. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014No3129r6nXFycnzdAEknt
The build is the check that every docs snippet still compiles. Deploying from the release job keeps the site in step with what is on npm; the Website workflow can also deploy by hand. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014No3129r6nXFycnzdAEknt
A change that breaks a snippet or demo fixes it in the same change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014No3129r6nXFycnzdAEknt
CI runs the typecheck before any build, so .astro/types.d.ts (which types the brand asset imports) did not exist yet. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014No3129r6nXFycnzdAEknt
Walk a small town tile by tile, read the signs, and talk to three villagers. The rules are headless systems with a Mode state machine (Exploring / Talking); Pixi only draws. check.ts drives it with scripted input and an invariant checked every frame. Art and font: the CC0 Ninja Adventure pack by Pixel-boy and AAA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Homepage: the brand animation in the hero, the Town demo below it with a "Play the demo" button that opens it full screen, three steps to a running game, and a mistakes explorer with compiled errors - Code blocks: file titles, highlighted and focused lines, diffs, a richer theme from the brand palette, and no more empty scroll area from hidden type popups (queries render as lines, popups are fixed) - Docs: shorter prose, more comments and spacing in snippets, and a fix diff after each type-safety error - Full screen enlarges the game in place instead of opening a new page - Header and footer alignment, no chips above titles Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…demo main (#63) groups devices in Controls: the top-down controls now take a keyboard, a mouse, and a gamepad. The browser host binds Pointer actions on its canvas, and the devtools page's scripted run passes a scripted mouse. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Sandro · project thread
This PR adds a docs website for Ritmo, written for humans. This description is the hand-off document: an agent picking the work up should be able to finish it from what is written here, the code on this branch, and
website/README.md.1. Requirements (from Sandro, the owner)
These are paraphrased from the original request and have not been relaxed:
SETUP.md, the skill).brand/README.md).typeonce-dev/ritmo).ritmo.typeonce.dev.Project-wide constraint: Ritmo must never depend on Effect. That applies to the published packages, and it is also why the deploy uses plain
wranglerinstead of Alchemy, which is Effect-based and what the Spirit Call game uses.2. Decisions taken (and why)
@shikijs/twoslash4.5,twoslash0.3.9) for snippets^?queries,// @errors:lines.typescript6.0.3, while the repo is on TS 7.0.2^5.5 || ^6), which native TS 7 does not have. Ritmo supports TS ≥ 5.9, so the errors match what games see.workspace:*deps)website/twoslash.mjs)Fix<"…">,__fixTickOrder__,__schemaConflicts__,__runtimeRequirementError__). The page shows only that message, and the copy says so honestly. Absolute build paths are stripped from hovers./play/<id>/Keyboard.actions(window, …)andGamepad.actions(window, …)listen onwindow. A frame isolates input and crashes, and lets several games share a page. Frames are lazy-loaded and start on click, which also gives the frame focus.integration/top-downunchanged and add only a browser host and a Pixi rendererFixedLoop,BrowserTickSource,Controls,InputCapture,RenderSync,PixiNodeRegistry).pagefind.yml).wrangler(website/wrangler.jsonc)ritmo.typeonce.dev.release.yml) and by hand from theWebsiteworkflowmain.brand/assets, never copied (src/brand.ts)brand/stay the only place assets are made.3. What is done in this PR
Package:
website/is a private workspace package, added topnpm-workspace.yaml. It is not in the changesets fixed group and is not published. The roottsconfig, vitest, andpnpm checkdon't include it.Pages (
website/src/pages):/: hero with the running game, install command, three pillars, a compiled tick-order error, and the "Ritmo does not draw" section./docs/: Getting started (install, the packages table, first world, a system, running a tick)./docs/with-an-agent/: the agent-first pitch, theSETUP.mdprompt, the skill and its principles./docs/concepts/: world, systems, queries, commands andapplyDeferred, schedules and the tick, state machines, the fixed step and determinism./docs/type-safety/: a gallery of compile errors, each with its fix message: undeclared write, undeclared spawn, missing required component, raw id despawn, tick order, missing service, duplicate names,Clock.hz(59.94)and a state typo, andResultfromRuntime.make./docs/browser/: the embedded game,FixedLoop+BrowserTickSource,Controls/Keyboard/Gamepad/InputCapture, andRenderSyncwith Pixi./docs/devtools/: a scriptedSessionrun of the top-down game with an invariant, realwhy()and lint output, a table of session calls, the lint and oxlint checks, andDeterminism.check./examples/: the top-down game, plus links to Spirit Call (spirit-call.typeonce.dev) and Inkline Town./brand/: logos with downloads, the palette, type, and rules./play/top-down/: the bare game page that gets embedded.404.Components:
Header: lockup, nav, search dialog, theme toggle.Docslayout: sidebar, prev/next, "edit on GitHub".Game: the iframe embed.BrandAssetsandPalette.TypePopups: places Twoslash hover popups withposition: fixedso code blocks that scroll sideways don't clip them.Footer.Styling:
src/styles/global.css. Ink is the default; Paper is the light theme, chosen byprefers-color-schemeor the toggle stored inlocalStorage.src/shiki/ritmo.jsonis built from the palette (Tick for keywords and errors).src/styles/twoslash.css.Demo (
src/demos/top-down/):game.ts(mount(host)): Pixi app, world scaled to fit, runtime with input and node-registry services,FixedLoop, and a HUD read through aGame.Inspector.render.ts: oneRenderSync.systemeach for walls, pickups, and the player.src/demos/index.ts.CI and deploy:
.github/workflows/website.ymlruns on Node 24, because Astro needs ≥ 22.23.4. On every PR and push it runstypecheck(astro sync && tsc) andbuild(astro build && pagefind). Itsworkflow_dispatchtakes adeployinput (main only).release.yml: the changesets step hasid: changesets. Whenpublished == 'true', the job builds and runspnpm --dir website run deploy:cloudflare.Repo rules:
AGENTS.md(whichCLAUDE.mdsymlinks to) now nameswebsite/in Repo, adds the website build to Verify, and replaces "the root README is the only doc for humans" with the website rule.Verified:
pnpm checkpasses.pnpm --dir website typecheckandbuildpass.wrangler deploy --dry-runreads the build.4. What remains (in priority order)
Deploy secrets (Sandro will provide). Add repo secrets
CLOUDFLARE_API_TOKEN(Workers Scripts edit on the account, Workers Routes edit on thetypeonce.devzone) andCLOUDFLARE_ACCOUNT_ID. The release job runs in thenpmenvironment, so the secrets must be visible there. Then deploy once by hand: run theWebsiteworkflow onmainwith "Deploy" ticked, and checkhttps://ritmo.typeonce.dev. Note that release automation only runs while the repo variableRITMO_RELEASES_ENABLEDistrue.Link the site from the root
README.md(and optionally each package'shomepageinpackage.json) once it is live. This was left out so the link doesn't 404 before the first deploy. Changinghomepagechanges what a package publishes, so it needs a changeset andpnpm pack:check.Touch controls for the demo. On a phone, the game can be seen but not played:
top-downbinds only keyboard and gamepad. AddTouchfrom@typeonce/ritmo-browser(a floating stick and an interact button) to the demo host, merged into the sameControlsactions. Keep it inwebsite/src/demos/top-down/or extendintegration/top-down/types.tsif the simulation's bindings should own it. Update thecontrolstext insrc/demos/index.ts.More embedded games. Requirement 4 asks for games in each page where useful. To add a demo:
src/demos/<id>/game.tsexportingmount(host: HTMLElement): Promise<() => void>;src/demos/index.ts(title, description, controls, source,load);<Game id="<id>" />.Good candidates: a tiny demo per concept (commands spawning a wave, a state machine pausing, determinism replaying a recorded input side by side), or
integration/algorithms.Optional: embed Spirit Call on
/examples/(an iframe ofspirit-call.typeonce.dev; check that its headers allow framing, and note it pins Ritmo 0.9), a social card image (brand/assets/ritmo-lockup-stacked*.svgrasterised forog:image; it currently uses the 512px app icon), and self-hosted fonts instead of Google Fonts.5. Gotchas
ci.yml) stays on Node 22; only the website job uses 24.// @errors: 2345placed inside an indented block is ignored and the build fails with "errors were not marked as expected". Put flags right after// ---cut---at column 0. One@errorsline can list several codes.throws: true). This is intended: it's the check that docs match the API.website/twoslash.mjs(condense). A new Ritmo error shape (a new__fix…__key) is caught by the__fix\w+__pattern. Anything else falls back to the full message with paths stripped. Twoslash'sresult.errorsis a getter overresult.nodes, so rewritenodes, noterrors.astro syncbeforetsc..astro/types.d.tstypes the.svg/.pngimports. Without it the typecheck fails with TS2307 (this was the first CI failure on this PR).../../brand/assets/...fromsrc/).vite.server.fs.allow: [".."]permits that in dev.deploy:cloudflare, notdeploy, becausepnpm deployis a built-in pnpm command.src/pages/<path>.mdx(/docs/maps todocs/index.mdx).brand/README.md): say step, tick, order, exact, checked, declared, deterministic, replay; no musical puns. Player-facing and docs copy uses no gendered pronouns.Commands
🤖 Generated with Claude Code
https://claude.ai/code/session_014No3129r6nXFycnzdAEknt