Stretch Goals.
Everything the site could offer creators and games that we haven't built yet. Sorted by cost, by dependency, and by what it unlocks. None of it is live. All of it is written down.
The rule for this page is: every goal gets a cost, a dependency, and an honest statement of what it does not do. A feature list without costs is marketing. A feature list with costs is a plan. This is the plan.
Ship it looking right
The problem this section solves has a name: the harp looked like shit on mobile. It took days to build and it broke on the device most people would see it on. That's a platform failure, not a creator failure. The platform should catch it before the work goes live.
The headless-Chrome service
One worker on the 24GB node that runs a headless browser, loads a work at a known URL, waits, and captures. Same shape as the Python container: a job queue, an isolated process, a result. This is the linchpin — four of the features below reuse it.
Auto-thumbnails and the postcard
Wire the screenshot job into the catalog: the card grid reads from public/thumbnails/{creator}/{slug}/1366x768.png instead of showing CANVAS PREVIEW, and the OG image comes from the same place. The screenshots themselves are already produced by the gated job from Additions §7 — the missing piece is the catalog integration and a postcard endpoint.
Smoke test / perf report
Does it load, does it throw, how long to first paint, what's the median frame time, does audio survive the gesture requirement. Headless Chrome can report all of this via --dump-dom and CDP; the job handler produces screenshots today, and extending it to parse console output is the missing piece.
Render-to-video
A choreography or canvas piece renders to mp4 via ffmpeg. The "JavaScript choreography video" category gets a real export path — and every other work gets a trailer. Expensive: one render per work per week.
Verify it
Seeded runs, the daily seed, and the seeded PRNG (TF.rng) shipped in the last round — see Additions. The remaining piece of that story is verification: proving a submitted score came from a real playthrough. That needs the headless-Chrome service to be running and a determinism contract that a work can opt into.
Ghost replays
A leaderboard entry is {seed, inputTape, score}. The server replays the tape against the seed to verify the score before accepting it. Top ten entries are replayable as ghosts — a translucent version of another player's run racing alongside yours. Bot-proof, because a bot has to produce a replayable tape to cheat.
The verification shape
A ghost entry is not a score. It's a tape. The server's job is to run the tape and check that it produces the score the player claims. If it doesn't, the entry is rejected. If it does, the entry is accepted and the tape is stored alongside the score.
Play together
The site already promises "Multiplayer Rooms" in the Save System page. Half of that promise is now live — async matches cover turn-based games with no persistent connection. The other half is this: a websocket relay for synchronous, real-time rooms.
The websocket relay
One persistent process on the 24GB node that routes messages between players in the same room. It does not store anything. It does not know who a player is. It holds a room code, a set of connections, and forwards messages. That's the whole process.
Jackbox-style rooms
A host opens the work on a big screen (the "TV"). The screen gets a room code. Players open a controller URL on their phones, type the room code, join. The host screen renders the shared state; the phones render buttons and the 64 preset phrases. No accounts. No installs. The site already calls itself "automatic television" — this is the multiplayer version of that.
That's the whole protocol. Five message types. No authentication, no user identity, no chat — the 64 preset phrases rule still applies in every multiplayer game on the site. The relay doesn't route free text at all; it routes actions and phrase IDs.
Async matches
For turn-based games — chess-by-mail, Words-with-Friends-style — there's a cheaper path that needs no websocket at all. A match object is a save block with two hash codes instead of one. The server stores the board, the player's browser fetches it, the move is appended, the other player fetches it next time. Almost free: it reuses the Save API and adds one field.
Jackbox-style rooms
Host screen plus phone controllers, joined by room code. Five message types. No free text. The 64 preset phrases still apply. Async matches shipped in the last round — see Additions §3. This is the synchronous version, and it requires the websocket relay described above.
A world that moves
The site's whole vibe is "moving pictures, automatic television." These are the primitives that make a work feel like it's on rather than stored. They're the reason a TV file exists as a category.
Shared world state
One small mutable object per work, rate-limited and schema-checked. A 1000×1000 pixel canvas where each hash code can place one pixel per minute. A shared high-score table. A board of the last 100 messages. The r/place primitive, same shape as the Save API but global instead of per-code.
Cron and calendar
A per-work scheduled task: rotate the daily seed at 00:00 UTC, unlock an advent-calendar door on December 1st, show a different scene on a holiday. A work asks the platform "what day is it?" and the platform answers truthfully. Seasonal content without shipping a new version.
Assets and plumbing
The less-glamorous stuff that makes the glamorous stuff possible. Most of it is plumbing. Some of it is the difference between a work looking amateur and looking finished.
Platform asset library
CC0 fonts, sprite sheets, sample packs, hosted at a stable URL and allowed by the CSP the way the Save API is. A 10KB pixel font means a work has a distinct look without inlining a font into a 5MB file. A shared sample pack means a WebAudio piece has a real drum kit without inlining 2MB of samples.
Server-side media processing
Point the Python container at ffmpeg and ImageMagick. "Here's a 3MB WAV, give me a 200KB Opus." "Here's a screenshot, give me an OG crop." "Here's a video, give me a waveform image." Same shape as the existing container, new image, same isolation.
The postcard
A shareable PNG of a work's canvas at a chosen moment, generated by the same headless-Chrome service. One endpoint, returns a URL. Tiny feature, lots of sharing surface. The card grid stops saying CANVAS PREVIEW and starts showing the actual work.
Insight for creators
The site already promises "aggregate play & view counts" in the Privacy Policy. The version of that which is actually useful to a creator of a 32-minute episode is not a total. It's a histogram.
Retention histogram
At what timestamp do people close the tab? A histogram, not per-user, not per-session. For Niki's Playground, "people drop off at minute 14, right after the animals section" is the single most valuable number a creator can get. It requires a beacon, but it's the same privacy posture as the existing play counter: aggregate, no identity.
Frame-time distribution
The work already runs in a sandbox; the platform can measure FPS and report a histogram back. "Your work runs at 24fps on a 2019 Android" is a thing a creator can't easily find out on their own, and it's the thing they most need to know.
Order of operations
The order matters, because most of these things depend on something earlier in the list. The chain is roughly: headless Chrome → seeds and ghosts → async matches → rooms → broadcast and shared state → assets and plumbing → analytics.
Enable screenshots + wire auto-thumbnails
The screenshot job exists but is gated. Enable it, then teach catalog.py to read public/thumbnails/ into works.js. Turns CANVAS PREVIEW into real card images.
Ghost replays
The verification layer on top of TF.rng and the daily seed. Reuses the screenshot infrastructure for replay.
Rooms (the websocket relay)
The first realtime subsystem. Async matches covered the turn-based case; this covers the synchronous one.
Shared world state + cron
The remaining "world that moves" primitives. Broadcast is live; shared state and a scheduler are not. Shared state needs abuse resistance.
Assets + media processing
The one section that breaks the "runs offline" promise for opt-in works. Media processing reuses the Python container.
Analytics: retention, frame-time
The remaining feedback loops. Both need a sandbox beacon. The rater histogram shipped; these are the other two.
Ship in the order of the list. Ghost replays depend on screenshots being enabled; auto-thumbnails depends on the same. The relay is a much bigger lift and sits at step 3 — not because it depends on steps 1 and 2, but because the operational complexity argues for doing it later. Async matches already cover most of the multiplayer use cases without any of that complexity.
If you're going to build one thing this month, enable screenshots and wire auto-thumbnails. It's the smallest end-to-end lift that makes the site look finished — the job handler already works, the catalog just needs to look at the output.
Status
| Goal | Status | Blocked on |
|---|---|---|
| Auto-thumbnails / postcard | Planned | Screenshots enabled + catalog integration |
| Smoke test / perf report | Planned | Screenshots enabled + CDP parsing |
| Render-to-video | Blocked | ffmpeg + headless Chrome + render budget |
| Ghost replays | Blocked | Screenshots enabled for verification |
| Jackbox-style rooms | Blocked | Websocket relay (new subsystem) |
| Shared world state | Blocked | Rate limits + moderation design |
| Cron / calendar | Ready to build | One scheduler |
| Asset library | Blocked | CSP design + opt-in labeling |
| Server-side media processing | Blocked | ffmpeg in Python container image |
| Retention histogram | Blocked | Beacon endpoint + privacy review |
| Frame-time distribution | Blocked | Sandbox beacon + privacy review |
What we are not building
The opposite of a stretch goal. Things that look like they should be on this page and aren't, because they'd contradict something the site already promises.
- Accounts. The whole privacy model is built on there being no player accounts. Every feature above works without one, and that's the point. A feature that needs an account doesn't get built here.
- Payment handling. Donation links go straight to the creator's own service. The site doesn't hold money and doesn't want to.
- Live text chat. The 64 preset phrases rule applies everywhere, including in the rooms above. The relay routes actions and phrase IDs, not free text.
- AI-generated whole games. The language model is a helper for short text and server-side tasks. It doesn't author games, doesn't review code, and isn't a substitute for a creator. That's not a limitation; it's the design.
- Video hosting. Render-to-video produces an mp4 for a creator to take elsewhere. The site doesn't host video files — it renders them. That's what "moving pictures" means here.
- Ads, sponsorships, or a paid tier. The site is funded by donations and the maintainer's own money. A stretch goal that required a revenue stream would fail its own cost test.
See also
For the additions that shipped — the seeded PRNG, the daily leaderboard, async matches, Channel One, the catalog JSON, the rater histogram, and the screenshot job — see Additions. For what's live today, see the Status & Roadmap page. For the language model that runs on the same node, see Language Models. For the Save API that the seeds, ghosts, and matches all reuse, see the Save System. For the submission pipeline that the smoke test and semantic screening feed, see the Submission Criteria. For the websocket relay's security posture, the general shape is described in Security & Trust — the relay is a new subsystem and will get its own threat-model section when it ships.
See what's live today → Join the Discord →