Public: anyone can read this; the crew can change it.

The studio's stylesheet belongs in the stylesheet, not in every page #166

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`studioCss` and `boardCss` now live in the served stylesheet instead of in a `<style>` block on every page that draws them.

shipped production is serving it deploy d63cf43

opened this

studioCss and boardCss now live in the served stylesheet instead of in a <style> block on every page that draws them.

What moved. studioCss (4,587 bytes, sent by nine studio pages plus /apps) and boardCss (13,744 bytes, sent by the board) join css in src/web/style.ts, in the components layer, last — after avatarHues, before content. An inline block sits outside every layer and therefore beats all of them, so last in components is the nearest place that reads the same; I checked it selector by selector before moving anything. Nothing else in the sheet styles a .studio- or .board- selector, and the four rules that reach a shared class — .badge[data-variant="accent"], .studio-asks .row-lead, .studio-head .env-facts, .board-run .avatar — set properties those components do not, or out-specify them in either arrangement. The rule text is unchanged: I diffed both blocks, whitespace-normalised, against what the pages used to send, and they are identical.

The trade, in numbers. The sheet grows from 94,585 to 112,970 bytes (+18,385), cached with an ETag and immutable once #113 lands; a studio app page sheds 4,587 bytes of CSS plus the <style nonce> wrapper, on every request, and the board sheds 13,744. styleCss stays for what its doc names — labelCss, colours mixed from the labels actually on the page — and its doc now says so explicitly.

Look at this. One test, a finished run renders in the studio's own word, asserted data-word="look". The badge on that page has always read waiting ("no deploy of this head yet"); what matched was .studio-list li[data-word="look"] inside the inline stylesheet. The test was wrong, not the code — I confirmed the rendered word is waiting on main too — so it now asserts the badge itself (data-word="waiting" id="run-word") and that the word is not planned, which is what a run whose pull was not found would say.

What I did not do. bulkCss came along: it is generated from the bulk-action table at module load but is the same for every request, so it belongs with the rest. mapCss (src/web/pages/map.ts, still passed as styleCss from two places) is the same kind of static block and the same fix, but it is a different surface with its own cascade checks to do, and the issue scoped this to the studio and the board — worth its own issue. I also left shell, rail and most of rows in place: the doc comment says nothing draws them any more, and deleting a rule changes what is served, which is not this change.

How to try it. curl -s $PREVIEW/assets/forge.css | grep -c studio- finds the rules in the sheet; view source on the studio home, an app page, /apps or /board and there is no <style> element; open an issue with a label and there still is one, holding only its lc- rule. bun x tsc --noEmit is clean and the check's test list is green apart from six failures that are identical on main in this sandbox (they spawn git over SSH, which this environment refuses).

🤖 Generated with Claude Code

Closes #155

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs