Lossless Changelog
product

Every project gets a face, and none of them is the Astro logo

Seven rows of the ledger wore the Astro scaffold's logo as if it were a brand, one mark was invalid XML that no browser would draw, and a white plate sat behind all of them on a page with only a dark mode.

Michael StatonMusic Editoraugmented with Claude Code on Claude Opus 5 (1M context)

Every project gets a face, and none of them is the Astro logo

Why Care?

The project ledger is a list of forty things. A mark beside each name is what lets you find the row you want without reading. That only works if the marks are different from each other and visible, and until today a third of them were neither.

Seven rows carried the same 749-byte file. Six more rendered as a browser's broken-image placeholder. Every mark in the column sat on a near-white square on a page that has exactly one mode, and it is dark.

Forty streams, thirty-nine after this entry. Twenty-four now have a mark.

What's New?

  • The Astro scaffold's logo is no longer mistaken for a brand. Seven streams were showing it.

  • No plate behind the marks. They carry their own grounds.

  • Six marks drawn here for projects that never drew their own, in src/marks/ — a placeholder tier that loses automatically to a real favicon.

  • This site has a favicon: the ledger strip, five bars sampling the era ramp.

  • icon: in streams.yaml — an explicit override for repos whose real mark is not where the search looks.

  • Neo is removed from the manifest.

How it Works

The scaffold logo is not a mark

create astro writes the same public/favicon.svg into every new site. A site that never replaced it still has that file, so sync-icons.mjs found one, stopped looking, and copied the Astro logo in as the project's brand. Seven streams, all byte-identical — which is how it was caught.

The fix is a signature set keyed on the file with whitespace collapsed, so a reformat upstream cannot slip a fresh copy past it. A new Astro release that redraws the logo will need its signature added; the symptom is several rows suddenly sharing one mark again.

Three of the seven had a real mark all along, just not at the default path. Banner Site keeps its under public/brand/, The Water Foundation under an appIcon__ name, Cilantro under a Parslee one. Those are now declared outright rather than guessed at, because the guess-it heuristic already has one recorded near-miss: hypernova-site holds two favicon__The-Water-Foundation*.svg files left over from a different client, and taking those would have put the wrong brand on the wrong row.

A fallback for one group only

Astro Knots sites that still have no mark of their own fall back to the Astro Knots mark. They are one family built from one set of conventions, so the family mark reads as one of these rather than as a placeholder.

No other group falls back. Repeating the AI Labs mark down its children would only assert that they share a parent directory, which the nesting already shows.

In practice the fallback now fires for nothing, because every Astro Knots row has its own mark or a drawn one. It stays for the next site that has neither.

Under the Hood

Three faults, and only the first was the one being looked for.

-- is illegal inside an XML comment

astro-knots.svg carried a comment reading matches --color-accent → --color-thread. XML forbids -- inside a comment, so the entire file was unparseable and no browser would draw it. It looks perfectly correct in an editor.

That is the six broken-image squares: the mark had never rendered, and the new group fallback then pointed nine rows at it at once. Repaired at the source in astro-knots/splash/public/favicon.svg, and the sync now refuses to copy an SVG it cannot parse — a well-formedness check for the two faults that actually bite, not a validator.

The white squares were CSS, not the icons

Not one icon in the set has a white ground baked in. ProjectRow.astro painted background: var(--color-text) behind every mark — a near-white plate, on a dark-only page. Transparent marks showed the plate and read as white tiles.

Removing the plate would have erased Banner Site

Its flag is drawn in currentColor. Inside an <img>, currentColor resolves to the SVG document's own default, which is black — so the mark was legible only because of the plate that had to go.

CSS cannot reach inside an <img>, so the substitution happens at sync time, on the copy: a monochrome mark gets color="#e2f2f4" set on its root. Nothing that specifies its own colours is touched.

Verifying this needed a browser, not a rasterizer

qlmanage -t on an SVG bakes transparency to white, which makes a transparent ground and a white plate look identical — exactly the distinction under question. Two rounds of contact sheets proved nothing.

What works is thumbnailing an HTML page that embeds the marks at their real 15px over #0d1117. That goes through WebKit, so alpha, gradients and currentColor all resolve the way the page will resolve them.

Files Touched

  • scripts/sync-icons.mjs — stock-logo denylist, XML well-formedness gate, currentColor ink substitution, src/marks/ fill pass

  • src/lib/groups.ts — iconOrGroup, scoped to the Astro Knots family

  • src/components/ProjectRow.astro — the plate is gone

  • src/config/streams.yaml — the icon: field; Neo removed

  • src/marks/ — six drawn stand-ins

  • public/favicon.svg — the ledger strip

Also in this Push

Numbers refreshed across all four syncs: 456 entries, 5,640 commits, 3,261,832 authored lines — code 60.6%, content 19.8%, context-v 14.1%, changelog 5.5%, with 722,605 dropped as lockfiles and vendored. 320 active days, 127 of them above ten commits.

Neo is gone from the manifest. It had one entry and no local clone, so it had been contributing to the entry count and to neither of the other two — the totals above are unchanged by its removal, which is the tell.

What's Next

  • Fifteen streams still have no mark, mostly the content-farm plugins. The drawn-here tier makes that cheap to fix whenever it is worth doing.

  • parslee is now the last inert stream — declared, disabled, zero entries upstream, no clone. Same shape as what Neo was.

  • The stock-logo signature is Astro 5.x's. It will need company eventually.