main
tag: launch-2026-06-01
tag: magicmirror-v0.1.1
tag: magicmirror-v0.3.0
tag: mnw-cli-v0.1.2
tag: mnw-cli-v0.1.3
tag: mnw-cli-v0.1.4
tag: pom-v0.4.1
tag: pom-v0.4.2
tag: pom-v0.4.3
tag: pom-v0.4.4
tag: pom-v0.4.5
tag: wam-v0.3.0
tag: wam-v0.3.1
Files
Commits
Tags
Notes
Issues
Follow the Bespoke split, and say which of its regions owe a fill
Seven of this server's nine opaque regions are `Handover`: the five tab
panels, the version uploader, and the media transport. Each is a fill the
app owes every host, so a renderer without one is looking at a hole and
now says so instead of drawing an empty box.
Two are `Ceded`: the analytics charts, on the ruling this repo already
carries that a bar chart is not describable and should not be. Nothing is
owed there and silence is the right drawing.
The transport went `Handover` rather than `Ceded` on its own doc's
argument: "a handover for now, a widget eventually", naming the media
player as the first candidate to become one. A terminal shown nothing
there is missing content the reader wants, which is the distinction
`owed()` exists to carry.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01MptwXZ8k65v19rFmdGAyki
16 files changed,
+41 insertions,
-36 deletions
18
18
# `makeover-tui` is the terminal renderer, and its `theme` feature is the
19
19
# intents-to-ratatui-colours mapping. No hex value is written in this crate.
20
20
makeover = "3.0"
21
-
makeover-tui = { version = "0.42", features = ["theme"] }
21
+
makeover-tui = { version = "0.43", features = ["theme"] }
22
22
tokio = { version = "1.50.0", features = ["macros", "rt-multi-thread", "time", "sync", "signal", "fs"] }
23
23
# `rustls-no-provider` rather than `rustls`: the latter is an alias for
24
24
# `__rustls-aws-lc-rs`, which links a C crypto backend. The provider is ring
15
15
# selection; `makeover-tui` is the terminal renderer, and its `theme` feature is
16
16
# the intents-to-ratatui-colours mapping. No colour is named in this crate.
17
17
makeover = "3.0"
18
-
makeover-tui = { version = "0.42", features = ["theme"] }
18
+
makeover-tui = { version = "0.43", features = ["theme"] }
19
19
tokio = { version = "1", features = ["full"] }
20
20
# `rustls-no-provider` rather than `rustls`: the latter is an alias for
21
21
# `__rustls-aws-lc-rs`, which links a C crypto backend. The provider is ring
5406
5406
5407
5407
[[package]]
5408
5408
name = "makeover-layout"
5409
-
version = "0.42.0"
5409
+
version = "0.43.0"
5410
5410
5411
5411
[[package]]
5412
5412
name = "makeover-timing"
10771
10771
name = "makeover-tui"
10772
10772
version = "0.42.0"
10773
10773
10774
+
[[patch.unused]]
10775
+
name = "kberg"
10776
+
version = "0.1.0"
10777
+
10778
+
[[patch.unused]]
10779
+
name = "ops-status"
10780
+
version = "0.1.0"
10781
+
10782
+
[[patch.unused]]
10783
+
name = "painhours"
10784
+
version = "0.1.0"
10785
+
10774
10786
[[patch.unused]]
10775
10787
name = "quasi-immediate"
10776
10788
version = "0.97.0"
10786
10798
[[patch.unused]]
10787
10799
name = "quasi-tauri"
10788
10800
version = "0.97.0"
10789
-
10790
-
[[patch.unused]]
10791
-
name = "kberg"
10792
-
version = "0.1.0"
10793
-
10794
-
[[patch.unused]]
10795
-
name = "ops-status"
10796
-
version = "0.1.0"
10797
-
10798
-
[[patch.unused]]
10799
-
name = "painhours"
10800
-
version = "0.1.0"
168
168
# rather than reached through quasi-router's re-export because a described
169
169
# screen names FieldKind and Tone directly; it has to track what quasi-router
170
170
# resolves or the two `layout::` paths are different crates.
171
-
makeover-layout = "0.42"
171
+
makeover-layout = "0.43"
172
172
# The webview renderer's field emitter, called directly by
173
173
# `quasi::rich_field` so one markdown editor's markup comes from the same
174
174
# place a whole described screen's would. Pinned here rather than reached
175
175
# through quasi-webview for makeover-layout's reason: two `form::` paths from
176
176
# two resolutions are two crates, and the `data-format="markdown"` rules in
177
177
# `static/layout.css` are generated from this one.
178
-
makeover-webview = "0.71"
178
+
makeover-webview = "0.72"
179
179
# For the request head the per-viewer state factory reads. axum re-exports it,
180
180
# but the factory's signature is quasi-axum's and names `http::request::Parts`.
181
181
http = "1.3.1"
254
254
# Emits static/geometry.css (makeover-geometry) and static/layout.css
255
255
# (makeover-webview). The same generator GO and BB run; only the output paths
256
256
# differ, since the server serves its stylesheets rather than bundling them.
257
-
makeover-build = "0.64"
257
+
makeover-build = "0.65"
258
258
# Read directly for the embeds' own copy of the spacing layer, which they need
259
259
# because an iframe cannot link a stylesheet. makeover-build does not re-export
260
260
# it, so the pin lives here and has to track the one makeover-build resolves.
70
70
//! - **Disclosure.** The Guide section groups into `<details open><summary>`
71
71
//! subsections. No node says that, so the described version flattens them.
72
72
//! - **The search box.** The input, its results container and `docs-search.js`
73
-
//! are bespoke, so this screen needs a `Region::Bespoke` fill even though
73
+
//! are bespoke, so this screen needs a `Region::Handover` fill even though
74
74
//! phase 0 rated it furniture. Worth noting for the sizing: "furniture" was
75
75
//! read off templates, and this one turned out to carry a fill.
76
76
//!
241
241
242
242
/// The audio player: the card, with the transport in a bespoke region.
243
243
///
244
-
/// **Bespoke for now, widgets eventually.** A play button, a scrub bar and an
244
+
/// **A handover for now, a widget eventually.** A play button, a scrub bar and an
245
245
/// elapsed readout are a media transport, and the vocabulary names none of the
246
246
/// three on purpose — describing playback would
247
247
/// put scrub, rate and chapters into a core two of the three renderers could only
248
248
/// degrade. So this screen describes the chrome around the player and leaves the
249
-
/// player alone, which is exactly what a [`RegionKind::Bespoke`] is for.
249
+
/// player alone, which is exactly what a [`RegionKind::Handover`] is for: the
250
+
/// fill is owed, and a renderer without one should say so rather than draw an
251
+
/// empty box where the transport goes.
250
252
///
251
253
/// The markup and the script that fills it are [`player_markup`], unchanged from
252
254
/// the template this replaces.
264
266
265
267
Screen::single(&view.title).with(slot).with(Slot::new(
266
268
PLAYER_REGION,
267
-
RegionKind::Bespoke {
269
+
RegionKind::Handover {
268
270
name: "media-transport".into(),
269
271
},
270
272
))
271
273
}
272
274
273
-
/// The bespoke region the transport is mounted in.
275
+
/// The handover region the transport is mounted in.
274
276
pub const PLAYER_REGION: &str = "transport";
275
277
276
278
/// The player document: the described chrome, with the transport mounted.
15
15
//! cancel, a retry and an error surface, all of it client-side state.
16
16
//!
17
17
//! The table is described here. The upload machine stays markup, mounted as a
18
-
//! [`RegionKind::Bespoke`] region, which is what bespoke regions are for and
18
+
//! [`RegionKind::Handover`] region, which is what a handover is for and
19
19
//! what `super::user_analytics` already does with its chart. Describing a
20
20
//! progress machine is its own conversion with its own vocabulary questions,
21
21
//! and `138ad5ab`'s SCOPE says to split rather than widen. So it is split, and
216
216
217
217
// The upload machine, whatever state it is in. Below the table on an empty
218
218
// panel too, which is what "create your first version below" points at.
219
-
slot = slot.with(Node::Region(Slot::bespoke(UPLOADER_SLOT, "version-upload")));
219
+
slot = slot.with(Node::Region(Slot::handover(
220
+
UPLOADER_SLOT,
221
+
"version-upload",
222
+
)));
220
223
221
224
Node::Region(slot)
222
225
}
190
190
.showing_one(shown);
191
191
192
192
for (at, tab) in tabs.iter().enumerate() {
193
-
let mut region = Slot::bespoke(tab.panel, "item-panel").label(tab.label);
193
+
let mut region = Slot::handover(tab.panel, "item-panel").label(tab.label);
194
194
if at != shown {
195
195
// Every panel here is an Askama route, so every one of them needs to
196
196
// be told where its answer goes: a route that names no region leaves
8
8
//! # The panels are not described and are not meant to be
9
9
//!
10
10
//! Max's ruling: describe the strip, leave the panels as routes. So every tab is
11
-
//! a [`RegionKind::Bespoke`], a place and nothing else, and what lands in one
11
+
//! a [`RegionKind::Handover`], a place and nothing else, and what lands in one
12
12
//! is whatever its route already answered with. That is the honest kind for a
13
13
//! region whose contents are Askama's, and it is what lets the five panel routes
14
14
//! in `routes::pages::public` stay untouched.
167
167
.showing_one(0);
168
168
169
169
for (at, tab) in shown.iter().enumerate() {
170
-
let mut panel = Slot::bespoke(tab.panel, "library-panel").label(tab.label);
170
+
let mut panel = Slot::handover(tab.panel, "library-panel").label(tab.label);
171
171
if at > 0 {
172
172
let mut call = Action::get(tab.route).awaiting();
173
173
// Described routes name their own region and must be left to;
145
145
/// Markup for the bespoke regions this request's screen describes.
146
146
///
147
147
/// The seam between a handler and its renderer, and the reason it has to be
148
-
/// here rather than in either of them: a `Region::Bespoke` is filled on the
148
+
/// here rather than in either of them: a `Region::Handover` is filled on the
149
149
/// [`Webview`](quasi_webview::Webview), which quasi-axum builds *after* the
150
150
/// handler has answered, and the renderer factory is handed `&S` and the
151
151
/// answer. So the handler writes what it drew here and the renderer reads
124
124
} else {
125
125
// The description says only that there is a region here and what it is
126
126
// called; `drawn` puts the markup in it.
127
-
Node::Region(Slot::bespoke(CHART_SLOT, "revenue-chart"))
127
+
Node::Region(Slot::ceded(CHART_SLOT, "revenue-chart"))
128
128
});
129
129
130
130
out.push(Node::section("Top Performing Items"));
188
188
.showing_one(shown);
189
189
190
190
for (at, tab) in tabs.iter().enumerate() {
191
-
let mut region = Slot::bespoke(tab.panel, "project-panel").label(tab.label);
191
+
let mut region = Slot::handover(tab.panel, "project-panel").label(tab.label);
192
192
if at != shown {
193
193
// Every panel is an Askama route naming no region, so each is told
194
194
// where its answer goes or htmx swaps it into the pressed button.
259
259
.showing_one(shown);
260
260
261
261
for (at, section) in sections.iter().enumerate() {
262
-
let mut region = Slot::bespoke(section.panel, "settings-panel").label(section.label);
262
+
let mut region = Slot::handover(section.panel, "settings-panel").label(section.label);
263
263
if at != shown {
264
264
let mut call = Action::get(section.route).awaiting();
265
265
// A described route names its own region and must be left to. Same
24
24
//! 2. **A bar chart is not describable, and should not be.** makeover-layout
25
25
//! names no chart, and the admission test is that a node composes something
26
26
//! it already names. Inventing one there would be the layer naming a widget.
27
-
//! So the chart is a [`quasi_router::RegionKind::Bespoke`] fill, which is
27
+
//! So the chart is a [`quasi_router::RegionKind::Ceded`] fill, which is
28
28
//! exactly what bespoke regions are for, and it is the first one in the
29
29
//! tree. See [`chart_markup`].
30
30
//! 3. **A proportion bar inside a table cell is one site.** The comparison
278
278
} else {
279
279
// The chart's own markup arrives through the renderer. The description
280
280
// says only that there is a region here and what it is called.
281
-
slot.with(Node::Region(Slot::bespoke(CHART_SLOT, "revenue-chart")))
281
+
slot.with(Node::Region(Slot::ceded(CHART_SLOT, "revenue-chart")))
282
282
};
283
283
284
284
// One project is not a comparison, which is the condition the template
208
208
.showing_one(shown);
209
209
210
210
for (at, tab) in tabs.iter().enumerate() {
211
-
let mut region = Slot::bespoke(tab.panel, "user-panel").label(tab.label);
211
+
let mut region = Slot::handover(tab.panel, "user-panel").label(tab.label);
212
212
if at != shown {
213
213
let mut call = Action::get(format!("/dashboard/tabs/{}", tab.route)).awaiting();
214
214
// A described route names its own region and must be left to; an