chrome: give a service its own navigation row The switcher lists the instance's services, each on an origin of its own. Three artifacts pages rode ExtraNav into it, so that row's membership changed from service to service and its active element - spent naming "artifacts" - said nothing about which of the three the reader was on. Sections is the second row instead, the one upstream draws as .header-tabbed wrapping .nav.nav-tabs and meta puts profile and keys in. A service declares its sections at startup; Page marks the one the request's path stands in, so a page cannot forget to declare itself, and a path in no section lights nothing rather than the first tab. Both classes arrive with core.sr.ht's nav.scss, so the row costs no service any CSS. ExtraNav is deprecated with it: bench and cov abandoned it when the instance deployed a tokens.sr.ht and the word appeared in the navbar twice, and artifacts was its last user.
chrome: a default favicon, optional listing columns, and a table partial Three services asked for a favicon field and bench argued against one: it ships no icon deliberately, and its layout says why — a <link rel="icon"> pointing at an asset the binary does not have is a 404 on every page load, for a file nobody asked for. A default that is a path hands that to every service without a logo, so the default carries its own bytes instead: the brand's ring as a data: URI, which cannot 404 and costs no request. It is a template.URL because html/template rewrites any href whose scheme is not http, https or mailto to "#ZgotmplZ" — the type is how a caller says it meant a data: URI. Updated and Meta are optional for the reason the four listing services could not agree: bench and spec have a modification time, dolt's schema has no timestamp at all, and cover's index is a table of sparklines no shared partial will render. A required column would have pushed dolt back onto a local copy. Updated is a time.Time so the partial renders "3 hours ago" with the exact stamp in the title once, rather than five services spelling it five ways. srht-repo-table is a second partial over the same dot rather than a variadic first one: growing columns on the cards would have made them worse cards for the services that wanted cards. Attach now installs Funcs itself, because the partials call reltime and abstime and an unknown function is a parse error — a caller who had not merged Funcs would have got a startup panic naming a template it never wrote. pages consequently attaches before layering the service's own map on top, which is what keeps a deliberate shadow working.
chrome: shared page chrome for the instance's custom services Extract the nav/chrome idiom that compare, spec, dolt and cover each carried as a private copy (and bench was about to fork as a sixth): BuildNav over the shared config.ini with the canonical ordering and paste/pages/hub exclusions, a per-request Page with login/logout/profile URLs against meta's unified login, embedded srht-nav / srht-env-banner partials (circle brand + red service label + switcher + login box), and the generic dict/shortsha template helpers. Policy decisions the copies had drifted on are baked in: switcher only for authenticated viewers, hub excluded in the builder rather than the template, profile link prefers hub's ~username page, environment name uppercased for the banner. Service-specific needs surfaced by the cover survey get seams instead of copies: ExtraNav for extra switcher entries, ContainerClass for full-bleed pages, the config section as an explicit parameter for the active check.