Skip to main content

01 · Logo system

The canonical spec. Every implementation of the SecurityV0 mark cites this file and pulls geometry from it — not from the consumer codebase.

This document is normative. If Logo.tsx, securityv0.svg, a marketing deck, or a partner asset disagrees with this file, the asset is wrong.

01 · Construction

Every dimension derives from a single value: M, the mark's side length in pixels. Pick M for the surface, then read off the rest.

TokenValueNotes
Mmark side length (px)Single input. Everything else derives from this.
Corner radiusM × 0.187532 px mark → 6 px radius. Same scale at every size.
Bracket arm widthM × 0.1093.5 / 32 of the mark width. Stays optically thin at small sizes.
Letter fontJetBrains Mono 700 (outlined to a path)Mono picks up the "code/version" semantic. Shipped as an outlined <path>, not live text — see the note under the reference SVG.
Letter caseUppercase SAlways uppercase. Lowercase reads as "lab build"; uppercase reads as a product mark.
Letter sizeM × 0.312510 / 32. Inner-S cap-height matches wordmark cap-height (parity rule).
Letter y-offsetviewBox y = 20.15 (for 32 box)S optical-center sits ON bracket midline (y = 16). Earlier value y = 21 dropped it 1.15u below.
Wordmark sizeM × 0.532 px mark → 16 px wordmark. Optical balance, not algebraic.
Wordmark optical shiftmargin-top: -0.07emPulls cap-line down to bbox-center so flex-center aligns to optical center, not bbox center.
Lockup gapM × 0.37532 px mark → 12 px gap. Tight enough to read as one unit, loose enough to breathe.
Clear space≥ M × 0.25 on every sideQuarter-mark padding. Never crop tighter.

Reference SVG (32-px viewBox, all sizes derive from this)

<svg width="32" height="32" viewBox="0 0 32 32" role="img" aria-label="SecurityV0">
<rect width="32" height="32" rx="6" fill="var(--color-primary)"/>
<!-- Left bracket -->
<path d="M8 8 H11.5 V10.5 H10.5 V21.5 H11.5 V24 H8 Z" fill="var(--color-on-primary)"/>
<!-- Right bracket -->
<path d="M24 8 H20.5 V10.5 H21.5 V21.5 H20.5 V24 H24 Z" fill="var(--color-on-primary)"/>
<!-- Letter S — the JetBrains Mono 700 'S' glyph outlined to a path
(font-size 10, baseline y=20.15, centered on the 600u mono advance) -->
<path d="M16.03 20.25Q15.29 20.25 14.735 19.99Q14.18 19.73 13.875 19.245Q13.57 18.76 13.57 18.09H14.8Q14.8 18.58 15.135 18.87Q15.47 19.16 16.03 19.16Q16.57 19.16 16.885 18.875Q17.2 18.59 17.2 18.11Q17.2 17.75 16.995 17.475Q16.79 17.2 16.41 17.1L15.43 16.85Q14.64 16.65 14.18 16.1Q13.72 15.55 13.72 14.79Q13.72 13.86 14.33 13.305Q14.94 12.75 15.96 12.75Q16.65 12.75 17.165 13Q17.68 13.25 17.96 13.705Q18.24 14.16 18.24 14.77H17.02Q17.02 14.35 16.73 14.09Q16.44 13.83 15.96 13.83Q15.49 13.83 15.215 14.085Q14.94 14.34 14.94 14.75Q14.94 15.09 15.135 15.31Q15.33 15.53 15.68 15.63L16.69 15.88Q17.5 16.08 17.965 16.68Q18.43 17.28 18.43 18.11Q18.43 18.76 18.135 19.24Q17.84 19.72 17.3 19.985Q16.76 20.25 16.03 20.25Z" fill="var(--color-on-primary)"/>
</svg>

The S is an outlined path, not live text. Like the brackets, the inner S ships as an SVG <path> — the JetBrains Mono 700 S glyph outlined at font-size 10 / baseline y=20.15. This makes the mark font-independent: SVG favicons and app icons render in an isolated document with no access to web fonts, so a live <text> S would silently fall back to system mono. To regenerate (e.g. if the typeface changes), extract the glyph with fontTools and re-outline at the same transform — do not hand-edit the path.

Why a 32-box and not 56-box. The geometry is canonical at the size where the inner-S parity rule was measured. Larger renderings scale the SVG; they don't redraw it. Don't introduce a 56-box variant — it forces re-deriving y-offset and font-size, and they will drift.

02 · Color and ground rules

The mark always sits on a filled tile. The tile color follows the surface — never pull the mark off the tile, and never sit a slate tile on a near-black sidebar.

Three valid grounds

SurfaceTile fillGlyph fillUse
Light surface (login, page)--color-primary #565e74--color-on-primary #f7f7ffThe default lockup
Dark surface (sidebar)--color-mark-tile-inverted #d9e4ea--color-inverse-surface #0b0f10The inverted lockup
Slate marketing slab--color-inverse-surface #0b0f10whiteMarketing hero on saturated slate

Three forbidden grounds

