docs/branding.md · rev. 2026-11

SHEET 00 / IDENTITY BLUEPRINT

The tetra brand.

Square, dark and quiet, so the emotes can be loud. This sheet is the rendered version of docs/branding.md. Components are in sheet 08.

[01]

Principles

Four rules every screen follows.

  1. 01

    Square

    No rounded corners, anywhere. Squareness is the brand.

  2. 02

    Emotes are the color

    The interface stays dark and quiet; emotes carry the energy.

  3. 03

    ASCII as an accent

    Monospace glyphs nod to chat. Seasoning, not the main course.

  4. 04

    One loud color

    Orange marks what matters. Everything else is neutral.

  5. 05

    Native, not a website

    Instant states, default cursor, no web-page flourishes on controls.

[02]

Color

Three roles, dark only. OKLCH tokens in app.css.

role
Background
token
background
value
oklch(0.145 0.003 38)
use
The page. surface for raised areas, border for lines.
role
Brand
token
primary · brand-500
value
oklch(0.655 0.214 38) · #f64f02
use
Primary actions, the key word of a heading, focus, active states.
role
Signal
token
signal · signal-400
value
oklch(0.81 0.13 215)
use
Rare. One detail per view that must not compete with orange.

brand-*

50
100
200
300
400
500
600
700
800
900
950

neutral-*

50
100
200
300
400
500
600
700
800
900
950

signal-*

300
400
500
  • — text on orange or signal is dark: white on #f64f02 fails contrast
  • — signal: at most one element per view, never next to orange on one element
  • — body text ≥ 4.5:1, control edges and focus rings ≥ 3:1

[03]

Typography

Geist family. Sans by default, serif as the accent, mono for ASCII.

font-sans · Geist · 100–900

Every emote, one command.

Default for everything: interface, body text and most headings.

font-serif · Geist Serif · 400 only

emotes

Accent only: one or two words in a heading. Never body text or interface.

font-mono · Geist Mono · 100–900

/addemote byname:catJAM

ASCII art, labels, commands, technical captions.

[04]

Shape

Radius is always 0. Lines over shadows.

r = 0
  • Every --radius-* token is 0, so is ui-sdk's --ui-radius.
  • No rounded-full either: dots, avatars and pills are square.
  • Structure comes from 1px hairlines and shared borders between cards.
  • No shadows, except the orange glow on the main call to action.

[05]

ASCII

The accent. One ASCII moment per block, always aria-hidden.

ramp · light → dense

␣.:-=+*#%@
  • + character illustrations in feature cards
  • + section labels: [01] / features
  • + terminal command lines
  • + faint texture, brand-500 at ~10%
  • − meaning that only exists in ASCII

[06]

Motion

Quiet by default, a few signature moments.

entrance
Rise and un-blur, 0.9s, staggered ~150 ms
signature
Orange wave, emote drop, block cursor
hover
Instant color changes, no transitions, no scaling
reduced motion
Content appears instantly, background stops

[07]

Voice

Speak like chat, write like a tool.

+ do

Add any emote with one command.

− don't

Leveraging advanced optimization pipelines for emoji assets.

+ do

Add to Discord

− don't

Add To Discord

  • Lead with what the user gets, not with technology.
  • English, sentence case for headings and buttons.
  • Wordmark: lowercase tetra in Geist Mono. No logo yet.
  • Never claim what isn't verified: pricing, permissions, numbers.

[08]

Components

components/ui. Built on ui-sdk where it ships the behavior.

<Button variant size glow render>

primary
secondary
destructive
ghost
glowone per page

<Heading level size> · level is the outline, size is the look

display

Emotes, squared.

xl

Emotes, squared.

lg

Emotes, squared.

md

Emotes, squared.

sm

Emotes, squared.

<Text size tone>

Large text for intros.

Default body text.

Small muted text for secondary details.

<Eyebrow index> · <Accent>

[01] / features

emote manager for discord

One accent word per heading.

<SegmentedControl> · <Slider> · <Switch> · <Radio>

96 px

<TextField prefix suffix error>

::

Clear it to see the inline error.

<SizeMeter value limit max> · bar ends at the original size

File size338 KB / 256 KB
File size212 KB / 256 KB

<SlotMeter label used limit> · emoji slots, orange in the last 10%

static31/50
animated47/50
animated50/50

<Notice title action> · a heads-up that doesn't block · <Spinner>

Processing

This GIF is 7.40 MB, our editor is made for smaller ones

You can keep going, but processing may be slow or fail.

<EmoteMenu kind> <Emote emote> · right-click, long-press or Shift+F10

One component for every emote in the panel. The list's actions decide the menu; a click selects and brings up the selection bar with the same actions.

<Toaster> · toast() · toast.promise()