Design system

Contract

Design system

All new UI uses tokens and components from this page. If a primitive does not exist here, add it here first. Teal is healthy and the only accent — do not invent a second green. Buyer install, env, and screens live in Documentation.

Page contract

Every screen is a table, timeline, split inbox, or kanban — not a card grid. Radius is 6px on controls and 8px on panels. No 16px+ marketing cards, no gradients, no emoji icons.

Layout

Phone is under 768. Tablet is 768–1023. Desktop is 1024 and up. The rail is a charcoal drawer below desktop. KPI strips go 1 / 2 / 3. Split pages stack. Inbox is list or thread on the phone, two panes on tablet, three on desktop. Pipeline scrolls sideways until desktop. Tables scroll sideways — never squash columns. Header forms open in a Sheet, never inside the title row.

Reply rate

2.4%

Positive replies

1.1%

Bounce rate

4.1%

Color roles

Teal · healthy + accent

Orange · attention

Red · money-losing

Canvas

Panel

Rail

  • Teal = brand + healthy. Inbox ready, DNS pass, sequence ready.
  • Orange = attention / in-progress. Ramp, pending DNS, verifying.
  • Red = money-losing. Bounce pause, DNS fail, blocked launch.

Status chips

Inbox readyRamp day 3VerifyingBounce pauseNeutral

Ready states map 1:1: inbox ready, list clean, sequence ready, campaign sending, deal won → teal. Anything still working → orange (pulse if in-progress). Anything that loses money or blocks send → red.

Type

Page titles only

Sans for humans. Never serif inside a card, table, or form.

you@acme.dev · 20 / 40 · v=spf1 include:_spf.google.com ~all

Table

InboxCapStatus
hello@send.acme.dev20 / 40Paused
mailpit@local10 / 40Ready

Row 40px. Mono for emails, counts, DNS. Selection tint is interaction state, not health — status is carried by the chip only. Do not tint danger rows red.

Fields

Machine-truthful value

Max 40/day — higher volumes on a new inbox trigger spam filters.

File lives inside Field — no second browser box.

Field is the only box. Input, Select, Textarea, FileInput, and CheckList have no border of their own. Focus ring sits on the field, not a second inner control.

Multi-select is a CheckList inside Field — never select multiple.

Meters

Ramp cap20 / 40
Daily used8 / 20
Bounce rate1.2% / 3.0% limit
Bounce rate4.1% / 3.0% limit

Meter fill inherits the status color of what it measures — ramp/pending = orange, healthy usage = teal, red only for bounce/danger. Bounce is rate vs the 3% pause limit; fill is distance-to-pause, not a 0–100 vanity bar.

Locked launch

Launch blocked: DMARC missing. Fix records

Account mail

Welcome, invite, and password reset share one chrome: src/emails/ledger.tsx. Same tokens as this page. Campaigns never use this template — those leave on the customer's SMTP.

  • From is OutboundOS <hello@outboundos.org>. Reply-to is the same inbox.
  • Header uses the product seal, not a blank teal tile.
  • Canvas wash, charcoal rail header, paper panel, 8px radius. Button is 6px teal.
  • Serif only on the title. Mono for kicker, facts, and the raw URL.
  • Facts stack label over value so a phone never clips an address.
  • No open pixel, no click wrapper, no second green, no emoji, no shadow.
  • Inbox preview under 90 characters. One primary action. Expire in the footnote.
  • Web-safe stack in the MIME: Georgia for the title, system sans, ui-monospace.

OutboundOS

Ledger · account

Workspace

Ready to send from your domain.

WebBuddy is live. Add an inbox you own, pass DNS, then launch. OutboundOS never sends from outboundos.org on your behalf.

Workspace

WebBuddy

Next

Inbox · DNS · launch

Sending

Your SMTP

https://outboundos.org/dashboard

outboundos.org · your SMTP · hello@outboundos.org

MailFileWhen
Welcomesrc/emails/welcome.tsxSignup
Invitesrc/emails/invite.tsxSeat added
Resetsrc/emails/reset.tsxPassword forgot

Preview the live React Email templates with npm run email on port 3333. Do not add a fourth account mail without putting a specimen here first.

Marketing / auth

`/` and the auth panes are the only marketing surface. Same tokens, same 40px controls. ButtonLink is the link-shaped Button. No second palette, no shadow cards, no stock photos.

Disabled vs locked vs busy

Disabled = not applicable. Busy = the click landed and the network is still working.

Busy disables the control, swaps the label to the verb in progress, and pulses with the verifying token. Locked = blocked by a gate, always shows why and the fix. Never use a grayed primary for a deliverability gate.

Toast

Imported 48 leads

Bottom-right, 3.2s, one at a time (replace, do not stack). Only copied / test sent / imported n. Failures use banners or field errors.

Skeleton

Tables and meters while polling. Pulse token is the same as verifying; it respects prefers-reduced-motion.

Sheet

Add inbox

Bottom sheet on the phone, centered panel from tablet up. Close on backdrop. This is the only place a create form may live — never in the page header.

Events

  • Motion is 120ms opacity or translate only. No page wipes.
  • Press drops opacity. Hover tints rows. Selection tint is not health.
  • Escape and backdrop close Sheet, palette, and the rail drawer.
  • Overlays trap focus and lock body scroll. Nested locks stack.
  • ⌘K opens the palette. Arrows move, Enter runs, Escape closes.
  • Inbox: j/k move, e interested, u suppress, r reply, p poll — never while typing.
  • Table rows that navigate are keyboard links — Enter and Space.
  • Buttons default to type=button. Submit is explicit.
  • Toast allowlist: copied / test sent / imported n. Failures stay on the field.

Focus

One focus style: teal 2px ring, 2px offset. Do not invent another.

Voice

Errors state the rule and the reason. “Max 40/day — higher volumes on a new inbox trigger spam filters.” That is the product, not Instantly-generic validation.

Empty state

No inboxes yet.

Add a Mailpit inbox to send the first test.

Banner

Inbox paused — bounce rate 4.1%

Red banner. Orange is only for in-progress work, never this.

Marks

Seal
Design system
Documentation
Dashboard
ICP
Inboxes
Lists
Sequences
Campaigns
Inbox
Pipeline
Analytics
Settings