SurfaceWhy it's wrong
Light tile on dark sidebar with light glyphGlyph disappears into the tile; mark reads as a blank chip
Slate tile on dark sidebar (current PR #780 bug)Slate has near-zero contrast against #0b0f10 — the mark floats off-surface
Mark without tile in product UIReserved for favicons only. In product surfaces, the tile is the mark — removing it removes the mark's identity

03 · Lockup

The horizontal lockup is the canonical SecurityV0 identity unit: [mark] gap [Security][V0].

Vertical alignment — the optical rule

Flexbox align-items: center aligns bounding boxes. Inter's metrics put empty space above the cap-line and a descender slot below the baseline, so the bbox-center sits below the cap-center. Without compensation, the mark visually lands ~7 % × M below the wordmark's cap-line — a real defect, not a perception thing.

Fix: apply margin-top: -0.07em to the wordmark span. This pulls the cap-line down to the bbox-center; flex-center then aligns optical-to-optical.

.lockup        { display: inline-flex; align-items: center; gap: calc(var(--mark-size) * 0.375); }
.lockup .word { margin-top: -0.07em; } /* the optical-shift rule */

The same rule applies whenever you put the mark next to typography (a headline, a slab, a partner logo): align cap-center to mark-center, not bbox-center.

Three approved arrangements

ArrangementWhereNotes
A · Horizontal, mark leftSidebar, topbar, loginThe default. All surfaces use this unless explicitly listed below.
B · Horizontal on darkDark sidebarSame arrangement, inverted ground per §02
C · Mark onlyFavicon, app icon, collapsed sidebarUsed when horizontal space is scarce or recall doesn't need the wordmark

Three forbidden arrangements

ArrangementWhy
Stacked (mark over wordmark)Reads as "logo + caption" — wrong register for a single brand mark
Mark right of wordmarkBreaks left-anchored reading; non-Western feel without the underlying intent
Wordmark only in product UILoses the mark; recall drops. Wordmark-only is OK in body copy and footers, never in identity surfaces

04 · Wordmark

Security + V0, set in Inter, with V0 demoted in color and weight.

PropertyValue
Font familyInter
Security weight700
V0 weight600 (one step lighter)
Security color--color-on-surface (or white on dark surfaces)
V0 color--color-outline #717c82 (or #9a9d9f on dark surfaces)
Letter-spacing-0.015em
Line-height1
Optical shift in lockupmargin-top: -0.07em
<span class="wordmark">
<span>Security</span><span class="muted">V0</span>
</span>

The two-tone treatment is load-bearing. It's how V0 reads as a version cue rather than a co-brand. Recoloring V0 to slate (matching the mark) makes it look like a Vercel-v0 co-promotion. See 03 · Trademark.

05 · Application across surfaces

App topbar (logged-in)

TokenValue
M28 px
Gap11 px
Wordmark14 px

Full lockup, dark ground. M = 32 px. The Security color is #fff; V0 is #9a9d9f.

Mark only. Tile is light (#d9e4ea), glyph is dark. Pass aria-label="SecurityV0" since the wordmark isn't visible.

Login screen

Lockup centered above the sign-in card.

TokenValue
M48 px
Gap18 px
Wordmark24 px

The larger M is intentional — login is ceremonial, the mark carries weight there it doesn't need to in dense product UI.

Favicon and app icon

Same SVG, scaled. M ∈ { 16, 32, 64, 128 }. Use the slate-light variant (slate tile, white glyph) on every browser/OS; the inverted variant is for in-product dark surfaces, not for OS chrome.

WorkOS AuthKit (hosted login)

WorkOS only exposes a small set of branding controls. The values live in 02 · Applications — they're operational, not part of the spec.

06 · Forbidden — the master list

In one place, for grep-ability:

  • Stacked lockup (mark over wordmark)
  • Mark right of wordmark
  • Wordmark without mark in product surfaces (favicon-only is fine)
  • Letter case drift (lowercase s, italic, etc.)
  • Recoloring V0 to slate (it must read demoted)
  • [V0] or [v0] between brackets — only [S]
  • Placing the mark on a tile that doesn't match the surface contract (§02)
  • Re-deriving SVG geometry from a 56-box or other viewBox

07 · Open questions

  • Mark-only in dense surfaces. Currently the topbar uses the full lockup; some reviewers want mark-only there to recover horizontal space. Pending a measured before/after.
  • Vercel v0 hedge — formal legal review. The voluntary hedge is in 03 · Trademark. A formal trademark search has not been run.

08 · Decided

  • The app typeface is Inter only. JetBrains Mono is not adopted as a product font, and --font-mono stays the system monospace stack (ui-monospace, monospace). JetBrains Mono survives in the brand only as the outlined shape of the mark's S — the app loads no monospace web font. Path IDs, scanner output, and mono chips render in the system monospace face; that's deliberate, not a gap. (Decided 2026-05-20, after the mark's S was outlined to a path — there was no longer any consumer that needed the web font.)

Implementation in code

The spec is the source of truth; code follows. Consumer-side implementations live in:

  • sv0-platform/ui/src/components/Logo.tsx — React component
  • sv0-platform/ui/public/securityv0.svg — favicon (hardcoded hex; favicons can't read CSS vars)
  • sv0-website — marketing surfaces

When any of those drifts from this spec, update the consumer — never edit this file to match the consumer.

Provenance

This spec was authored from the Claude Design v3 handoff (artifact jWP0ol8mKRrVAeMBTVUY6g, 2026-05-05). The original logo-system.html is preserved verbatim under archive/2026-05-05-claude-design-handoff/. Two earlier handoffs (initial branding canvas, v2 trademark research) informed the 03 · Trademark hedge and lived briefly at branding.sv0-reviews.pages.dev.