Design System
Ghost’s design system follows one core principle: containers get out of the way; data speaks. Every visual decision is about reducing noise and making the information stand out — cards are nearly invisible, borders are barely there, and the only things that catch your eye are the actual data: HTTP methods, status codes, timing numbers, and content. The design avoids decoration for its own sake — no glass effects, no heavy shadows, no gradients on containers. Premium means restraint and precision, not more visual weight.
The entire design system is defined in a single CSS file using Tailwind v4’s @theme directive (no tailwind.config.ts). Every color, spacing value, font, and animation is a CSS custom property, making themes as simple as overriding these variables.
Typography
Section titled “Typography”Ghost uses two fonts, both bundled as woff2 files (no CDN, no external requests):
| Role | Font | Weights | Format | Usage |
|---|---|---|---|---|
| UI | Space Grotesk | 300–700 (variable) | woff2, 2 files (Latin + Latin Extended) | All interface text — labels, buttons, headings, body copy. Chosen for its clean geometric shapes with just enough personality to feel premium without being distracting. |
| Code | JetBrains Mono | 400–500 (variable) | woff2, 2 files (Latin + Latin Extended) | All code display — request/response bodies, header values, addon scripts, agent tool outputs. Chosen for its clear character distinction (l vs 1 vs I) and comfortable reading at small sizes. |
Both use font-display: swap — the browser shows fallback system fonts immediately and swaps in the custom fonts once they load, so there’s no invisible text during page load.
CSS variables:
--font-sans:'Space Grotesk', system-ui, sans-serif--font-mono:'JetBrains Mono', monospace
Color Palette
Section titled “Color Palette”Ghost Grayscale
Section titled “Ghost Grayscale”A 12-step neutral scale with a subtle blue-purple undertone (not pure gray). Used for all surfaces, text, and borders. In dark mode, lower numbers are darker; in light mode, the scale inverts completely.
| Token | Dark Value | Light Value | Typical Usage |
|---|---|---|---|
ghost-950 | #09090b | #fafafb | App background (deepest surface) |
ghost-900 | #111118 | #f1f1f5 | Card / elevated surface background |
ghost-850 | #16161f | #e8e8ef | Popover / dropdown background |
ghost-800 | #1c1c28 | #dddde8 | Input backgrounds, borders, panel separators |
ghost-700 | #2a2a3a | #b8b8cc | Borders, dividers, scrollbar thumb |
ghost-600 | #6a6a88 | #8585a3 | Placeholder text, disabled states |
ghost-500 | #8585a3 | #6a6a88 | Muted / secondary text |
ghost-400 | #a0a0b8 | #555570 | Labels, secondary text |
ghost-300 | #c0c0d0 | #3a3a50 | Body text |
ghost-200 | #d8d8e4 | #252535 | Emphasized text, hover states |
ghost-100 | #ededf2 | #16161f | High-emphasis text, foreground |
ghost-50 | #fafafb | #09090b | Maximum contrast text |
Brand Colors
Section titled “Brand Colors”Four accent colors derived from the Ghost logo gradient (cyan → blue → purple → pink). Each has three variants: standard, dim (for backgrounds and muted states), and bright (for hover/active states).
| Color | Dark | Dark Dim | Dark Bright | Light | Light Dim | Light Bright |
|---|---|---|---|---|---|---|
| Cyan | #22d3ee | #06b6d4 | #67e8f9 | #0891b2 | #0e7490 | #06b6d4 |
| Blue | #0ea5e9 | #0284c7 | #38bdf8 | #0284c7 | #0369a1 | #0ea5e9 |
| Purple | #8b5cf6 | #7c3aed | #a78bfa | #7c3aed | #6d28d9 | #8b5cf6 |
| Pink | #ec4899 | #db2777 | #f472b6 | #db2777 | #be185d | #ec4899 |
Light theme colors are shifted deeper for better contrast on white backgrounds.
Semantic Colors
Section titled “Semantic Colors”| Token | Dark | Light | Usage |
|---|---|---|---|
success | #22c55e | #16a34a | Positive states, 2xx status codes |
warning | #eab308 | #ca8a04 | Caution states, 4xx status codes |
error | #ef4444 | #dc2626 | Error states, 5xx status codes |
info | #0ea5e9 | #0284c7 | Information, 3xx status codes |
HTTP Method Colors
Section titled “HTTP Method Colors”Each HTTP method has a dedicated color, used consistently across the traffic list, inspector, composer, and comparison views:
| Method | Dark Color | Light Color |
|---|---|---|
| GET | #22c55e (green) | #16a34a |
| POST | #0ea5e9 (blue) | #0284c7 |
| PUT | #eab308 (yellow) | #ca8a04 |
| PATCH | #8b5cf6 (purple) | #7c3aed |
| DELETE | #ef4444 (red) | #dc2626 |
| OPTIONS | #6b7280 (gray) | #4b5563 |
| HEAD | #6b7280 (gray) | #4b5563 |
Method badges use 10% opacity backgrounds with full-color text (e.g., bg-method-get/15 text-method-get), so they’re visible but don’t dominate the row.
Status Code Colors
Section titled “Status Code Colors”| Range | Text Class | Badge Class |
|---|---|---|
| 1xx (Informational) | text-ghost-400 | bg-ghost-600/10 text-ghost-400 |
| 2xx (Success) | text-success | bg-success/10 text-success |
| 3xx (Redirect) | text-info | bg-info/10 text-info |
| 4xx (Client Error) | text-warning | bg-warning/10 text-warning |
| 5xx (Server Error) | text-error | bg-error/10 text-error |
Brand Gradient
Section titled “Brand Gradient”The signature Ghost gradient appears throughout the app — in the logo, accent borders, status bar accent line, and hover effects.
Dark theme:
--gradient-ghost: linear-gradient(135deg, #22d3ee, #0ea5e9, #8b5cf6, #ec4899);--gradient-ghost-subtle: linear-gradient(135deg, #06b6d4, #7c3aed);--gradient-ghost-horizontal: linear-gradient(90deg, #22d3ee, #8b5cf6, #ec4899);Light theme (deeper stops for contrast):
--gradient-ghost: linear-gradient(135deg, #0891b2, #0284c7, #7c3aed, #db2777);--gradient-ghost-subtle: linear-gradient(135deg, #0e7490, #6d28d9);--gradient-ghost-horizontal: linear-gradient(90deg, #0891b2, #7c3aed, #db2777);Gradient utility classes:
.gradient-text— applies the horizontal gradient as text color viabackground-clip: text.gradient-border-l— 2px left accent border via::beforepseudo-element.gradient-border-b— 2px bottom accent border via::afterpseudo-element.gradient-border-t— 2px top accent border via::beforepseudo-element (with overflow hidden).gradient-glow— box-shadow glow using cyan and purple at low opacity
Components
Section titled “Components”21 restyled shadcn/ui components, all remapped to Ghost design tokens. Every component that comes from shadcn/ui has been restyled — the default shadcn appearance is not used anywhere.
Button
Section titled “Button”| Variant | Appearance |
|---|---|
default | Cyan background with dark text (primary action) |
destructive | Red background (dangerous action) |
outline | Ghost-700 border, transparent background |
secondary | Ghost-800 background |
ghost | Fully transparent, shows on hover |
link | Text-only, underlined |
| Size | Height |
|---|---|
default | 36px (h-9) |
xs | 28px (h-7) |
sm | 32px (h-8) |
lg | 40px (h-10) |
icon | 36×36px |
icon-xs | 24×24px |
icon-sm | 32×32px |
icon-lg | 40×40px |
| Variant | Appearance |
|---|---|
default | Ghost-800 background with ghost-700 border |
ghost | Transparent background, no border, subtle hover |
Sizes: default (h-9), sm (h-8), lg (h-10). Focus state: cyan border at 50% opacity with cyan ring at 20%.
Select
Section titled “Select”Uses Radix primitives. Trigger: ghost-800 background, ghost-700 border, h-9. Content dropdown: ghost-850 background, ghost-700 border, max height 320px. Selected item indicator: cyan text color.
Other Components
Section titled “Other Components”| Component | Key Styling Details |
|---|---|
| Textarea | Ghost-800 background, ghost-700 border, 80px minimum height, vertical resize enabled |
| Checkbox | 16×16px, rounded 4px corners, ghost-800 background. Checked: cyan background with dark check icon. Focus: 3px cyan ring. |
| Switch | Two sizes: default (h-1.15rem, w-8) and sm (h-3.5, w-6). Checked: primary background. |
| Badge | Rounded full (pill shape). Variants: default, secondary, destructive, outline, ghost, link. |
| Card | Ghost-900 background (dark) / white (light), ghost-700 border, rounded-xl, subtle shadow. Padding: 24px vertical, 24px horizontal content. |
| Dialog | Overlay: black at 60% opacity with backdrop blur. Content: ghost-900 background, ghost-700 border, rounded-xl, deep shadow. Max width: 32rem (sm). Close button optional. |
| DropdownMenu | Ghost-850 background, ghost-700 border, rounded-lg, deep shadow. Item height: 36px. Focus: ghost-800 background. Destructive items: error color with 10% error background on focus. |
| ContextMenu | Same styling as DropdownMenu (shared design language for all menus). |
| Menubar | Trigger text: 11px, ghost-400. Hover/active: ghost-800 background. Content: ghost-900, rounded-md. |
| Tooltip | Inverted colors (foreground as background, background as foreground). Zero delay by default. Arrow matches foreground. |
| Alert | Default: card styling. Destructive: error text with card background. |
| Progress | 8px height bar, rounded full. Track: primary at 20%. Indicator: primary solid. |
| Separator | Border color. Horizontal: 1px tall, full width. Vertical: full height, 1px wide. |
| Label | 12px uppercase with wider letter spacing, ghost-400 color. |
| FormField | Wrapper with optional label, hint (ghost-500), and error (error color, 12px). |
| Collapsible | Thin wrapper around Radix, no custom styling. |
| ScrollArea | Scrollbar thumb: ghost-700, rounded full. |
| TagInput | Complex host management input with search, bulk add, collapse/expand. Container: ghost-700 border, ghost-800 background. Tags: ghost-700 background, 11px text, individual remove buttons. |
IconButton (Custom Component)
Section titled “IconButton (Custom Component)”A custom Ghost component (not shadcn) that wraps Phosphor icons with built-in tooltips:
- ghost variant: ghost-500 text, ghost-800 background on hover
- subtle variant: ghost-400 text, ghost-850 background on hover
- Default icon size: 14×14px
- Tooltip: ghost-800 background, ghost-200 text, ghost-700 border, 12px text
Themes
Section titled “Themes”Ghost supports two themes — dark and light — implemented via a data-theme attribute on the root HTML element. The theme is toggled via a sun/moon icon in the command bar or the command palette, and persists to localStorage.
Dark Theme (Default)
Section titled “Dark Theme (Default)”The default theme. The deepest background (ghost-950) is #09090b — nearly pure black with a hint of blue. Cards (ghost-900) are #111118 — barely distinguishable from the background, making them feel like windows into the content rather than containers around it. Text ranges from ghost-600 (placeholder, 40% legible) to ghost-50 (maximum emphasis, nearly white).
The ghost logo uses mix-blend-mode: screen in dark mode, which makes it glow against dark backgrounds.
Light Theme
Section titled “Light Theme”Activated by setting data-theme="light" on the document root. The light theme overrides every single color token in the system:
- Grayscale inverts completely —
ghost-950becomes the lightest color (#fafafb),ghost-50becomes the darkest (#09090b) - Brand colors shift deeper — cyan goes from
#22d3eeto#0891b2, purple from#8b5cf6to#7c3aed, ensuring adequate contrast on white backgrounds - Semantic colors shift deeper — success from
#22c55eto#16a34a, etc. - Method colors shift deeper — same pattern, all darkened for legibility
- All three gradient definitions regenerate with deeper stops
- shadcn semantic tokens remap — card background becomes white, popover becomes white, borders use light ghost values
- Logo blend mode changes to
multiply(the inverse ofscreen, works on light backgrounds)
Both themes are equal quality — Ghost is not “dark-first with a light afterthought.” The light theme has its own tuned color palette, not just inverted dark values.
Animations
Section titled “Animations”13 keyframe animations, all designed to be subtle and functional rather than decorative:
| Animation | Duration | Easing | Purpose |
|---|---|---|---|
flow-flash | 1.2s | ease-out | Cyan glow on newly arrived flow rows, fades to transparent |
skeleton-shimmer | 1.5s | ease-in-out, infinite | Loading skeleton pulse, opacity 6% → 12% |
view-enter | 200ms | ease-out | View entry: fade in + slide up 4px |
panel-reveal | 250ms | cubic-bezier(0.34, 1.56, 0.64, 1) | Panel entry: fade in + slide up 8px, springy overshoot |
sort-bounce | 200ms | ease-out | Column sort arrow: 1px bounce up |
ghost-breathe | — | — | Logo ambient pulse: opacity 20% → 35%, scale 1 → 1.04 |
status-pulse | 2s | ease-in-out, infinite | Status dot expanding ring |
tap-pulse | 400ms | ease-out, forwards | Device tap indicator: scale 0.5 → 2.5, opacity 1 → 0 |
cursor-blink | 600ms | ease-in-out, infinite | Chat streaming cursor: opacity 30% → 100% |
overlay-backdrop-in | 150ms | ease-out | Modal backdrop fade in |
overlay-panel-in | 200ms | cubic-bezier(0.34, 1.56, 0.64, 1) | Modal panel scale 97% → 100%, springy |
slide-over-in | 200ms | ease-out | Slide-over panel entrance from right |
slide-over-out | 200ms | ease-in | Slide-over panel exit to right |
Stagger Animation
Section titled “Stagger Animation”The .stagger-enter class creates a cascading entrance effect for lists and grids. Up to 6 children are staggered with 50ms increments (0, 50, 100, 150, 200, 250ms delay), each using the view-enter animation at 250ms.
Sidebar Navigation Micro-interaction
Section titled “Sidebar Navigation Micro-interaction”Sidebar navigation buttons (.sidebar-nav-btn) have a subtle scale interaction:
- Hover: scale 1.05 (100ms ease)
- Active (clicking): scale 0.95
- Active state indicator: a 2px-tall gradient bar (
::afterpseudo-element) that scales from 0 to full width via a 150ms CSS transition
Reduced Motion
Section titled “Reduced Motion”All animations respect the prefers-reduced-motion media query. When the user has enabled reduced motion in their operating system preferences, all animation durations are forced to 0.01ms (effectively instant) and limited to a single iteration.
Panel Separators
Section titled “Panel Separators”The draggable dividers between resizable panels have gradient feedback:
- Horizontal separator: 8px tall, ghost-800 background,
row-resizecursor. On hover/active: gradient from cyan → purple → pink (90° horizontal) - Vertical separator: 8px wide, ghost-800 background,
col-resizecursor. On hover/active: gradient from cyan → purple → pink (180° vertical)
Accessibility
Section titled “Accessibility”Focus Indicators
Section titled “Focus Indicators”All interactive elements use a visible cyan outline on keyboard focus:
:focus-visible { outline: 2px solid var(--color-cyan); outline-offset: 2px; border-radius: 2px;}Mouse clicks do NOT show the outline (:focus:not(:focus-visible) removes it), so keyboard users get clear focus indicators without cluttering the UI for mouse users.
Cursor Rules
Section titled “Cursor Rules”All button and [role="button"] elements automatically get cursor: pointer. Disabled elements and [aria-disabled="true"] get cursor: not-allowed.
Text Selection
Section titled “Text Selection”Selected text uses a cyan highlight at 30% opacity via color-mix(), maintaining brand consistency even in text selection.
Keyboard Navigation
Section titled “Keyboard Navigation”All panels, lists, menus, and interactive elements support full keyboard navigation. The command palette (Ctrl+K) provides keyboard-driven access to all major actions.
Build Configuration
Section titled “Build Configuration”- Tailwind CSS v4 via
@tailwindcss/viteplugin (notailwind.config.tsorpostcss.config.ts) - All design tokens defined via CSS
@themedirective inindex.css - Animation library:
tw-animate-css(imported alongside Tailwind) - Path alias:
@→./src - Dev server: port 5173, proxies
/apitolocalhost:9090,/wsas WebSocket - Source maps:
hidden(for Sentry, not served to browser)