jevcrates.git / jev-ui / README.md
README.mdpreviewREADME.mdsource105 lines · 6.0 KB · raw
1# Chapter 22: jev-ui — what the Jev sites' pages share
2
3lmjtfy.fun and whiskers.lmjtfy.fun look alike on purpose: near-black on white,
4one pink band, ordered-dither dot fields and old operating system windows with
5a black title bar, after typesafe.ai. This crate is the one copy of that look,
6so the second site did not get a second copy of it.
7
8It is the opposite of its neighbours in one way: nothing here talks to Jev.
9It is the page around whatever a site says.
10
11## What a site gets
12
13| From | What |
14| --- | --- |
15| `asset` | The files a page loads, embedded: `ui.css`, `ui.js` (the copy buttons and the dither fields), Datastar's `datastar.js`, the three fonts and a fourth, a small pixel-emoji font. `asset::find(path)` for a fallback route, `Asset::href()` for a link named by the hash of its bytes. |
16| `shell` | `document(head, body_attrs, body)`: the one head (title, preview tags, preloaded fonts, the shared sheet and script, Datastar) and the body's open and close. `Assets::Linked` for a site whose policy forbids inline script, `Assets::Inline` for one that does not. |
17| `components` | `nav`, `headline`, `window`, `sheet`, `band`, `copy_line`, `footer`, `skip_link`, the 12 by 12 `pixel_icon`, and SerenityOS's pixel emoji: `PixelEmoji` (play, pause, the two hourglasses), `pixel_emoji` and an `hourglass` that turns over (still under reduced motion). |
18| `preview` | `Preview`: Open Graph and Twitter tags that cannot be built wrong (an origin that is not https, a video of odd size, a card too small to be shown large), for a still card or a looping video, and `missing(html, kind)` to check a rendered page. |
19| `wire` | A call to Jev as a window: `json` prints a body from the raw text (whitespace added, nothing else), `exchange` is the folding request-and-response window, `bars` is lmjtfy's probability rule with an optional decision tick, `printed_json` reads a panel back for a test. |
20| `flow` | `spine`: a flow drawn as one SVG from rows of steps, each with the ways it can end. Built from the data it is given, so a site that builds the rows from the code that runs the flow cannot draw a step the code lacks. |
21| `card` | The preview card's look as SVG: `Chrome` (the dither, the pink band, the window with its title bar, in lmjtfy's measures), and pixel `text`. A site composes what goes inside the window. |
22
23A page, in whiskers' shape:
24
25```rust
26use jev_ui::components::{Link, Nav, band, nav, sheet, window};
27use jev_ui::shell::{Assets, Attr, Head, document};
28
29let head = Head { title: "Whiskers", meta: preview_tags, style: SITE_CSS, assets: Assets::Linked,
30                  datastar: true, icon: Some("/favicon.svg"), extra: maud::html! {} };
31let page = document(&head, &[Attr::new("data-signals", "{}")], body);
32```
33
34and in the Worker, every asset the crate owns in one route:
35
36```rust
37// as the router's fallback; `path` and `query` are the request's
38if let Some(asset) = jev_ui::asset::find(path) {
39    // content-type: asset.content_type, cache-control: asset.cache_control(query), body: asset.body
40}
41```
42
43## What is a parameter and what is not
44
45Everything a site differs in is a field: the title, the tags, the site's own
46stylesheet (it comes after the shared one), the nav's links, what sits between
47the name and the links, the footer's words, a picture's query. The look is not
48a parameter: there is one palette, light only, as typesafe.ai's is. A site
49that wants another look is not a Jev site.
50
51Fonts are served by the site itself, from this crate (Inter Tight, JetBrains
52Mono and VT323, all under the SIL Open Font License, see
53[assets/](assets/)). lmjtfy fetched them from Google Fonts; a Jev site makes no
54request to another site.
55
56## Try it
57
58```
59cargo test -p jev-ui
60cargo build -p jev-ui --target wasm32-unknown-unknown
61```
62
63## Moving lmjtfy onto it
64
65lmjtfy (`~/lmjtfy`) still carries its own copy of all of this, which is
66temporary debt: `apps/lmjtfy/src/page.css` and `page.js` (the shared half of
67each is this crate's `ui.css` and `ui.js`), `view.rs`'s `icon`, `nav`,
68`footer`, `clone_line`, `head` and `preview`, `ds-bundle/` (this crate's
69`datastar.js`, byte for byte), the Google Fonts link, and `packages/card`'s
70palette, dither and pixel text. To move it:
71
721. Move `third-party/jevcrates` to a commit with `jev-ui`; depend on it by path.
732. Delete the shared half of `page.css` and `page.js`; what remains
74   (transcript, feed, rules diagram, code pages, toasts) is lmjtfy's `Head.style`
75   and its own script. Its `.bar-title`, `.win`, `.share` and the rest already
76   mean the same thing here.
773. Replace `view.rs`'s head and footer with `shell::document` and
78   `components::footer`, with `Assets::Inline`, and its `preview` with
79   `preview::Preview` (a `?q=` card is `Picture { query: Some("q=…&a=…") }`).
804. Serve `jev_ui::asset::find` as a fallback instead of `/datastar.js`, and drop
81   the Google Fonts `preconnect` and `link`.
825. Hold lmjtfy's page tests to the same checks, then delete `ds-bundle/`.
83
84## Outstanding
85
86- [ ] Move lmjtfy onto this crate (the steps above), then delete its copies.
87- [ ] `packages/card` draws lmjtfy's own card straight into a PNG with the
88      same palette, dither and pixel text as `card.rs`; once lmjtfy depends on
89      this crate, one of the two should draw from the other.
90- [ ] lmjtfy's tool-call panels and bars (`view.rs`: `json`, `node`, `choice`, `jev_card`) are the same markup as `wire`; lmjtfy's `.rete` diagram is Rete-specific and stays its own, but its CSS box language is what `flow` borrows.
91- [ ] Mermaid (lmjtfy's code pages) is still fetched from jsdelivr there; it is
92      not part of this crate.
93
94## For the people who maintain it
95
96### In this folder
97
98| Path | What |
99| --- | --- |
100| [src/](src/) | The code: Chapter 22½. |
101| [assets/](assets/) | The stylesheet, the script, Datastar and the fonts: Chapter 22¾. |
102| [Cargo.toml](Cargo.toml) | Dependencies: `maud` and `font8x8` only. |
103| [CLAUDE.md](CLAUDE.md) | Invariants for agents. |
104
105← Previous: [Chapter 21½: inside jev-mock/src](../jev-mock/src/) · Up: [jevcrates](../) · Next: [Chapter 22½: inside jev-ui/src](src/) →