Brand
The signet is a construction, not a fixed drawing. What this system
fixes is how one is built. The mark in packages/frontend/assets/ came from the Dev
Companion prototype and is a worked example of the rules — the reference
implementation, not an approved product mark. A product adopting this system
draws its own to the same construction.
The worked family under packages/frontend/assets/*-signet-{l,m,s}.svg
makes the claim checkable rather than asking a reader to believe it. The Dev
Companion, Tryout and design-system examples share the box, outer radius,
stroke, rounding, gap and the single orange in the top-right corner; only the
interior differs, and it carries one idea.
The system's own mark has no window and its accent is a stroke, both on purpose: a frame reads as a terminal, and a terminal is what the products are, not what the system is. The construction is written out as something to act on further down this page — hand it to an agent with a product name and it should produce a mark that belongs here.
The TYPO3 Soul is not used, and a footer says what the product is, never whose it is.
The TYPO3 Soul is not used, and a footer says what the product is, never whose it is.
TYPO3 in the wordmark names the domain the system serves, not the owner of
the system. The Association's asset is therefore neither nested nor cropped
into this mark: nesting would make it the mark and erase the product, while
cropping would alter an asset that is not ours. Where co-branding is needed,
the marks sit beside one another.
How one is drawn#
Everything follows the stroke: stroke 2 → rounding 1 (half the stroke, on frame caps, line ends and the marker's points alike) → gap ≥ 2, measured ink to ink. A 32 × 24 box centred in a square viewBox, corner radius 4 shared by frame and marker. The frame is one open path — both ends are caps, not cuts — and it stops gap + stroke short, because each cap reaches half a stroke further. The marker sits on the frame's outer edge, not on the box.
Those are units of the file, and a unit is a pixel: the drawing is made in the box it is for, so every straight edge is a whole number and lands on a whole device pixel.
Optical sizes and their boxes#
The optical files use viewBox="0 0 32 32", 0 0 24 24 and
0 0 16 16: one unit is one pixel at the size the file is for, so a
drawing is true at that size and at every multiple of it — 32, 64, 96 for
the large one, 24 and 48 for the middle, 16, 32 and 48 for the small. Between
those it is a vector like any other and the edges go grey.
32 takes stroke 2 and three lines; 24 keeps stroke 2 in a smaller box, which is a heavier mark, and drops the faint middle line; 16 takes stroke 1, because sixteen pixels have nowhere to put two, and keeps the ink of the middle size so the mark gets heavier as the box shrinks rather than fainter. Pick the file at the link, because a media query inside an SVG only sees its own viewport.
Every box is square, which is the shape every slot a mark lands in already has — a favicon, an avatar, an app icon, a bar. One number sizes it, and there is no aspect to state twice or to get wrong.
A signet is not an icon#
Never put .sds-icon on a signet. Icon rules size a glyph from the text it
sits in, while each signet file is drawn for a particular pixel box. Applying
the icon class would erase that choice and make the optical files render at
the same inherited size.
.sds-signet deliberately sets display and flow but no dimensions. The
element or lockup that places the mark states its width and height, and chooses
the matching file. This keeps size at the place where the available box is
known without turning a brand mark into a UI glyph.
The family#
One construction, distinct interiors. What is shared is the square box and the 4:3 construction inside it, the outer radius, the stroke and its two consequences (rounding, gap), and the single orange in the top-right corner. What is not shared is the interior — one idea per product.
Drawing a new one#
Everything above, written as something to act on. It is here in full and not behind a link because it is a thing to hand over rather than a thing to read: copy the whole block, name the product, and what comes back should belong to the family without its author having seen a single sibling. Take half of it and you get a mark that shares a colour and nothing else — every number in it follows from the stroke, and the rules that keep the optical sizes reading as one mark are the ones easiest to leave behind.
# Draw a signet to this construction
Everything here is the construction, and it is written to be complete on its
own: it assumes you cannot open a single mark already drawn to it. The only
thing left to invent is the interior.
---
## The prompt
> Draw a signet for `<product>`, which is `<one sentence: what it does, for
> whom>`.
>
> It joins an existing family. Everything structural below is fixed and is not
> yours to change — you are inventing the interior and nothing else. Produce
> three SVG files, one per drawn size, and nothing more.
## The box
- **A square viewBox at the size the file is for**: `viewBox="0 0 32 32"`,
`"0 0 24 24"`, `"0 0 16 16"`. No offset, no margin, no negative origin.
- **The construction box is 4:3, centred in it** — 32 × 24, 24 × 18, 16 × 12.
The mark is drawn in that box; the strip above and below it is air, and it
is what makes the file square.
- Square because every slot a mark lands in is square: a favicon, an avatar,
an app icon, the mark well in a bar. One number sizes it, and a caller
cannot state the wrong aspect because there is no aspect to state.
- Outer corners of the construction box: **radius 4 / 3 / 2**.
## One unit is one pixel
This is the rule the three files exist for. Each drawing is made in the box of
the size it is for, so a unit *is* a device pixel there:
- **Every straight edge is a whole number.** Not the geometry — the *ink*. A
filled shape lands on whole numbers directly; a stroked path is centred on
its edge, so with an even stroke the centreline is whole (a 2-unit stroke on
`x=1` inks 0 to 2) and with a 1-unit stroke it is a half (`x=0.5` inks 0 to
1). Half values in a 16 file are the rule working, not an exception to it.
- **Curves are exempt and always were.** An arc, a diagonal, the point of a
triangle: no grid holds them and none is asked to. Only what a screen can
hold straight has to land.
- **A drawing is true at its size and at every whole multiple of it** — 32, 64
and 96 for the large file; 24, 48 and 72 for the middle; 16, 32 and 48 for
the small. Between those it is a vector like any other, every edge falls
mid-pixel, and each line comes out with one hard edge and one soft one. That
is what this construction is built to avoid, and it is why the size is
chosen at the link.
## The one value everything follows
Pick the stroke, and the rest is decided:
| | L (32) | M (24) | S (16) |
| --- | --- | --- | --- |
| viewBox | `0 0 32 32` | `0 0 24 24` | `0 0 16 16` |
| construction box | 32 × 24 | 24 × 18 | 16 × 12 |
| stroke | 2 | 2 | 1 |
| rounding | 1 | 1 | 0.5 |
| minimum gap, ink to ink | 2 | 2 | 1 |
| outer corner radius | 4 | 3 | 2 |
| path radius for that corner | 3 | 2 | 1.5 |
- **Rounding is half the stroke, everywhere.** Line ends, the corners of a
filled shape, the points of a triangle — one radius, no exceptions.
- **Gap is never less than the stroke**, and it is measured ink to ink, not
path to path. A stroked path's ink reaches half a stroke past its geometry;
forgetting that is the most common way these drawings go wrong. A gap under
one whole pixel separates nothing, which is the same failure seen from the
other end.
- **Nothing leaves the box.** The same half stroke applies outwards: every
path that draws an outer edge is inset half a stroke, so its ink lands on
the box.
- **Three sizes, drawn, never scaled between.** The stroke does not shrink
with the box: L and M both carry two pixels of it, so the middle size is the
heavier mark of the two. At 16 the stroke goes to one pixel — sixteen pixels
have nowhere to put two — and the interior keeps the ink the middle size is
drawn with rather than giving ground. **The box shrinks around the interior;
the interior does not shrink with it.** If something stops reading at 16 it
is dropped, not kept small.
## Colour
- The ink is a mid warm grey, written as a token with a hex behind it:
`fill="var(--text-primary, #8A8378)"`. A page that declares the tokens gets
its own ink; the file still renders on its own, where the hex is what it
draws as.
- The accent is flat `var(--accent, #FF8700)`.
- **Orange appears exactly once**, and it appears **in the top-right corner**.
That position is the family's one shared gene. Nothing else is coloured.
- Nothing colours the drawing from a `<style>` block or from the root, and no
comment in the file may carry a double dash — that is malformed XML, and a
file with one draws nothing wherever it is fetched.
## The interior is yours, under three conditions
1. **One idea, not two.** One sentence about the product, drawn. Three
interiors built this way, written out because you cannot open them: a
session ending in an answer — a terminal frame around two muted lines and
one orange one; the thing you press to start something — a triangle; the
parts and the frame around them — three unequal blocks between two crop
marks.
2. **It must be drawn at 16, not survive being taken there.** Draw the small
file on its own grid and look at it at 16. Detail that turns to mush is
detail that has to go, and what stays gets the whole pixels it needs.
3. **It must be an idea only this product could have.** The generic readings
— a terminal, a play triangle, a stack of parts — are the first ones anyone
reaches for, which is why a sibling is most likely holding them already.
Put another product's name in front of the sentence the interior draws: if
it stays true, the mark identifies a category and not a product, and it is
one nobody can tell from the sibling it lands on.
## Two techniques worth stealing
- **A filled shape that needs the family's rounding**: give it `fill` *and*
`stroke` in the same colour at the size's stroke width, with
`stroke-linejoin="round"`. The join produces the rounding, the shape grows
by half a stroke on every side, and you keep one construction instead of
two. Growing on every side is also why its geometry stops half a stroke
short of the box corner while its ink lands on it — and, in the 16 file, why
its geometry sits on halves like every other 1-unit stroke.
The corner marker every mark carries is drawn this way, and so is the one
interior in the family that is a triangle — a triangle's three points come
out at the family's rounding through the round join, without a second
construction that would have to be kept in step with the first.
- **An outer corner of radius R on a stroked path**: give the path radius
R − half the stroke, and the ink lands on R.
## What to hand back
Three files, named `<product>-signet-l.svg`, `-m.svg`, `-s.svg`, each with a
`<title>`, `role="img" aria-label` naming the product, `id="soul-ref"` on the root
so it can be referenced, and a comment saying what the interior means and what
changed at that size. Then render each one at the size it is drawn for and at
twice that, side by side, and look at them — the check is whether the three
read as one mark, and nothing but your own eyes does it.
## The one deviation, and it is not yours
A product mark **fills** its corner marker. One mark in the family strokes it
instead — the design system's own, which is the frame the others are composed
inside, and a frame that outweighs its contents is the wrong shape. You are
drawing a product mark: fill it.
# Draw a signet to this construction
Everything here is the construction, and it is written to be complete on its
own: it assumes you cannot open a single mark already drawn to it. The only
thing left to invent is the interior.
---
## The prompt
> Draw a signet for `<product>`, which is `<one sentence: what it does, for
> whom>`.
>
> It joins an existing family. Everything structural below is fixed and is not
> yours to change — you are inventing the interior and nothing else. Produce
> three SVG files, one per drawn size, and nothing more.
## The box
- **A square viewBox at the size the file is for**: `viewBox="0 0 32 32"`,
`"0 0 24 24"`, `"0 0 16 16"`. No offset, no margin, no negative origin.
- **The construction box is 4:3, centred in it** — 32 × 24, 24 × 18, 16 × 12.
The mark is drawn in that box; the strip above and below it is air, and it
is what makes the file square.
- Square because every slot a mark lands in is square: a favicon, an avatar,
an app icon, the mark well in a bar. One number sizes it, and a caller
cannot state the wrong aspect because there is no aspect to state.
- Outer corners of the construction box: **radius 4 / 3 / 2**.
## One unit is one pixel
This is the rule the three files exist for. Each drawing is made in the box of
the size it is for, so a unit *is* a device pixel there:
- **Every straight edge is a whole number.** Not the geometry — the *ink*. A
filled shape lands on whole numbers directly; a stroked path is centred on
its edge, so with an even stroke the centreline is whole (a 2-unit stroke on
`x=1` inks 0 to 2) and with a 1-unit stroke it is a half (`x=0.5` inks 0 to
1). Half values in a 16 file are the rule working, not an exception to it.
- **Curves are exempt and always were.** An arc, a diagonal, the point of a
triangle: no grid holds them and none is asked to. Only what a screen can
hold straight has to land.
- **A drawing is true at its size and at every whole multiple of it** — 32, 64
and 96 for the large file; 24, 48 and 72 for the middle; 16, 32 and 48 for
the small. Between those it is a vector like any other, every edge falls
mid-pixel, and each line comes out with one hard edge and one soft one. That
is what this construction is built to avoid, and it is why the size is
chosen at the link.
## The one value everything follows
Pick the stroke, and the rest is decided:
| | L (32) | M (24) | S (16) |
| --- | --- | --- | --- |
| viewBox | `0 0 32 32` | `0 0 24 24` | `0 0 16 16` |
| construction box | 32 × 24 | 24 × 18 | 16 × 12 |
| stroke | 2 | 2 | 1 |
| rounding | 1 | 1 | 0.5 |
| minimum gap, ink to ink | 2 | 2 | 1 |
| outer corner radius | 4 | 3 | 2 |
| path radius for that corner | 3 | 2 | 1.5 |
- **Rounding is half the stroke, everywhere.** Line ends, the corners of a
filled shape, the points of a triangle — one radius, no exceptions.
- **Gap is never less than the stroke**, and it is measured ink to ink, not
path to path. A stroked path's ink reaches half a stroke past its geometry;
forgetting that is the most common way these drawings go wrong. A gap under
one whole pixel separates nothing, which is the same failure seen from the
other end.
- **Nothing leaves the box.** The same half stroke applies outwards: every
path that draws an outer edge is inset half a stroke, so its ink lands on
the box.
- **Three sizes, drawn, never scaled between.** The stroke does not shrink
with the box: L and M both carry two pixels of it, so the middle size is the
heavier mark of the two. At 16 the stroke goes to one pixel — sixteen pixels
have nowhere to put two — and the interior keeps the ink the middle size is
drawn with rather than giving ground. **The box shrinks around the interior;
the interior does not shrink with it.** If something stops reading at 16 it
is dropped, not kept small.
## Colour
- The ink is a mid warm grey, written as a token with a hex behind it:
`fill="var(--text-primary, #8A8378)"`. A page that declares the tokens gets
its own ink; the file still renders on its own, where the hex is what it
draws as.
- The accent is flat `var(--accent, #FF8700)`.
- **Orange appears exactly once**, and it appears **in the top-right corner**.
That position is the family's one shared gene. Nothing else is coloured.
- Nothing colours the drawing from a `<style>` block or from the root, and no
comment in the file may carry a double dash — that is malformed XML, and a
file with one draws nothing wherever it is fetched.
## The interior is yours, under three conditions
1. **One idea, not two.** One sentence about the product, drawn. Three
interiors built this way, written out because you cannot open them: a
session ending in an answer — a terminal frame around two muted lines and
one orange one; the thing you press to start something — a triangle; the
parts and the frame around them — three unequal blocks between two crop
marks.
2. **It must be drawn at 16, not survive being taken there.** Draw the small
file on its own grid and look at it at 16. Detail that turns to mush is
detail that has to go, and what stays gets the whole pixels it needs.
3. **It must be an idea only this product could have.** The generic readings
— a terminal, a play triangle, a stack of parts — are the first ones anyone
reaches for, which is why a sibling is most likely holding them already.
Put another product's name in front of the sentence the interior draws: if
it stays true, the mark identifies a category and not a product, and it is
one nobody can tell from the sibling it lands on.
## Two techniques worth stealing
- **A filled shape that needs the family's rounding**: give it `fill` *and*
`stroke` in the same colour at the size's stroke width, with
`stroke-linejoin="round"`. The join produces the rounding, the shape grows
by half a stroke on every side, and you keep one construction instead of
two. Growing on every side is also why its geometry stops half a stroke
short of the box corner while its ink lands on it — and, in the 16 file, why
its geometry sits on halves like every other 1-unit stroke.
The corner marker every mark carries is drawn this way, and so is the one
interior in the family that is a triangle — a triangle's three points come
out at the family's rounding through the round join, without a second
construction that would have to be kept in step with the first.
- **An outer corner of radius R on a stroked path**: give the path radius
R − half the stroke, and the ink lands on R.
## What to hand back
Three files, named `<product>-signet-l.svg`, `-m.svg`, `-s.svg`, each with a
`<title>`, `role="img" aria-label` naming the product, `id="soul-ref"` on the root
so it can be referenced, and a comment saying what the interior means and what
changed at that size. Then render each one at the size it is drawn for and at
twice that, side by side, and look at them — the check is whether the three
read as one mark, and nothing but your own eyes does it.
## The one deviation, and it is not yours
A product mark **fills** its corner marker. One mark in the family strokes it
instead — the design system's own, which is the frame the others are composed
inside, and a frame that outweighs its contents is the wrong shape. You are
drawing a product mark: fill it.
Lockup#
TYPO3 at 600, an orange pipe, Soul Design System at 300. The pipe is
separator and caret at once, and the only colour in the mark. Signet is
1.36 × the type size, gap 0.5 ×, clear space half the signet height.
Never#
A second colour in the mark. Equal weights on the two words. Stretching. An orange fill behind it. The large drawing at a small size. The marker in anything but orange.