Prototype: the Cinder admin surface #122
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #114
Blocked by: #115
Question
What does a dense operations view look like without leaving Cinder?
Cinder pins one
--measure: 760pxcolumn and forbids cards, corners, and shadows; tokens are the:rootblock inbackend/internal/web/static/style.css, and the source of truth for the visuallanguage is the Claude Design project
BookmarkManager Web UI(
969ac210-fe02-4c01-ae1b-9a271dcc779a). A conventional dashboard grid violates all of it, andthe whole reason this map exists is that the current page does not read as an operations surface.
Settled: this is an explicit extension of Cinder, negotiated in that project — not a second
visual language.
Make a rough, concrete artifact to react to: the summary line, a Lane block, a Series list row
carrying several facts and an action, and the Series detail page. Then decide:
.confirm-row) survives at list density.--embermeansnew chapter only, destruction gets
--danger, both colour branches touched together.Link the prototype from this issue rather than pasting it.
Added by #115
The surface to prototype is four pages behind one nav row (
Overview · Lanes · Readers · Series,beside the existing
Libraryghost link), not one stacked page:/admin(summary line, stats block,per-Site table),
/admin/lanes,/admin/readers,/admin/series(filterable list), and/admin/series/{key}(detail plus intervention). The open visual questions are the density of theper-Site table and the stats block, and how the nav row reads in Cinder; the phone viewport follows
whatever density this settles.
From #119 (closed), two controls the prototype now has to carry: a Series row with Check now (not confirm-gated) plus an ageing pending marker
check requested <age> agoand no ETA; and a Lane row with a pause duration picker (1h/6h/24h), Pause, and Resume on an already-paused row. A paused Lane must read as paused rather than as stalled or quiet. Accent is the existing.attentionclass — never--ember, never--danger.sulthan referenced this issue2026-08-18 06:59:54 +07:00
Added by #118 (closed) — the Series list frame is now specified, so the prototype has a frame to
fill rather than invent:
SeriesFilter.Filterholds one value), theactive one marked with the existing
.attentionclass, plus an All series reset.?site=and
?kind=are separate controls that stack on top. Never--ember, never--danger.<N> series · <label>, using #116'sCOUNT(*) OVER ()total."nothing here".
No Readers, Never checked, Not checked in 12h, No cover, Latest from a Reader — plus library
size, the manga/novel split and the roster count. Every figure is a link to what it counts,
except a zero, which prints the digit unlinked. That asymmetry is the thing to get right
visually: a zero must still read as a measured fact, not as a disabled control.
SeriesRowfields a row renders, in what order, at whatdensity, alongside #119's Check now and its ageing pending marker.
Surface added by #121 (closed) — both controls on the Series detail page (
/admin/series/{key}), never on the list row:--ember, no--danger.series_urlrepair, rejected400when it failslatest.FetchableSeriesURL. The owner presses Check now (#119) afterwards — the repair itself fetches nothing, so the page must not imply it did.corrected <age> agomarker whilelatest_corrected_at > 0, i.e. while the live value is a human's. It is erased by the next machine write of the number, so the marker is transient by design and must not read like history.Both post to
POST /admin/series/{key}/<verb>and answer with the swapped detail fragment (#115's shape). Density and field layout are still your call.Prototype up: branch
prototype/admin-surface-122, filebackend/internal/web/templates/admin-prototype.html.Run:
cd backend/internal/web/templates && python3 -m http.server 8731, then openhttp://127.0.0.1:8731/admin-prototype.html?variant=A(switch A/B/C via the floating bar or?variant=, keyboard ←/→).Three structural variants answering the ticket's question:
--measure-wide: 1080px): borderless grid table, hairline column header, per-column alignment. Reads as a table without a card.Content draws from the closed tickets: overview verdict line (#117), seven filter figures with zero unlinked (#118), lane pause picker 1h/6h/24h + Resume (#119), Check now unconfirmed + pending marker (#120), numeric chapter + series_url correction forms with transient markers (#121), per-row confirm-gating sketched for orphan removal (#125).
Four decisions the ticket leaves open — verdict wanted from the owner:
--measure-widetoken?--measure-wideonly, or anything else? (Core law untouched: no ember anywhere on admin.)Verified in a real browser: all three variants render, lane states, detail correction forms, empty state, zero figures unlinked, confirm-gating reachable in all variants, phone-width collapse, hash navigation.
Round 1 review addressed (commit
f988e68, branchprototype/admin-surface-122):<use>mirror — rendered as a lopsided single page). Now byte-identical to the chrome.html mark.All verified in a real browser. Four decisions from the ticket still open — verdict wanted:
--measure-wide: 1080pxalongside the 760 reading column?--measure-wideonly, ember nowhere on admin?Resolved in the Claude Design project BookmarkManager Web UI (
969ac210-fe02-4c01-ae1b-9a271dcc779a):admin.cssplusadmin-overview.html,admin-lanes.html,admin-readers.html,admin-series.html,admin-series-detail.html. Those five pages supersede the three-variant sketch on branchprototype/admin-surface-122— variant B won, A and C are dropped, and the branch stays only as the exploration record. Port from the design project, not fromadmin-prototype.html.The four decisions
--measure-wide: 1080pxalongside an unchanged--measure: 760px. The admin.sheetmaxes at the wide one; every reading page keeps the 760px column. Admin is the only consumer..tbl), a hairline.theadof mono uppercase labels, hairline row rules, no vertical rules, no card backgrounds, no corners. Gutters are cell padding, nevercolumn-gap(a gap slices the row rule into segments and reads as a ragged edge). Figures arefont-variant-numeric: tabular-nums, 15px mono mixed case at ~0 tracking — uppercase-at-.1emis for labels and marks only. Titles stay in the display face (18px)..tbl.seriesrows aredisplay: grid; grid-column: 1 / -1; grid-template-columns: subgrid, title on its own full-width line, facts on the subgrid line under it, so a long title never breaks column rhythm. Separation is banding (.trow.band { background: var(--hover) }), not hairlines, so a title and its facts read as one record;.bandis a class, not:nth-of-type, because collapsed confirm rows are.trowsiblings and would throw the alternation off..tbl.lanes) and the landing per-Site table (.tbl.sites) are single-line B rows. Site numerics are centred, not right-flushed: at 106px a right-flushed figure loses its header.+Ntail rather than stacking..c-actholds 12px.ghostlinks flush right, hover in--patina. Check now is unconfirmed, and its ageing pending marker (requested 3m ago) renders once, on the title line flush right above the actions — not under the action, which added a second line to every row. Destructive actions are.ghost.dangerand open an in-place.confirm-row: a full-width grid row on--danger-washwith Keep / Remove, shippinghiddenand unmounted (.tbl.series .trow:has(> .confirm-row[hidden]) { display: none }, else every orphan printed an empty striped band).--measure-wideis the only addition. Everything else is existing Cinder:--patinafor the admin accent and active filters,--dangerfor lane problems and destruction,--hoverfor banding,--hatchfor the cover placeholder, the six per-Site hue tokens on the site cell. No--emberanywhere on admin — the only ember on the page is the brand glyph, unchanged. Both colour branches are in the file.Also settled by the artifact
Overview · Lanes · Readers · Series) under the topbar, active tab underlined in--paper;Library+Log outgroup as a right-aligned cluster in the topbar..secmono uppercase led by a 34px--patinatick, not a full-width hairline — stacked rules between Hygiene / Library / Sites competed with the tables' own rules.--patinaphrase plus--paperfigures, hairline under..stats):repeat(auto-fit, minmax(232px, 1fr))across the full measure, one rule on the block; every figure links, a zero is.fig.zeroin--muteand unlinked.Outcomes · state/ controls. Browser reachability is a.statuslinepinned to the section-heading line, not a paragraph of explanation. A trouble state (refusing,no browser,not checking) renders--danger; a deliberate pause stays--patina(paused · resumes in 3h). The pause select (1h/6h/24h) + Pause live in.pausebar, and Resume replaces them in the same slot.site:series_id · site · kind, a 160px--hatchcover, an uppercase mono meta row carrying the marks, then a two-column.detail-gridof the #121 forms (numeric Set chapter; url Save) with Check now below. All unconfirmed.deferral blockedchip cannot make one row taller.Amendment to #118
The Series filter row is not eight plain links. Eight hygiene labels do not read as a chip row, so the filter is a
<select>whose option labels carry their counts (No cover (3)), Site is a second select, and kind is a three-way.segrow(both / manga / novels) marked active in--patina. Filters remain one-at-a-time and URL-addressable exactly as #118 specified — only the control changed. Heading, empty state and the linked-figures-except-zero rule are unchanged.Fog cleared
"The admin surface on a phone" is answered by the breakpoints above and leaves the map's Not yet specified.
Amendment from #124 (closed) — two things land on the surface you prototyped:
card.html:58-59): Finish is confirm-gated — press reveals a.confirm-rowreading Mark this Series finished? with Finish / Cancel — while un-finish fires instantly, exactly like Restore, because it is the reversal and destroys nothing.--danger. You reserved that for lane trouble and destruction, and a finish takes nothing away: no bytes, no row, no Bookmark. It uses--patina, the admin accent. Un-finish likewise.SeriesRow.FinishedAtis projected either way) — a scan tells you which rows are finished; it just offers no one-press way to finish the wrong one.<select>are unchanged; your row shape is unchanged.--moss(card.html:35-37,style.css:87), which the new reader-visible finished label reuses in the web card and both userscript rows. Purely a label — no tab, no filter, no reordering, no ember interaction.sulthan referenced this issue2026-08-20 20:32:21 +07:00
Additions from #127 (closed):
<outcome word> · failing <age>in--danger, rendered whenever the Series has a row in the newpoll_failurestable. Never--ember, consistent with your no-ember-on-admin rule;--dangerfollows your own use of it for lane trouble.failingfilter only. A second visual state would ask the owner to learn a rule the line cannot state in a word, and the age is already on the line.unverifiedcase./admin/series?site=<site>&filter=failing, as navigation and not attached to any of the outcome counts, which stay unlinked (see #118). Your five outcome counts also become six:not_foundsplits out oferrors.<select>grows to eleven options: #127 addsfailingandunverified.