Show structure. Hide ornament.
Hairlines, generous whitespace, strong type hierarchy. No drop shadows, no gradient backgrounds, no decorative blobs. If a pixel doesn't earn its place, cut it.
One token model, two surfaces. The same colors, type, and motion power the marketing site, the product, and every artifact in between. Direct. Confident. Never decorative.
Paperclip is the app people use to manage AI agents for work. The brand and the product share one design system: serious software for serious work — direct, confident, never decorative.
Hairlines, generous whitespace, strong type hierarchy. No drop shadows, no gradient backgrounds, no decorative blobs. If a pixel doesn't earn its place, cut it.
Same tokens, same type ramp, same motion. The marketing site feels like a continuation of the product, not a different app. Differences are density and content, not vocabulary.
The 1:2 capsule shape is reserved for agent representation — capsule fields, org chart nodes, status indicators, avatars. Never on chrome, never on buttons. That's why it stays meaningful.
Pause, resume, override, reassign, terminate. The visual language emphasizes legibility, traceability and accountability. Buttons read like commands. Status reads like telemetry. The interface never pretends the agent is choosing — the operator is.
One token model spans two production surfaces. Theme, density, and content adapt; the vocabulary doesn't.
Editorial. Light-only in production. Astro. Tells the story, sells the product.
Grid-disciplined. Light + dark. React + Tailwind + shadcn. Where work happens.
The Paperclip mark is a minimalist line drawing of a paperclip. Functional. Recognizable at any size. Always rendered as a stroke — never filled, never decorated.
Maintain minimum clear space equal to the icon width on all sides. Below 16px, drop the wordmark and use the icon only.
Use the stroke-based mark. Pure currentColor — adapts to surface.
Never fill the paperclip shape. The line is the brand.
No gradients. No drop shadows. No effects.
Never rotate, skew, or transform the mark beyond the default ‑12°.
Always title-case. Not "PaperClip", "paperclip", or "PAPERCLIP".
Never substitute the wordmark typeface. Inter Semibold only.
Inter Tight carries display and editorial weight. Inter does every other word on the page. JetBrains Mono carries the engineering credibility — telemetry, code, timestamps. Nothing else.
The display voice. All headings, display copy, big moments. Default weight 600 — tight tracking provides the editorial gravity without leaning on bold.
font-family: 'Inter Tight', sans-serifweight: 600 · line-height: 1.02–1.2 · letter-spacing: -0.04em → -0.02emThe workhorse. Body, labels, navigation, buttons, the wordmark. ss01 + cv11 are enabled site-wide.
font-family: 'Inter', sans-seriffont-feature-settings: 'ss01', 'cv11'The engineering layer. Timestamps, hex codes, agent names, tool calls, terminal, telemetry chips. tabular-nums always on.
$ paperclip status --agent ceo ▸ alive budget 64% 4h 32m
font-family: 'JetBrains Mono', monospaceUse the role, not the size. Display roles use Inter Tight at 600. Body and labels use Inter. Mono is JetBrains Mono.
| ROLE | SAMPLE | SPEC |
|---|---|---|
| display-1 | Headline. | clamp(42, 5.5vw, 80) · 600 · ‑0.04em |
| display-2 | Section heading | clamp(40, 5.5vw, 72) · 600 · ‑0.035em |
| display-3 | Subsection | clamp(28, 3.5vw, 44) · 600 · ‑0.03em |
| display-4 | Card title | 26 · 600 · ‑0.02em |
| lede | Subhead / hero lede | 20 / 1.45 · 400 · 0 |
| body-lg | Body large — feature copy | 18 / 1.5 · 400 · 0 |
| body | Body — running text, paragraphs, default UI copy. | 16 / 1.6 · 400 · 0 |
| body-sm | Body small — secondary text, table cells, dense UI. | 14 / 1.5 · 400 · 0 |
| caption | EYEBROWS · LABELS · CATEGORY TAGS | 11 · 500 · +0.08em · UPPER |
| mono | $ paperclip status — 1042 events | 13 / 1.4 · 400 · tabular-nums |
| mono-sm | 14:32:07 · #1042 · CEO Hermes | 11 / 1.4 · 400 |
Agents wake on a schedule, check their work, and act. Delegation flows up and down the org chart automatically.
Pause. Resume. Override. Reassign. Terminate.
Inter Tight at 600. Tight tracking. Sentence-case. The tight spacing does the editorial work.
No all-caps display. No loose tracking on display sizes. Caps are reserved for the caption role.
Use the mono stack for timestamps, IDs, tool calls, agent names, hex values, terminal output. tabular-nums keeps columns aligned.
Don't dress system telemetry in editorial type. Mono is the layer that signals "this is real, this happened, this was logged."
Brand neutrals derived from office materials — bond, vellum, ink, manila folders — so screens have depth beyond generic black-on-white. Status colors carry product meaning. The agent palette is saturated gradients reserved for agents and org-chart nodes, never for chrome or buttons.
Material vocabulary: bond → linen → parchment → manila → vellum → steel → aluminum → graphite → charcoal → ink. Each is a named token, always literal — never swaps with theme. Use these when you need a specific color regardless of mode (callouts, swatches, brand marks).
Components reference these. They swap with theme. The brand neutrals above are the literal values they resolve to.
| TOKEN | LIGHT | DARK | USAGE |
|---|---|---|---|
| --bg | bond #FFF | charcoal #141413 | Page background |
| --bg-alt | linen | #141413 | Alt background, banded sections |
| --surface | parchment | #1F1D1A | Cards · panels · active states |
| --rule | vellum | #2F2C28 | Hairline borders + dividers |
| --text | ink | manila | Primary text |
| --text-2 | graphite | #9A958A | Secondary text · subhead |
| --text-muted | aluminum | #6E6960 | Captions · placeholders · mono labels |
| --accent | signal #22C55E | signal #22C55E | Focus rings · CTA hover · active dots |
Five semantic colors carry meaning across both surfaces. Each has a soft variant for backgrounds + chips and a deep variant for accessible text on those backgrounds.
Brand use only. Twelve saturated gradients reserved for the capsule motif — agent representation, org-chart nodes, status indicators, testimonial avatars. Never on buttons, status pills, or generic chrome. That's why the palette stays meaningful.
Use ink + warm neutrals for chrome. Signal green earns its place only when status truly is "alive" or "succeeded."
No gradient buttons. No agent-palette colors on chrome. Saturation in chrome dilutes the brand-language signal.
Agent palette belongs on the capsule motif — agent representation only.
Never on buttons, never on badges. The palette is a brand asset, not a decoration kit.
A 4-pixel micro and 8-pixel base. The page-level rhythm uses CSS clamp() so generous whitespace stays generous on big screens and collapses gracefully on small ones.
| TOKEN | VALUE | VISUAL | USAGE |
|---|---|---|---|
| --space-1 | 4px | Micro — chip gaps, icon padding | |
| --space-2 | 8px | Inline gaps, badge padding, label→input gap | |
| --space-3 | 12px | Button gap, dense grids | |
| --space-4 | 16px | Card padding tight, list row gap | |
| --space-5 | 24px | Card padding default, section subhead gap | |
| --space-6 | 32px | Gutter, card padding generous | |
| --space-7 | 48px | Block-level rhythm, subsection spacing | |
| --space-8 | 64px | Hero padding, section margin | |
| --space-9 | 96px | Section padding-y (default) | |
| --space-10 | 128px | Page-top, big editorial gaps | |
| --space-lg | clamp(32, +1.5vw, 48) | fluid | Card-to-card spacing in marketing |
| --space-xl | clamp(48, +3vw, 80) | fluid | Subsection blocks |
| --space-section | clamp(80, +5.5vw, 144) | fluid | Marketing section padding-y |
Radius isn't decoration — it signals what kind of thing you're touching. A pill is a primary action. A 16px rounded rect is a card. A capsule is an agent.
Status pills · code chips · table cells
Inputs · small cards · agent cards in lists
Default card · panel · feature blocks
Modals · large surfaces · terminal block
Primary CTA only. Buttons that initiate action. Also: theme toggle, badge chips.
Agents only. Stadium pill at 1:2 ratio. Reserved for capsule motif.
Pill (--r-pill) is reserved for primary actions. Echoes the capsule motif at the chrome level — the brand mark and the call-to-action are the same shape. Everything else uses 8/10/16/24px rounded rect.
Pill is primary. Secondary is 10px rounded — close to the input shape, not the agent shape.
Don't pill secondaries. Don't square-off primaries. The shape vocabulary is part of the brand.
Icons label actions, states, or help the user understand functionality quickly. They never compete with the capsule motif or compete for attention.
Stroke only. currentColor. Rounded line caps + joins.
No filled glyphs in chrome. Fills compete with capsule-motif fills.
No emoji in product UI or technical docs. Emoji is a different visual language.
Every agent is a capsule. Every capsule is an agent. The mark and the metaphor are the same shape.
Construction: border-radius: 9999px (or 50% of width). Fill: smooth linear-gradient(to bottom, anchor-a, anchor-b). Flat single-color variant available for contexts that need a solid mark.
Eight agents. Each its own gradient. Different heights signal cost, status, or output.
One initial on the agent gradient until a profile photo is uploaded. Same gradient classes as capsules — every visual of an agent shares one DNA.
The graphic generator produces on-brand artifacts — OG images, blog covers, social posts, slide backdrops — by arranging capsules into templates and colorizing them from palettes. Below: a mini, in-doc version. Production tool: paperclip-graphic-generator.
Paperclip speaks with authority about complex systems but never obscures meaning. Short sentences. Active verbs. Technical when needed, never when not.
"Paperclip uses those agents. It orchestrates them into a company — with org charts, budgets, goals, governance, and accountability."
"Pause. Resume. Override. Reassign. Terminate. You have full control over every agent in the org."
"Not a chatbot. Not an agent framework. Not a workflow builder."
"Full observability. Every ticket traced. Every decision explained. Every tool call logged."
"Paperclip is a revolutionary, AI-powered next-gen platform that empowers teams to leverage the full potential of their agentic workforce!"
"Paperclip orchestrates a team of AI agents. Org charts, budgets, goals. You hire. You approve. You ship."
"Various optimizations have been applied to ensure that runaway costs are mitigated through robust budget enforcement mechanisms."
"Every agent gets a monthly budget. When they hit it, they stop. No runaway costs. Hard limits, enforced by the system."
"🚀 Get started with Paperclip today and unlock the future of work! 💼✨"
"Open source. Self-hosted. npx paperclipai onboard and you're running."
Animation signals life and state. Entrance reveals stagger. Active elements pulse. Transitions ease at 200ms. Nothing bounces unless it has a reason — and almost nothing does.
| TOKEN | VALUE | WHERE |
|---|---|---|
| --ease-out | cubic-bezier(.2,.8,.2,1) | Entrance, hover lifts, primary motion |
| --ease-in | cubic-bezier(.4,0,1,.6) | Exit, dismissal |
| --ease-inout | cubic-bezier(.65,0,.35,1) | Scrub, pinned scroll |
| --dur-micro | 120ms | Hover color shifts, focus rings |
| --dur-short | 200ms | Default UI transitions, button hover |
| --dur-medium | 400ms | Theme swap, panel slide-in |
| --dur-long | 700ms | Hero reveals, pinned set pieces |
450ms ease-out · 140ms stagger · translateY 12 → 0
1.6s ease-in-out · infinite · alive · scale 0.85 ↔ 1.0
200ms ease-out · color shift only · no transform, no bounce
700ms ease-out · opacity 0 → 1 · translateY 24 → 0
400ms ease-out · background + color crossfade
Every motion pattern has a no-motion fallback. If the user prefers reduced motion, animations stop or shorten to a 100ms color crossfade.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 100ms !important;
scroll-behavior: auto !important;
}
}
Every component below ships in light and dark. Every interactive control has explicit default, hover, focus, active, and disabled states. Hover the state explorer chips to preview each state in place.
Agents wake on schedule or on demand. Every action logged.
Same card pattern, dark surface. Used in marketing callouts and product modals.
$ npx paperclipai onboard --yes ✓ Embedded postgres started ✓ Company created: note-taking-app ✓ CEO Hermes online (claude-sonnet-4-5) ✓ Dashboard at http://localhost:3100 $ ▍
// Self-host config export default { company: 'note-taking-app', db: 'postgres://localhost', heartbeat: 4, // hours budgets: { ceo: 60 }, }
Charts read like instruments. Ink lines on hairline grids. Mono labels. No gradients in chart fills — saturation stays in the agent palette where it carries meaning.
| AGENT | BUDGET USED | COST |
|---|---|---|
| CEO Hermes | $23.40 / $60 | |
| CMO OpenClaw | $32.00 / $40 | |
| CTO Codex | $50.00 / $50 | |
| COO Claude | $5.40 / $30 |
Semantic colors carry meaning consistently across the product. Task states use a small palette of icons + colors so the same status reads the same on a board, in a row, and in a chip.
| STATE | COLOR | PILL | DOT | EXAMPLES |
|---|---|---|---|---|
| Success | #22C55E · signal | Approved | Connected · Approved · Completed · Heartbeat alive | |
| Warning | #F59E0B · amber | Budget 80% | Budget alert · Slow heartbeat · Retrying | |
| Error | #DC2626 · red | Error | Failed · Blocked · Terminated · Budget exhausted | |
| Info | #2563EB · blue | Live run | Goal set · Budget set · In review · Focus rings |
Every ticket lives in exactly one of these states. The icon, color, and copy are fixed so the same status reads identically on the board, in a row, and in a chip.
Tokens ship as CSS custom properties (source of truth), a Tailwind theme extension for the React product, and JSON for tooling and Figma. Same names, same values. tokens.css is canonical; Tailwind and JSON exports stay aligned on release.
Import once. Semantic tokens swap under [data-theme="dark"]; brand neutrals and status colors stay literal.
:root {
/* ── Brand neutrals — material vocabulary, always literal ── */
--bond: #FFFFFF;
--linen: #F5F3F0;
--parchment: #F0ECE7;
--manila: #F3E6C4;
--vellum: #E0DCD6;
--steel: #D8DCDF;
--aluminum: #A8AEB2;
--graphite: #52585D;
--charcoal: #141413;
--ink: #0A0A0A;
/* ── Brand accent + status — literal across themes ── */
--signal: #22C55E;
--signal-soft: #DCFCE7;
--signal-deep: #188A3C;
--amber: #F59E0B;
--amber-soft: #FEF3C7;
--amber-deep: #B45309;
--red: #DC2626;
--red-soft: #FEE2E2;
--red-deep: #991B1B;
--blue: #2563EB;
--blue-soft: #DBEAFE;
--blue-deep: #1D4ED8;
/* ── Semantic tokens — light defaults ── */
--bg: var(--bond);
--bg-alt: var(--linen);
--surface: var(--parchment);
--rule: var(--vellum);
--text: var(--ink);
--text-2: var(--graphite);
--text-muted: var(--aluminum);
--input-bg: var(--bond);
--accent: var(--signal);
--accent-fg: #FFFFFF;
--accent-soft: var(--signal-soft);
--focus-ring: var(--signal);
/* ── Agent palette — 12 presets, brand only ── */
--agent-1a: #F7CFDC; --agent-1b: #1F7A3A; /* pink → forest */
--agent-2a: #C9A9E8; --agent-2b: #EE79A1; /* lavender → hot pink */
--agent-3a: #28164B; --agent-3b: #7A1530; /* purple → maroon */
--agent-4a: #F3E6C4; --agent-4b: #E3A21A; /* cream → amber */
--agent-5a: #1F4DD6; --agent-5b: #3AA35C; /* cobalt → green */
--agent-6a: #E94B27; --agent-6b: #5A1122; /* orange → maroon */
--agent-7a: #7EB6E3; --agent-7b: #EE79A1; /* sky → hot pink */
--agent-8a: #9CE8A7; --agent-8b: #BD7FF0; /* mint → violet */
--agent-9a: #F3B49E; --agent-9b: #1F4ED4; /* peach → cobalt */
--agent-10a: #F2D95F; --agent-10b: #4FBCBA; /* yellow → teal */
--agent-11a: #C2C2E8; --agent-11b: #5E3450; /* peri → mauve */
--agent-12a: #4DB9B7; --agent-12b: #3AA35C; /* teal → green */
/* ── Type ── */
--font-display: 'Inter Tight', 'Inter', system-ui, sans-serif;
--font-body: 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
/* ── Radius ── */
--r-xs: 4px;
--r-sm: 10px;
--r-md: 16px;
--r-lg: 24px;
--r-pill: 9999px;
/* ── Spacing — 4px micro, 8px base ── */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 24px;
--space-6: 32px;
--space-7: 48px;
--space-8: 64px;
--space-9: 96px;
--space-10: 128px;
--space-lg: clamp(2rem, 1.5rem + 1.5vw, 3rem);
--space-xl: clamp(3rem, 2rem + 3vw, 5rem);
--space-section: clamp(5rem, 3rem + 5.5vw, 9rem);
/* ── Motion ── */
--ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
--ease-in: cubic-bezier(0.4, 0, 1, 0.6);
--ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
--dur-micro: 120ms;
--dur-short: 200ms;
--dur-medium: 400ms;
--dur-long: 700ms;
}
[data-theme="dark"] {
--bg: var(--charcoal);
--bg-alt: #1F1D1A;
--surface: #1F1D1A;
--rule: #2F2C28;
--text: var(--manila);
--text-2: #9A958A;
--text-muted: #6E6960;
--input-bg: #1F1D1A;
--accent-fg: var(--ink);
--accent-soft: rgba(34, 197, 94, 0.14);
}
Semantic colors point at CSS vars so dark mode flips without duplicating hex in TypeScript.
import type { Config } from 'tailwindcss'
export default {
theme: {
extend: {
colors: {
// brand neutrals
bond: '#FFFFFF',
linen: '#F5F3F0',
parchment: '#F0ECE7',
manila: '#F3E6C4',
vellum: '#E0DCD6',
steel: '#D8DCDF',
aluminum: '#A8AEB2',
graphite: '#52585D',
charcoal: '#141413',
ink: '#0A0A0A',
// semantic (consume CSS vars so dark mode flips automatically)
bg: 'var(--bg)',
surface: 'var(--surface)',
rule: 'var(--rule)',
text: 'var(--text)',
'text-2': 'var(--text-2)',
muted: 'var(--text-muted)',
accent: 'var(--accent)',
// status
signal: { DEFAULT: '#22C55E', soft: '#DCFCE7', deep: '#188A3C' },
amber: { DEFAULT: '#F59E0B', soft: '#FEF3C7', deep: '#B45309' },
red: { DEFAULT: '#DC2626', soft: '#FEE2E2', deep: '#991B1B' },
blue: { DEFAULT: '#2563EB', soft: '#DBEAFE', deep: '#1D4ED8' },
},
fontFamily: {
display: ['Inter Tight', 'Inter', 'system-ui', 'sans-serif'],
sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'ui-monospace', 'monospace'],
},
borderRadius: {
xs: '4px', sm: '10px', md: '16px', lg: '24px', pill: '9999px',
},
transitionTimingFunction: {
'paperclip-out': 'cubic-bezier(0.2,0.8,0.2,1)',
'paperclip-in': 'cubic-bezier(0.4,0,1,0.6)',
'paperclip-inout': 'cubic-bezier(0.65,0,0.35,1)',
},
},
},
} satisfies Config
Neutral ramp, status, and radius for Figma and token pipelines. Not a full export of motion, spacing, or the agent palette — extend as needed.
{
"color": {
"neutral": {
"bond": { "value": "#FFFFFF" },
"linen": { "value": "#F5F3F0" },
"parchment": { "value": "#F0ECE7" },
"manila": { "value": "#F3E6C4" },
"vellum": { "value": "#E0DCD6" },
"steel": { "value": "#D8DCDF" },
"aluminum": { "value": "#A8AEB2" },
"graphite": { "value": "#52585D" },
"charcoal": { "value": "#141413" },
"ink": { "value": "#0A0A0A" }
},
"accent": { "signal": { "value": "#22C55E" } },
"status": {
"success": { "value": "#22C55E" },
"warning": { "value": "#F59E0B" },
"error": { "value": "#DC2626" },
"info": { "value": "#2563EB" }
}
},
"radius": {
"xs": { "value": "4px" },
"sm": { "value": "10px" },
"md": { "value": "16px" },
"lg": { "value": "24px" },
"pill": { "value": "9999px" }
}
}