Brand
The signet is a construction, not a fixed drawing. This system fixes
how to build one. The mark in packages/frontend/assets/ is a worked
example of the rules, the reference implementation, not an approved product
mark. A product that adopts this system draws its own to the same
construction.
The family under packages/frontend/assets/*-signet-{l,m,s}.svg makes the
claim checkable. The examples share the box, the outer radius, the stroke,
the rounding, the 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 stands further down this page as an instruction. Give it to an agent with a product name, and it produces a mark of the family.
The TYPO3 Soul is not in use, and a footer says what the product is, never whose it is.
The TYPO3 Soul is not in use, 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. So this mark neither nests nor crops the Association's asset.
Nested, it becomes the mark and erases the product. Cropped, it is an altered
asset that is not ours. Where co-branding is necessary, the marks
sit beside one another.
How to draw one#
Everything follows the stroke: stroke 2 → rounding 1 (half the stroke, on frame caps, line ends and the marker's points) → gap ≥ 2, ink to ink. A 32 × 24 box centred in a square viewBox, corner radius 4 for frame and marker. The frame is one open path, both ends caps, 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 lives in the box it is for, so every straight edge 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. That is 32, 64 and 96
for the large one, 24 and 48 for the middle, 16, 32 and 48 for the small.
Between those the edges go grey.
32 takes stroke 2 and three lines. 24 keeps stroke 2 in a smaller box, a heavier mark, and drops the faint middle line. 16 takes stroke 1, because sixteen pixels have no room for two, and keeps the ink of the middle size. So the mark gets heavier as the box shrinks, not fainter. Pick the file at the link, because a media query inside an SVG only sees its own viewport.
Every box is square, the shape of every slot a mark lands in: a favicon, an avatar, an app icon, a bar. One number sizes it.
A signet is not an icon#
Never put .sds-icon on a signet. Icon rules size a glyph from the text
around it, while each signet file fits one pixel box. The icon class erases
that choice and renders every optical file at the same size.
.sds-signet sets display and flow, and no dimensions. The element or
lockup that places the mark states its width and height, and chooses the
matching file. So the size stands where the box is certain, and a brand mark
does not become a UI glyph.
The family#
One construction, distinct interiors. Shared: the square box, the 4:3 construction inside it, the outer radius, the stroke with its rounding and gap. And the single orange in the top-right corner. Not shared: the interior, one idea per product.
A new one#
Everything above, as an instruction. It stands here in full because it is a thing to hand over, not a thing to read. Copy the whole block, name the product, and the result belongs to the family. Half of it gives a mark that shares a colour and nothing else: every number follows from the stroke.
# Draw a signet to this construction
Everything here is the construction, complete on its own. It assumes you
cannot open a 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 stays as it is,
> and you must not change it. You invent 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 lives in that box. The strip above and below it is air, and it
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 there is no
aspect to state wrong.
- 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 lives in the box of
its size, 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. A stroked path centres on its edge. So
with an even stroke the centreline is whole: a 2-unit stroke on `x=1` inks
0 to 2. 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 at work.
- **Curves are exempt.** An arc, a diagonal, the point of a triangle: no grid
holds them. Only what a screen can hold straight has to land.
- **A drawing is true at its size and at every whole multiple of it.** The
large file is true at 32, 64 and 96. The middle at 24, 48 and 72. The
small at 16, 32 and 48. Between those, every edge falls mid-pixel and
comes out with one hard edge and one soft one. That is why the link
chooses the size.
## The one value everything follows
Pick the stroke, and the rest follows:
| | 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 |
- **The rounding is half the stroke, everywhere.** Line ends, the corners of
a filled shape, the points of a triangle. One radius, no exceptions.
- **The gap is never less than the stroke**, ink to ink, not path to path. A
stroked path's ink reaches half a stroke past its geometry. A gap under one
whole pixel separates nothing.
- **Nothing leaves the box.** The same half stroke applies outwards. Inset
every path that draws an outer edge by 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. At 16 the stroke goes to one pixel, because sixteen pixels
have no room for two. The interior keeps the ink of the middle size. **The
box shrinks around the interior; the interior does not shrink with it.**
Drop what does not read at 16. Do not keep it small.
## Colour
- The ink is a mid warm grey, 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, in the hex.
- The accent is flat `var(--accent, #FF8700)`.
- **Orange appears exactly once, in the top-right corner.** That position is
the family's one shared gene. Nothing else has colour.
- No `<style>` block and no colour on the root. No comment in the file with a
double dash: that is not valid XML, and the file then draws nothing.
## The interior is yours, under three conditions
1. **One idea, not two.** One sentence about the product, drawn. Three
interiors of that kind, spelt out because you cannot open them. A session
that ends 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. **Draw it at 16. Do not shrink it to 16.** Draw the small file on its own
grid and look at it at 16. Detail that turns to mush has to go, and what
stays gets the whole pixels it needs.
3. **The idea belongs to this product only.** The generic readings are the
first ones anyone reaches for: a terminal, a play triangle, a stack of
parts. A sibling has them already. Put another product's name in front of
the sentence the interior draws. If it stays true, the mark identifies a
category, not a product.
## Two techniques
- **A filled shape with 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, and the shape
grows by half a stroke on every side. So its geometry stops half a stroke
short of the box corner while its ink lands on it. In the 16 file its
geometry sits on halves, like every other 1-unit stroke. The corner marker
and the triangle interior use this technique. So a triangle's three points
get the family's rounding without a second construction.
- **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, `<product>-signet-l.svg`, `-m.svg`, `-s.svg`. Each has a
`<title>` and `role="img" aria-label` with the product's name. Each has
`id="soul-ref"` on the root, and a comment that says what the interior means
and what changed at that size. Then render each one at its size and at twice
that, side by side, and look. The question is if the three read as one mark, and only your
own eyes answer 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, the frame around the others. A frame that
outweighs its contents is the wrong shape. You draw a product mark: fill it.
# Draw a signet to this construction
Everything here is the construction, complete on its own. It assumes you
cannot open a 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 stays as it is,
> and you must not change it. You invent 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 lives in that box. The strip above and below it is air, and it
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 there is no
aspect to state wrong.
- 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 lives in the box of
its size, 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. A stroked path centres on its edge. So
with an even stroke the centreline is whole: a 2-unit stroke on `x=1` inks
0 to 2. 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 at work.
- **Curves are exempt.** An arc, a diagonal, the point of a triangle: no grid
holds them. Only what a screen can hold straight has to land.
- **A drawing is true at its size and at every whole multiple of it.** The
large file is true at 32, 64 and 96. The middle at 24, 48 and 72. The
small at 16, 32 and 48. Between those, every edge falls mid-pixel and
comes out with one hard edge and one soft one. That is why the link
chooses the size.
## The one value everything follows
Pick the stroke, and the rest follows:
| | 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 |
- **The rounding is half the stroke, everywhere.** Line ends, the corners of
a filled shape, the points of a triangle. One radius, no exceptions.
- **The gap is never less than the stroke**, ink to ink, not path to path. A
stroked path's ink reaches half a stroke past its geometry. A gap under one
whole pixel separates nothing.
- **Nothing leaves the box.** The same half stroke applies outwards. Inset
every path that draws an outer edge by 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. At 16 the stroke goes to one pixel, because sixteen pixels
have no room for two. The interior keeps the ink of the middle size. **The
box shrinks around the interior; the interior does not shrink with it.**
Drop what does not read at 16. Do not keep it small.
## Colour
- The ink is a mid warm grey, 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, in the hex.
- The accent is flat `var(--accent, #FF8700)`.
- **Orange appears exactly once, in the top-right corner.** That position is
the family's one shared gene. Nothing else has colour.
- No `<style>` block and no colour on the root. No comment in the file with a
double dash: that is not valid XML, and the file then draws nothing.
## The interior is yours, under three conditions
1. **One idea, not two.** One sentence about the product, drawn. Three
interiors of that kind, spelt out because you cannot open them. A session
that ends 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. **Draw it at 16. Do not shrink it to 16.** Draw the small file on its own
grid and look at it at 16. Detail that turns to mush has to go, and what
stays gets the whole pixels it needs.
3. **The idea belongs to this product only.** The generic readings are the
first ones anyone reaches for: a terminal, a play triangle, a stack of
parts. A sibling has them already. Put another product's name in front of
the sentence the interior draws. If it stays true, the mark identifies a
category, not a product.
## Two techniques
- **A filled shape with 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, and the shape
grows by half a stroke on every side. So its geometry stops half a stroke
short of the box corner while its ink lands on it. In the 16 file its
geometry sits on halves, like every other 1-unit stroke. The corner marker
and the triangle interior use this technique. So a triangle's three points
get the family's rounding without a second construction.
- **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, `<product>-signet-l.svg`, `-m.svg`, `-s.svg`. Each has a
`<title>` and `role="img" aria-label` with the product's name. Each has
`id="soul-ref"` on the root, and a comment that says what the interior means
and what changed at that size. Then render each one at its size and at twice
that, side by side, and look. The question is if the three read as one mark, and only your
own eyes answer 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, the frame around the others. A frame that
outweighs its contents is the wrong shape. You draw 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. The signet is
1.36 × the type size, the gap 0.5 ×, the clear space half the signet height.
A site with no brand draws the product name alone, at 700. There is no quiet half to read it against, so the whole mark carries the weight of the first word. The bar at its narrowest hides the brand and the pipe and arrives at the same place.
Clear space, edges, motion#
Never#
- a second colour in the mark;
- equal weights on the two words;
- a stretch;
- an orange fill behind it;
- the large drawing at a small size;
- the marker in anything but orange.