The homepage brief as an RFC: what "/" should show instead of the
repository list, which of the System page's metrics get a sparkline and
which only a cell, how the repository mosaic and its bar strip are built,
and under which constraints the implementation runs.
Written in German on purpose — it states the assignment, not the
solution; the PR-doc will be English again.
The four accepted artboards of the "Werkbank" direction are checked in
under 0003-homepage/drafts/ so the RFC survives its scratchpad.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
D1 bis D4 ersetzen den Abschnitt "Offene Fragen": die Balken kommen als
neues Feld aus RepoOverviews, "/" wird die Startseite und Latest zieht
auf "/latest", die Startseite gilt auch bei einem Repository, und ein
privates Repository traegt den Streifen ohne Beschriftung.
Dazu ein eigener Abschnitt zum umschaltbaren Dark Mode: dunkel gibt es
schon, nur entscheidet heute allein der Browser -- neu ist der Schalter,
und der beruehrt jede Seite.
Korrigiert ist ausserdem, was "/" heute wirklich zeigt: nicht die
Repository-Liste, sondern Latest Builds des bedienten Repositories.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Vorschlag sagte weiter "statt der Repository-Liste", das Mosaik
liess das private Repository ohne Streifen, der Header hiess
"unveraendert" obwohl D2 und der Dark-Mode-Knopf ihn anfassen, die
Schiene stand mit vier festen Zeilen da statt mit einer je Platte, und
der Entwurfsabschnitt vermutete, Dark Mode muesse erst eingefuehrt
werden -- es gibt ihn.
Dazu zwei Ergaenzungen im Dark-Mode-Abschnitt: color-scheme muss der
getroffenen Wahl folgen, und homeUrl meint heute die Latest-Seite, nicht
die Startseite.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Fusszeile ist inhaltsbreit und sitzt unter beiden Spalten, die
Startseite traegt das Watcher-Banner aber nicht die Repository-Zeile,
und sortiert wird nach neuester Aktivitaet -- Dringlichkeit zeigt die
Farbe, nicht die Position.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die vermeintliche Spannung zwischen D4 und PR#49 loest sich anders auf
als gedacht: history und latest geben fuer ein privates Repository
status, startedAt und durationSeconds der ganzen Historie heraus, also
genau das, was der Kommentar an durations als Geheimnis benennt. Nicht
der Balkenstreifen faellt aus der Reihe, sondern die Begruendung.
Die Regel wird ausgeschrieben: sichtbar ist, dass gebaut wird, wann und
wie lange -- nie, was. Die leere Liste an durations bleibt, mit der
zutreffenden Begruendung; die Invariante kommt nach AGENTS.md. Beides
als Additional Change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Namen sind ausdruecklich Inhalt: Repository, Branches, Build-
Definitionen, Commits, Artefakte. Metadaten sind ausdruecklich offen:
Build-Zeiten, Ausgaenge, Speicherplatzgroessen und jede andere
aggregierte Kennzahl. Damit ist die vollstaendige Zeitreihe an
history gewollt und nicht nur geduldet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Name eines privaten Repositories ist redigiert, aber bestaetigbar:
ein geratener Name antwortet mit 200, ein erfundener mit 404. Nach D8
ist der Name Inhalt, also geheim. Kuenftig antworten alle
repository-skopierten Routen ohne Control-Token wie fuer einen
unbekannten Namen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Redacting hid the contents of a private repository but not its name: a guessed
name answered 200 with redacted rows while an invented one answered 404, so the
routes confirmed the existence of exactly what D8 calls secret above all.
The named routes -- /repos/<name>/... and /api/repos/<name>/... -- now answer a
visitor without the control token with the same 404 an unserved name gets. The
unscoped form is untouched: it names nothing, and it permanently means the served
repository (ADR 0009).
The resolution now lives in one place, RepoRouting, instead of three copies of
repoOf plus three copies of the privacy check, so the two cannot drift apart.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The rule from D8 -- metadata of a private repository are given out, its content
never is, and its name is content -- goes into AGENTS.md, so the next PR does not
decide it differently again.
Two texts said something else and are corrected rather than kept: the rationale on
GET /api/builds/durations claimed the timings themselves were the secret, which its
own neighbours disprove (the empty list stays, for the real reason -- a trend card
is grouped by build definition, and redacted every card carries the same label);
and the PR#53 doc said the change had been squashed without its PR-doc, when commit
bbb892f reached main without any pull request at all.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The home page's card carries a bar strip -- height is duration, colour is outcome
-- and it needs one number per build, not a trend. RepoOverviewDto grows a
recentBuilds list of exactly that, so a single GET /api/repos feeds the whole
mosaic and the page polls like every other page.
GET /api/builds/durations is untouched: it aggregates per build definition over
thirty days, which is the History page's trend, not the last twelve runs.
The strip survives redaction (D4): duration and outcome are metadata a private
repository hands out (D8); what it loses with the name are the labels.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`/` becomes the instance's home page and the repository's Latest view moves to
`/latest` (D2). The invariant that the unscoped routes mean the served repository
is untouched: /latest, /branches and /history still do, only `/` now belongs to
the instance. The wordmark leads there, and the navigation gains a Home entry.
The page is the "Werkbank" draft of RFC 0003: a 288 px system rail left -- the
verdict, one row per gauge of the system page and four smaller tiles, each row a
link into it -- and the repository mosaic right, one card per repository with its
tags, its newest build and the bar strip of its last twelve builds.
D3 it appears with one served repository too; the single card takes the whole
width, and /repos still redirects to `/`.
D4 a private repository keeps its strip, unlabelled, and stays a card without
a destination.
D5 the footer sits outside the two-column grid, so it spans both at content width.
D6 no tabs, no h1, no repository line -- but the watcher banner, because a calm
mosaic over an unreachable origin would lie.
D7 newest activity first, like the Repositories page: attention is a tint, never
a new position, so the grid does not reorder under the reader's mouse.
The sparklines are the one thing the server does not draw; werkator.js fills them
from GET /api/system/history, as it already does for the system page's gauges.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
werkator.js polls GET /api/repos and GET /api/system on the table interval and
re-renders the mosaic and the rail's values from the data; the sparklines follow
once a minute from GET /api/system/history?range=24h.
The curves are drawn by drawSpark, the same function the system page's charts use,
which now takes its box from the element's own viewBox instead of assuming
300x120 -- one curve to keep right rather than two. The rail passes no total, so
it carries no threshold lines: at 150x26 a level line is a smudge, and the values
next to the graph are the readable part.
renderHomeCard mirrors home.html exactly, and barStrip, cardTone and homeMeta are
the twins of HomeBarView.strip, HomeCardView.toneOf and HomeTexts.
Two layout fixes found while looking at the page: a rail row needs min-width 0 or
the grid track grows to the sparkline's intrinsic width and pushes the value out
of the card, and the phone lays the gauge rows out two per line like the draft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Dark has existed for every page since RFC 0001, but only as
@media (prefers-color-scheme: dark): the browser decided and the reader could not.
New is the switch, not the mode.
The browser stays the default; a button in the header's row of instance controls
overrules it and the choice is kept in that browser alone -- no account, no
request, and the stylesheet's tokens are still the only place a colour is written.
The choice is applied by a tiny inline script in `head`, before the first paint,
or the page would flash the browser's preference first. color-scheme travels with
it, otherwise form controls and scrollbars keep the browser's idea of light and
dark while the page shows the opposite.
The dark palette therefore stands twice -- once per path -- because CSS cannot
share a token list between a media query and a plain selector, and this project
has no frontend build. DarkModeTokensTest compares the two blocks, so a colour
changed in one and forgotten in the other fails the build instead of showing up
for half the readers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The PR is #54, so the scenario ids become Scenario#54.01 to .09 and the PR-doc
carries the number rather than the PR#000 placeholder.
AGENTS.md and the architecture skill learn the three things that changed under
them: `/` is the instance's page and the unscoped routes are the named ones
without a repository segment, the header's wordmark leads home and its navigation
gained Home and the theme button, and the dark palette now exists twice on
purpose.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
With one served repository that root was `/`, which is now the home page: the
single card on the mosaic pointed at the page it sits on. The rail's rows lose
their `#<key>` fragment for the same reason -- the system page's cards carry
data-gauge, not ids, so it was a dead anchor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The template separates the two with whitespace, werkator.js appends two elements
with none -- so the card read "home-pagedf955a7" the moment the first poll
re-rendered it. A margin on the code element makes both paths agree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three corrections to the home page.
The rail was a heading-less column beside one that had a heading, so the two
started at different heights. The mosaic now sits in a panel built exactly like
the rail -- header strip, summary row, content, footer -- and the words it used to
carry in a loose line are redistributed into it: "newest activity first" into the
header, "6 served" into the summary row, worded as on the Repositories page.
The rail's graphs get a quarter more height, which is what makes them readable
enough to be worth the click they invite.
And the mosaic fits as many cards per row as there is room for, instead of three
whatever the window. Below 1000 px the rail's fixed 288 px costs more than it is
worth -- the cards would be down to one per row while the rail sits half empty
beside them -- so it moves on top at full width and lays its rows out across.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The document was written in German because it was a brief rather than a
description of a finished thing. It is now the record of what was built, so it
follows the repository's rule like every other document, and the note explaining
the exception goes with it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The mosaic keeps its natural height and the rail stretches to it, so the two
columns end where they end together instead of the rail stopping halfway down.
The gauge rows absorb the difference: their sparklines grow from 33 px to
whatever the row became, capped at 110 px -- a tall mosaic would otherwise blow
one of them up to a few hundred pixels, which is a chart, and the rail is not
where charts are read.
A short mosaic gets no blank tail: it is align-self: start, so it never stretches
to a rail that happens to be taller than it.
The stacked layouts below 1000 px have no row to stretch into and keep their
fixed heights.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each box is now the metric's full scale: a disk at 52 % stands at half height, and
two disks at the same percentage look the same because they are the same.
Normalising every series to its own maximum made a quiet one fill the box and
claim something it did not mean -- SSD and HDD were indistinguishable although one
is half full and the other a third. Pressure takes 100 %, load the machine's
threads.
Two things drawSpark draws for the system page are left out here, through a new
options argument, so /system is untouched: the dashed 80/90 % lines, which at
60 px sit a dozen pixels apart and read as noise, and the per-bucket maxima line,
which the 24 h range does carry -- and which was worse than noise in the rail,
because .spark-max is styled under .spark only, so an unstyled polyline was being
painted as a black filled shape. That was the heavy spiky area in the CPU graph.
The level colouring of the curve stays and now has its rail colours.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The house gap of 56 px is measured for a page that ends in a table or a paragraph.
Under the home page's bordered panels it reads as a hole, so it is 28 px there --
scoped to this page, so no other one moves.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mi
merged commit 024d6311df into main2026-09-11 12:22:29 +02:00
mi
deleted branch home-page2026-09-11 12:22:29 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
`/` becomes the instance's home page and the repository's Latest view moves to `/latest` (D2). The invariant that the unscoped routes mean the served repository is untouched: /latest, /branches and /history still do, only `/` now belongs to the instance. The wordmark leads there, and the navigation gains a Home entry. The page is the "Werkbank" draft of RFC 0003: a 288 px system rail left -- the verdict, one row per gauge of the system page and four smaller tiles, each row a link into it -- and the repository mosaic right, one card per repository with its tags, its newest build and the bar strip of its last twelve builds. D3 it appears with one served repository too; the single card takes the whole width, and /repos still redirects to `/`. D4 a private repository keeps its strip, unlabelled, and stays a card without a destination. D5 the footer sits outside the two-column grid, so it spans both at content width. D6 no tabs, no h1, no repository line -- but the watcher banner, because a calm mosaic over an unreachable origin would lie. D7 newest activity first, like the Repositories page: attention is a tint, never a new position, so the grid does not reorder under the reader's mouse. The sparklines are the one thing the server does not draw; werkator.js fills them from GET /api/system/history, as it already does for the system page's gauges. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>