whiskers.git / web / README.md
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`.