The Angelulz brand is the look shared by my sites and self-hosted services: a hooded angel called the Warden, a smaller Sentinel for icons, a ring-shaped sigil and a dark palette. The Brand page shows what it looks like. This page is about how it’s kept: as code, in one small repository, which every surface copies at a fixed commit.
The problem
In September 2026 I wanted one new look across the file-sync service, the documentation, the status page and the home dashboard, and one logo used everywhere from then on. Each of those carried its own colours: the stylesheets for the file-sync service, the status page and the dashboard held 33, 14 and 14 colour values that belonged to no shared palette. Without one source, every logo or colour change would mean finding every copy, and nothing would say which copy was right.
What I built
- One repository as the source of truth, created on 24 September 2026. The sources are four SVG marks and one JSON file of colour tokens. The CSS custom properties and the exported PNGs and favicons are generated from them, and committed beside them.
- A build check that regenerates the outputs and fails if they differ from what’s committed, so source and output can’t drift apart in a merge.
- A contrast check that holds every text pair to WCAG’s 4.5:1 and every focus, status and data colour to 3:1, and keeps the data colours visibly distinct from each other and from the status colours. Its self-test plants failures, so a broken formula can’t pass silently.
- An export check that each image is the right size and actually painted.
How it works
Each consumer, the deck lab’s web app among them, copies the files it needs and records the full commit it copied in a BRAND_COMMIT file. A copy is never edited. A change in the brand repository therefore changes nothing live until a consumer copies it again, at a new commit.
The two WordPress themes load the token stylesheet directly, and neither theme’s own stylesheet holds a single colour literal: every colour is a token or a mix of one. Services that can’t load a stylesheet get the tokens pasted in as a :root block, and a check confirms every colour in those stylesheets is one of the tokens. The documentation’s architecture diagrams read their colours from the same pinned file, and a missing token is an error, never a fallback.
Each surface gets the mark that suits how it crops an image. The file-sync service shows its logo uncropped, so it gets the Warden; the sign-in page and the status page crop to a circle, so they get the sigil.
In September I redrew the Warden from my own pencil sketch. The Sentinel didn’t change, so every favicon re-rendered byte for byte and stayed out of the change. Each consumer then re-pinned in its own change. Cloudflare kept serving the old logo for a while afterwards, until its cached copy expired; a URL with a cache-busting query showed the new one at once.
Decisions and trade-offs
- Copy and pin, not one live shared copy. A brand change is safe to merge, and each surface moves when I choose. The cost is a re-pin per consumer for every redraw, and a cache that can show the old mark for a while.
- Generated files committed beside their sources. Consumers copy plain files with no tooling, and the build check keeps the two in step. The cost is generated output in the history.
- Mark colours written into the SVGs. An image loaded with
<img>can’t take colours from the page, so the marks carry their own. A colour change edits the SVGs too, guarded by a check for stray colours. - Dedicated data colours for charts and diagrams, not the status colours reused. A box in a diagram must never read as “healthy” or “down”. The cost is four more tokens, each held to the same checks.
What’s next
The thin bright ring on the sigil is still a colour literal in its SVG rather than a token. Two sites stay outside the brand on purpose: Merry on Main and Southern Sparkle Design have their own looks.
Built with
SVG, JSON, CSS custom properties, Python, librsvg, Pillow, Bash, Git and GitHub.