Brand
Repo brand
Every repo in the estate ships three brand artifacts: avatar.svg,
hero.svg, and a derived brand.png (the combined sheet,
avatar over hero on the surface canvas, for social cards and README banner
spots). Avatar is a metaphorical logo. Hero is a data-sheet with the metaphor
embedded. The hero exists because GitHub doesn't render the repo avatar; it
carries the brand on mirrored views.
Avatar
256 × 256 viewBox. Metaphorical glyph; reads at favicon and avatar scale.
Hero
1200 × 430 viewBox. Big title left, embedded metaphor below it, four fact tiles right.
Skill language
The rules, stated tersely. Lift the templates, replace the placeholders, keep the rest.
Two artifacts, two voices
Avatar answers what is this like? with a metaphor. Hero answers what does this promise? with principles. Don't mix: a flow diagram in the avatar or a metaphorical hero is the failure mode.
The metaphor goes in both
GitHub strips the repo avatar, so the hero embeds an elaborated version of the same glyph beneath the title. The hero version has more endpoints, more lines, more density; it's the avatar with room to breathe.
One tagline, two surfaces
The italic line on the hero (under the title) and the muted tagline on the avatar (under the title) are the same phrase. It's a tagline, not a stage direction — evocative about the project's posture, not a literal description of the visual ("a basket catching the day's photographs as they fall from the feed" is the failure mode; "collected moments of early learning" is the right register).
One phrase across both artifacts keeps the brand coherent on the two surfaces a viewer hits (avatar in the repo header, hero in the README). Pick a phrase that fits the avatar's narrower budget — the hero has more room than it'll ever need.
Character budgets
The viewBoxes are fixed; SVG text doesn't wrap. Overflow looks unprofessional and hides content. Treat these as the worst-they-still-fit ceilings:
| Field | Where | Budget |
|---|---|---|
| title | avatar + hero | ~10 chars (one short word) |
| tagline | avatar + hero italic | ~36 chars |
| title sub-line | hero, two lines | ~70 chars per line |
| top metadata | hero, mono caps | ~58 chars |
| tile big word | hero, font-size 34 | ~12 chars |
| tile subtitle | hero, font-size 11 | ~46 chars |
| tile spec line | hero, mono caps | ~30 chars |
| territory tags | hero bottom-left | ~38 chars |
| output line | avatar, font-size 9 | ~50 chars |
Always render the SVG at canvas size (avatar 256, hero 1200) before shipping, and look for text that crosses a tile edge or runs into a divider line. Then look at it as a 3× PNG (avatar 768, hero 3600) — the PNG is what social cards and external embeds will actually display, and some overflow is only obvious there.
Glyph stays in its band
The hero metaphor mark sits in y 230-380 (150 actual units;
~75 local at the template's scale(2)). The bottom rule line
at y 386 is hard — a glyph that overlaps it looks like a
layout bug. If a glyph won't fit at scale(2), drop a row of
elements before scaling down: a less-full layout reads as "the project's
still small / still growing," which is usually on-brand. Scaling below
1.7 makes the strokes too thin against the canvas.
The avatar glyph sits in y 90-200 (110 units) at
scale(1). Similar discipline: photo + caption + a binding
line beats four photos crammed in.
Token whitelist
Every fill and stroke comes from a published semantic token. The hero
uses --surface for its canvas so white tile fills pop;
the avatar uses --bg for cool-white card framing.
| Token | Hex | Use |
|---|---|---|
| --bg | #ffffff | avatar canvas, hero tile fill |
| --surface | #f4f4f4 | hero canvas, renderer-circle fill on hero |
| --border | #e0e0e0 | avatar outer border, hero dividers and tile borders |
| --text-muted | #707070 | mono small caps, captions, subtitles, response lines |
| --text-2 | #404040 | body copy, taglines |
| --text | #0a0a0a | glyph strokes, output line |
| --accent | #4a6741 | title, big tile word, primary stroke |
Type
Avatar uses the system stack
(Helvetica, Arial, sans-serif) so the SVG renders the same in
terminals, GitLab repo headers, and social cards where IBM Plex isn't
loaded. Hero uses
IBM Plex Sans, Helvetica, Arial, sans-serif with mono
(IBM Plex Mono, Menlo, monospace) for small-caps headers and
spec lines. Plex renders where it's loaded; system falls in everywhere
else.
Lines start and end at edges
Connecting lines start at the conductor's edge and end at the renderer's edge — never pass through circle centres. When the metaphor has both call and response, draw them as parallel lanes (perpendicular offset, same magnitude on both ends), not converging on the same point.
Tile content
Each of the four hero tiles carries four layers: a small-caps mono label, a big bold moss word, a body subtitle that grounds the word, and a small mono spec line at the bottom. Top row covers flow (in / out), bottom row covers discipline (posture / lifetime). The pattern is fixed; the labels can vary per project.
Territory tags
The bottom-left dotted line carries territory tags: stable
concepts that say what kind of project this is. Domain words
(audio, auth), form words
(cli, library), protocol names when they're
stable and central (UPnP, OAuth).
What doesn't go here: language names, library names, framework names, version numbers, LOC counts, file counts, CLI flag names. Anything that might be renamed or swapped is a maintenance detail and lives in the repo's badge row, not in the brand.
Required attributes
role="img"on the<svg>root.- Non-empty
aria-labeldescribing the diagram in a sentence. - Outer
<rect>filling the canvas with paper (avatar) or paper-warm (hero), so the artwork carries its own background. font-familyset on both the<svg>and the wrapping<g>so it inherits everywhere.<defs>marker IDs prefixed with the repo slug to avoid collisions when SVGs are inlined together.
Generation
avatar.png is derived from avatar.svg via
rsvg-convert -w 256 -h 256. brand.png is
derived by stacking the avatar (rendered at 800×800, padded to 1600×800
on a surface canvas) above the hero (rendered at 1600×573), with a
24px surface border around the whole thing. The hero stays SVG-only;
GitHub renders SVG natively.
Each repo's Makefile adds a brand target that
regenerates both PNGs. Run it after editing either SVG.
Files
Lift, rename, replace placeholders.
repo-brand/templates/avatar.svg→ copy to your repo asavatar.svg; replace project, tagline, glyph, summary line.repo-brand/templates/hero.svg→ copy ashero.svg; replace project, tagline, glyph, four tile contents, territory tags.brand.png→ derived;make brandregenerates it from the two SVGs.- Both templates ship the dunn.dev mark as the placeholder glyph. A repo without its own metaphor yet can leave it as-is and the artifact still carries the estate identity.