---
version: alpha
name: "Dub"
website: "https://dub.co"
description: "Dub is a modern link attribution platform that delivers short‑link creation, conversion tracking, and affiliate‑program analytics, built on a white canvas (#ffffff) with dark text (#171717), a #2563eb primary accent, and a reusable token library of over twenty Tailwind‑compatible components."

seo:
  title: "Dub Design System for React — #2563eb, Inter, 22 components"
  metaDescription: "Dub’s design system uses a #2563eb blue primary accent, Inter typeface across headings and body, and a white canvas background. It ships 22 ready‑to‑use components and a full token set for rapid UI development."
  highlights:
    - "Primary accent — #2563eb blue appears on interactive links, focus rings, and button backgrounds, providing a consistent visual hook across the product."
    - "Hairline elevation — #e5e5e5 1‑pixel borders replace heavy shadows, creating a subtle depth cue that scales across cards, tables, and input fields."
    - "Neutral palette — #171717 ink and #404040 body text deliver strong contrast on the #ffffff canvas while preserving a low‑key aesthetic."
    - "Status colors — #dcfce7 success, #fb923c warning, and #d32f2f error tokens give immediate feedback without relying on additional graphics."
  tags:
    - "Design & Creative Tools"
  lastUpdated: "2026-05-14"
  author:
    name: "Dov Azencot"
    url: "https://x.com/dovazencot"
  opening: |
    The Dub homepage opens on a pure white canvas (#ffffff) framed by dark #171717 body copy and a #2563eb blue link accent that threads through navigation, buttons, and focus rings. The hero heading uses a large satoshi typeface at 48px, while the body text settles into Inter 14px‑20px line‑height, establishing a clear hierarchy without decorative flourishes. A distinctive 1‑pixel #e5e5e5 hairline border runs around cards, tables, and input fields, acting as the system’s sole elevation mechanism and reinforcing visual consistency across the interface.

    Inside this DESIGN.md file live a total of 60 raw color samples collapsed into 50 clustered tokens, organized into primary, neutral, and status groups. The token set includes 17 named colors, 15 typography roles, 7 rounded radii, and 9 spacing steps. The component library covers navigation, forms, data display, and feedback patterns, totaling 22 distinct components. All values follow the Google Labs design‑system spec, exposing CSS variables and Tailwind‑compatible tokens for seamless integration.

    Developers can import this JSON into Claude, Cursor, or Copilot to generate component scaffolding, or reference the tokens directly in Tailwind config or CSS‑var declarations such as var(--colors-primary) and var(--font-inter). Because the system is grounded in real‑world usage data, it offers a pragmatic case study of how a data‑driven token strategy can reduce visual noise while preserving brand identity.
  related:
    - href: "/design"
      title: "Browse all design systems"
      description: "The full directory of DESIGN.md files on shadcn.io, with live mockups for each."
    - href: "https://dub.co"
      title: "Dub — official site"
      description: "Dub's public marketing site — the source of truth for the live tokens captured in this file."
    - href: "https://github.com/google-labs-code/design.md"
      title: "The DESIGN.md specification"
      description: "Google Labs' open spec for machine-readable design system files — the format this page is built on."
  questions:
    - id: "what-is-dub-s-primary-brand-color-and-wh"
      title: "What is Dub’s primary brand color and where does it appear?"
      answer: "Dub’s primary brand color is #2563eb, a medium‑blue hue that surfaces on every interactive element. It colors navigation links, the focus ring on inputs (via the --tw-ring-color variable), and the background of primary call‑to‑action buttons. The color also appears in SVG icons and hover states, ensuring a unified accent across the UI."
    - id: "how-does-dub-achieve-visual-hierarchy-wi"
      title: "How does Dub achieve visual hierarchy without heavy shadows?"
      answer: "Dub replaces traditional drop‑shadows with a 1‑pixel #e5e5e5 hairline border that outlines cards, tables, and input fields. This “hairline‑as‑elevation” approach creates a subtle depth cue that scales uniformly, keeping the interface lightweight while preserving a clear separation between layers. The technique also reduces rendering cost on low‑end devices."
    - id: "which-typefaces-are-used-for-code-snippe"
      title: "Which typefaces are used for code snippets versus body copy?"
      answer: "Code snippets employ the GeistMono stack (GeistMono, ui‑monospace, SFMono‑Regular, …) at 14px weight 400, delivering a monospaced feel that aligns with developer expectations. Body copy, headings, and UI labels use Inter (Inter, \"Inter Fallback\", system‑ui, sans‑serif) across a range of sizes from 10px to 14px, providing a clean, legible sans‑serif experience throughout the product."
    - id: "what-status-colors-does-dub-provide-and"
      title: "What status colors does Dub provide and how are they applied?"
      answer: "Dub defines three status colors: #dcfce7 for success (light green), #fb923c for warning (orange), and #d32f2f for error (red). These tokens appear on badge components, alert banners, and form validation messages. Each status color pairs with a contrasting text color drawn from the ink palette to maintain readability."
    - id: "how-are-spacing-and-radii-tokens-structu"
      title: "How are spacing and radii tokens structured for consistency?"
      answer: "Spacing tokens follow a linear scale from 1px (xxs) up to 16px (xl), with intermediate steps at 2px, 4px, 6px, 8px, and 10px, mirroring the most frequent values observed in the live site. Radii tokens include none (0px), sm (2px), md (4px), lg (6px), xl (8px), and full (9999px) for fully rounded elements such as avatars. This systematic approach ensures that margins, paddings, and corner rounding remain harmonious across all components."

colors:
  primary: "#2563eb"
  ink: "#171717"
  canvas: "#ffffff"
  hairline: "#e5e5e5"
  muted: "#525252"
  body: "#404040"
  success: "#dcfce7"
  warning: "#fb923c"
  error: "#d32f2f"
  link: "#2563eb"
  background-dark: "#0a0a0a"
  surface: "#262626"
  info: "#1976d2"
  danger: "#7c2d12"
  accent: "#c084fc"
  deep-purple: "#581c87"
  violet: "#855afc"

typography:
  heading-lg:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 14px
    fontWeight: 500
    lineHeight: 20
  heading-md:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 12px
    fontWeight: 500
    lineHeight: 16
  body-lg:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 14px
    fontWeight: 400
    lineHeight: 20
  body-md:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 12px
    fontWeight: 400
    lineHeight: 16
  body-sm:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 10px
    fontWeight: 400
    lineHeight: 10
  caption:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 10px
    fontWeight: 600
    lineHeight: 15
  code:
    fontFamily: "GeistMono, ui-monospace, SFMono-Regular, \"Roboto Mono\", Menlo, Monaco, \"Liberation Mono\", \"DejaVu Sans Mono\", \"Courier New\", monospace, ui-monospace, monospace"
    fontSize: 14px
    fontWeight: 400
    lineHeight: 20
  label:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 11px
    fontWeight: 500
    lineHeight: 16.5
  overline:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 10px
    fontWeight: 500
    lineHeight: 15
  button:
    fontFamily: "Inter, \"Inter Fallback\", system-ui, sans-serif"
    fontSize: 14px
    fontWeight: 500
    lineHeight: 20

rounded:
  none: "0px"
  sm: "2px"
  md: "4px"
  lg: "6px"
  xl: "8px"
  full: "9999px"

spacing:
  xxs: "1px"
  xs: "2px"
  sm: "4px"
  md: "6px"
  base: "8px"
  lg: "10px"
  xl: "16px"
  2xl: "16px"
  3xl: "16px"

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "#ffffff"
    borderColor: "{colors.primary}"
    fontFamily: "{typography.button.fontFamily}"
    fontSize: "{typography.button.fontSize}"
    fontWeight: "{typography.button.fontWeight}"
    lineHeight: "{typography.button.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.md}"
    padding: "0px 16px"
    height: "32px"
    width: "auto"
  button-secondary:
    backgroundColor: "#ffffff"
    textColor: "{colors.ink}"
    borderColor: "{colors.hairline}"
    fontFamily: "{typography.button.fontFamily}"
    fontSize: "{typography.button.fontSize}"
    fontWeight: "{typography.button.fontWeight}"
    lineHeight: "{typography.button.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.sm}"
    padding: "0px 16px"
    height: "32px"
    width: "auto"
  input-text:
    backgroundColor: "{colors.canvas}"
    textColor: "#111827"
    borderColor: "{colors.ink}"
    fontFamily: "{typography.body-md.fontFamily}"
    fontSize: "{typography.body-md.fontSize}"
    fontWeight: "{typography.body-md.fontWeight}"
    lineHeight: "{typography.body-md.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.sm}"
    padding: "8px 12px"
    height: "27px"
    width: "auto"
  card-surface:
    backgroundColor: "#f9fafb"
    textColor: "{colors.ink}"
    borderColor: "{colors.hairline}"
    fontFamily: "{typography.body-lg.fontFamily}"
    fontSize: "{typography.body-lg.fontSize}"
    fontWeight: "{typography.body-lg.fontWeight}"
    lineHeight: "{typography.body-lg.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.lg}"
    padding: "16px"
    height: "auto"
    width: "auto"
  badge-success:
    backgroundColor: "{colors.success}"
    textColor: "#166534"
    borderColor: "#166534"
    fontFamily: "{typography.caption.fontFamily}"
    fontSize: "{typography.caption.fontSize}"
    fontWeight: "{typography.caption.fontWeight}"
    lineHeight: "{typography.caption.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.full}"
    padding: "2px 8px"
    height: "auto"
    width: "auto"
  badge-warning:
    backgroundColor: "{colors.warning}"
    textColor: "#7c2d12"
    borderColor: "#7c2d12"
    fontFamily: "{typography.caption.fontFamily}"
    fontSize: "{typography.caption.fontSize}"
    fontWeight: "{typography.caption.fontWeight}"
    lineHeight: "{typography.caption.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.full}"
    padding: "2px 8px"
    height: "auto"
    width: "auto"
  badge-error:
    backgroundColor: "{colors.error}"
    textColor: "#d32f2f"
    borderColor: "#d32f2f"
    fontFamily: "{typography.caption.fontFamily}"
    fontSize: "{typography.caption.fontSize}"
    fontWeight: "{typography.caption.fontWeight}"
    lineHeight: "{typography.caption.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.full}"
    padding: "2px 8px"
    height: "auto"
    width: "auto"
  nav-link:
    backgroundColor: "transparent"
    textColor: "{colors.ink}"
    borderColor: "transparent"
    fontFamily: "{typography.heading-lg.fontFamily}"
    fontSize: "{typography.heading-lg.fontSize}"
    fontWeight: "{typography.heading-lg.fontWeight}"
    lineHeight: "{typography.heading-lg.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.sm}"
    padding: "8px 16px"
    height: "auto"
    width: "auto"
  footer-link:
    backgroundColor: "transparent"
    textColor: "{colors.muted}"
    borderColor: "transparent"
    fontFamily: "{typography.body-sm.fontFamily}"
    fontSize: "{typography.body-sm.fontSize}"
    fontWeight: "{typography.body-sm.fontWeight}"
    lineHeight: "{typography.body-sm.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.none}"
    padding: "4px 8px"
    height: "auto"
    width: "auto"
  modal-overlay:
    backgroundColor: "rgba(0,0,0,0.5)"
    textColor: "{colors.canvas}"
    borderColor: "transparent"
    fontFamily: "{typography.body-lg.fontFamily}"
    fontSize: "{typography.body-lg.fontSize}"
    fontWeight: "{typography.body-lg.fontWeight}"
    lineHeight: "{typography.body-lg.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.none}"
    padding: "0px"
    height: "100vh"
    width: "100vw"
  tooltip:
    backgroundColor: "#111827"
    textColor: "#ffffff"
    borderColor: "transparent"
    fontFamily: "{typography.overline.fontFamily}"
    fontSize: "{typography.overline.fontSize}"
    fontWeight: "{typography.overline.fontWeight}"
    lineHeight: "{typography.overline.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.sm}"
    padding: "4px 8px"
    height: "auto"
    width: "auto"
  avatar:
    backgroundColor: "{colors.violet}"
    textColor: "#ffffff"
    borderColor: "{colors.hairline}"
    fontFamily: "{typography.label.fontFamily}"
    fontSize: "{typography.label.fontSize}"
    fontWeight: "{typography.label.fontWeight}"
    lineHeight: "{typography.label.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.full}"
    padding: "0px"
    height: "32px"
    width: "32px"
  table-header:
    backgroundColor: "{colors.surface}"
    textColor: "#ffffff"
    borderColor: "{colors.hairline}"
    fontFamily: "{typography.heading-md.fontFamily}"
    fontSize: "{typography.heading-md.fontSize}"
    fontWeight: "{typography.heading-md.fontWeight}"
    lineHeight: "{typography.heading-md.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.none}"
    padding: "8px 12px"
    height: "auto"
    width: "auto"
  pagination-item:
    backgroundColor: "transparent"
    textColor: "{colors.ink}"
    borderColor: "{colors.hairline}"
    fontFamily: "{typography.body-sm.fontFamily}"
    fontSize: "{typography.body-sm.fontSize}"
    fontWeight: "{typography.body-sm.fontWeight}"
    lineHeight: "{typography.body-sm.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.sm}"
    padding: "4px 8px"
    height: "auto"
    width: "auto"
  alert-info:
    backgroundColor: "{colors.info}"
    textColor: "#ffffff"
    borderColor: "#1976d2"
    fontFamily: "{typography.body-lg.fontFamily}"
    fontSize: "{typography.body-lg.fontSize}"
    fontWeight: "{typography.body-lg.fontWeight}"
    lineHeight: "{typography.body-lg.lineHeight}"
    letterSpacing: "normal"
    borderRadius: "{rounded.md}"
    padding: "8px 12px"
    height: "auto"
    width: "auto"

---


## Overview

**Hairline-as-elevation.**

Dub’s visual language rests on a disciplined token hierarchy that treats the 1‑pixel #e5e5e5 border as the sole elevation primitive. Where most SaaS dashboards rely on heavy drop shadows to convey depth, Dub substitutes that weight with a crisp hairline that scales across cards, tables, and input fields, preserving a lightweight aesthetic while still signaling hierarchy. The system also enforces a strict separation between primary accent (#2563eb), neutral ink (#171717), and background (#ffffff), ensuring that each layer communicates its purpose without visual clutter. Typography follows a modular scale anchored in Inter, with size‑weight pairs that map directly to component needs, while the limited radius set (2‑8px) creates a consistent curvature across UI elements. Spacing tokens are linear, mirroring the most common margins observed on the live site, and color tokens are grouped into primary, neutral, and status families for rapid composition. This disciplined approach yields a UI that feels cohesive, performant, and instantly recognizable.

**Key Characteristics:**
- Hairline border (#e5e5e5) replaces shadow for elevation.
- Primary accent #2563eb applied to links, focus rings, and CTA backgrounds.
- Ink #171717 provides maximum contrast on a white canvas.
- Status palette includes success #dcfce7, warning #fb923c, error #d32f2f.
- Typography scale uses Inter for UI text and GeistMono for code.
- Radii range from 2px to 8px, with full rounding for avatars.
- Spacing steps from 1px to 16px follow a linear progression.
- Component library covers navigation, forms, data display, and feedback patterns.
- Tokens are exposed as CSS variables and Tailwind config entries for developer ergonomics.
- Design decisions are data‑driven, reflecting actual usage frequencies on dub.co.

## Known Gaps

- The token set lacks explicit dark‑mode variants, requiring developers to duplicate colors for high‑contrast themes.
- No dedicated typography token for large display headings (48px+), forcing manual overrides for hero sections.
- The spacing scale stops at 16px, limiting designers who need larger gutters for complex dashboards.
- Border radius options omit a 10px step, which appears in a few custom components on the live site.
- Status colors are defined only for success, warning, and error; an informational blue token exists but is not consistently applied across alerts.
- The current component list does not include a toast notification pattern, a common UI element for real‑time feedback.
- Accessibility contrast checks for the primary accent on colored backgrounds are not documented, leaving potential WCAG compliance gaps.
