1# web: whiskers.lmjtfy.fun 2 3The public page for Whiskers, in the look and stack of its neighbour [lmjtfy](https://lmjtfy.fun): a Rust 4Cloudflare Worker (axum, maud) with Datastar, so the server draws the page and the browser holds 5no state of its own. It tells a stranger what Whiskers is, how it keeps a child safe, how it works 6and how to get it, says plainly that it is a personal project and not a product, shows where it uses Jev (a diagram of one turn, the guard's questions and three real requests), and has a demo 7of the cat itself on the app's 15 by 16 pixel grid, on a black stage so its pale effects show, with moods and mascots the server chooses and eyes that 8follow the pointer. Pasted into Discord or Twitter it unfurls as a looping video of the cat (served with byte ranges, which those players need). 9 10Three mascots stand on the demo stage, in this order: **Ginger**, the cat the app started with and 11the default; **Grey**, the grey cat; and **Bunny**, a rabbit made for the page. A picker beside the 12demo chooses; the server answers with the new figure like it does for a mood, and nothing is 13remembered (`?mascot=ginger|grey|bunny` on the address pre-selects one, checked against the closed 14set `cat::Mascot`; anything else is Ginger). Ginger and Bunny are drawn in [`cat/`](cat/); the grey 15cat is drawn once, in [`../crates/whiskers-art`](../crates/whiskers-art/), and the app draws the same 16data. The link preview's PNG and MP4 show Ginger. 17 18`whiskers.lmjtfy.fun` is the canonical address. Any other address that is not local (the account's `workers.dev` one) answers 19GET and HEAD with a `308` to the same path and query there, so link previews and old links move; see `site/src/host.rs`. 20 21## Run it 22 23Everything runs from the toolchain `mise install` fetches (see the root README), with no account and no login: 24 25 mise run test:web # the pure parts, natively 26 mise run web:dev # http://localhost:8788/ 27 28(With nix, `nix develop` gives a shell with mise first; the tasks are the same.) 29 30`wrangler dev` runs [`tools/build`](tools/build) first, which builds the Worker and, when it is 31stale (a hash of what it is drawn from, `tools/preview-hash`, not file times), the preview PNG and MP4 (about fifteen seconds). Nothing here deploys; the owner's deployment 32notes are private and live outside this repository. 33 34## What is where 35 36| Path | What | 37| --- | --- | 38| [cat/](cat/) | The mascots: who can be shown (`Mascot`), Ginger's and Bunny's art, the SVG and the CSS that plays it. The grey cat's art and the motion are `../crates/whiskers-art`. | 39| [site/](site/) | Configuration, the demo's choreography, and `jev`: what the page says about where Jev is used, built from the guard's own definitions. | 40| [worker/](worker/) | The Worker: routes, page, headers, logging, `wrangler.toml`. | 41| [previewgen/](previewgen/) | Draws the preview card and the video's frames as SVG, in lmjtfy's card look (`jev_ui::card`). | 42| [third-party/](third-party/) | The pixel icons the downloads and tables use: shuqikhor's (MIT) and SerenityOS's (BSD 2-Clause) unchanged, and the Android and arm marks drawn here. | 43| [tools/](tools/) | `build`, `preview`, `check-preview`, `preview-hash`. | 44 45The look (stylesheet, page shell, windows, fonts, Datastar, the link-preview tags) is `jev-ui` in 46[`~/jevcrates`](../third-party/jevcrates/jev-ui/), shared with lmjtfy.fun. 47 48## Sizes (measured 2026-10-04) 49 50Measured with `tools/check-preview` and `wrangler dev`.