
Paddle Design System
Source & Stack
\- Site:
Typography \- No custom font detected in page source โ likely system-font stack or self-hosted via \_next/static \- Type scale is clean and editorial: large display headlines (h1 hero, bold weight), smaller section labels (h2โh3), compact body copy \- Heading style: sentence case, high contrast against dark/light backgrounds \- Code blocks on engineering blog use monospace (likely JetBrains Mono or Fira Code via Astro)
Color Philosophy \- Primary brand: Deep navy / near-black backgrounds for hero sections with white text (inverted logo variant: paddle-logo-inverted.svg) \- Light mode: White page backgrounds with dark text; subtle hover states (--paddle-color-background-hover) \- Accent: Paddle green (used for CTAs, status badges, success indicators) \- Destructive / alert: Red tone for destructive actions in menus (e.g., "Revoke" API key) \- Neutral grays: Used for table rows, secondary labels, dividers \- Two-logo system confirms dual-mode support: paddle-logo.svg (dark) and paddle-logo-inverted.svg (light)
Spacing \- Base unit: 4px grid (inferred from UI screenshots showing 8/16/24/32/48px rhythm) \- Table cells: padding-top offset of 120px for overlay states; sticky offsets top: 80px \- Section spacing: generous vertical padding between marketing sections (~64โ96px)
Component Defaults
\- Tables: Composable (TableHeader, TableBody, TableColumn, TableRow, TableCell); horizontal scroll with fade gradient; full-width row hover via CSS box-shadow trick; React Portals for dropdowns
\- Buttons: Primary (filled, green/dark), Secondary (outlined or ghost), Destructive (red label)
\- Status pills / badges: Inline components within table cells
\- Pagination: URL-param driven, cursor-based; separate
Layout \- Max content width: ~1280px centered, full-bleed section backgrounds \- Nav: Top horizontal bar, dark/inverted background, mega-menu dropdowns \- Marketing pages: Full-width hero โ alternating feature cards โ social proof logos โ CTA footer \- Dashboard: Sidebar nav (dark) + content area; tables span full content width with extended hover backgrounds \- Responsive: Horizontal scroll on tables preferred over column hiding; mobile nav collapses to hamburger
/ ============================================================ PADDLE DESIGN SYSTEM โ CSS Custom Properties Source: inferred from paddle.com + paddle.engineering Framework: Next.js + React Aria ============================================================ /
:root { / --- Brand Colors --- / --paddle-color-brand-primary: #1a1a2e; / deep navy โ hero bg, nav / --paddle-color-brand-accent: #2ecc71; / paddle green โ CTA, success / --paddle-color-brand-accent-hover: #27ae60; / darker green on hover /
/ --- Background --- / --paddle-color-background-page: #ffffff; --paddle-color-background-section-alt: #f7f8fa; / light gray alt sections / --paddle-color-background-hover: #f0f2f5; / table row hover, referenced in eng blog / --paddle-color-background-overlay: rgba(255, 255, 255, 0.6); / pending overlay / --paddle-color-background-dark: #0f0f1a; / hero / nav dark bg / --paddle-color-background-card: #ffffff;
/ --- Text --- / --paddle-color-text-primary: #0f0f1a; / near-black for headings / --paddle-color-text-secondary: #4a5568; / muted body / labels / --paddle-color-text-tertiary: #718096; / placeholder, meta / --paddle-color-text-inverse: #ffffff; / text on dark bg / --paddle-color-text-link: #2ecc71; / anchor links, accent / --paddle-color-text-destructive: #e53e3e; / destructive actions /
/ --- Border --- / --paddle-color-border-default: #e2e8f0; --paddle-color-border-focus: #2ecc71; --paddle-color-border-subtle: #f0f2f5;
/ --- Status / Semantic --- / --paddle-color-status-success: #2ecc71; --paddle-color-status-success-bg: #f0fff4; --paddle-color-status-warning: #f6ad55; --paddle-color-status-warning-bg: #fffbeb; --paddle-color-status-error: #e53e3e; --paddle-color-status-error-bg: #fff5f5; --paddle-color-status-info: #4299e1; --paddle-color-status-info-bg: #ebf8ff; --paddle-color-status-neutral: #a0aec0; --paddle-color-status-neutral-bg: #f7fafc; / Active / Expiring Soon pill variants observed in dashboard screenshots / --paddle-color-status-expiring: #ed8936; --paddle-color-status-revoked: #718096;
/ --- Typography --- / --paddle-font-family-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; --paddle-font-family-mono: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
--paddle-font-size-xs: 0.75rem; / 12px / --paddle-font-size-sm: 0.875rem; / 14px / --paddle-font-size-base: 1rem; / 16px / --paddle-font-size-md: 1.125rem; / 18px / --paddle-font-size-lg: 1.25rem; / 20px / --paddle-font-size-xl: 1.5rem; / 24px / --paddle-font-size-2xl: 1.875rem; / 30px / --paddle-font-size-3xl: 2.25rem; / 36px / --paddle-font-size-4xl: 3rem; / 48px โ hero display /
--paddle-font-weight-regular: 400; --paddle-font-weight-medium: 500; --paddle-font-weight-semibold: 600; --paddle-font-weight-bold: 700;
--paddle-line-height-tight: 1.2; --paddle-line-height-snug: 1.375; --paddle-line-height-normal: 1.5; --paddle-line-height-relaxed: 1.625;
/ --- Spacing (4px base grid) --- / --paddle-space-1: 0.25rem; / 4px / --paddle-space-2: 0.5rem; / 8px / --paddle-space-3: 0.75rem; / 12px / --paddle-space-4: 1rem; / 16px / --paddle-space-5: 1.25rem; / 20px / --paddle-space-6: 1.5rem; / 24px / --paddle-space-8: 2rem; / 32px / --paddle-space-10: 2.5rem; / 40px / --paddle-space-12: 3rem; / 48px / --paddle-space-16: 4rem; / 64px / --paddle-space-20: 5rem; / 80px โ sticky top offset / --paddle-space-24: 6rem; / 96px / --paddle-space-30: 7.5rem; / 120px โ overlay padding /
/ --- Border Radius --- / --paddle-radius-sm: 4px; --paddle-radius-md: 8px; --paddle-radius-lg: 12px; --paddle-radius-xl: 16px; --paddle-radius-full: 9999px; / pills / badges /
/ --- Shadows --- / --paddle-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); --paddle-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07), 0 1px 3px rgba(0, 0, 0, 0.06); --paddle-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.05); --paddle-shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.1), 0 10px 10px rgba(0, 0, 0, 0.04); / Extended row background โ from eng blog source snippet / --row-background: transparent;
/ --- Transitions --- / --paddle-transition-fast: 100ms ease; --paddle-transition-base: 150ms ease; / used in table row hover (blog confirmed) / --paddle-transition-slow: 300ms ease;
/ --- Layout --- / --paddle-max-width-content: 1280px; --paddle-nav-height: 64px;
/ --- z-index scale --- / --paddle-z-base: 0; --paddle-z-above: 1; / pending overlay (blog confirmed) / --paddle-z-dropdown: 100; / portalled dropdowns / --paddle-z-modal: 200; --paddle-z-toast: 300; }
/ CSS @property for animatable gradient (from eng blog) /
@property --fade-color {
syntax: "
/ Dark mode โ nav/hero uses dark bg by default; dashboard sidebar is always dark / @media (prefers-color-scheme: dark) { :root { --paddle-color-background-page: #0f0f1a; --paddle-color-background-section-alt: #1a1a2e; --paddle-color-background-hover: #1e2030; --paddle-color-background-card: #16162a; --paddle-color-border-default: #2d3748; --paddle-color-border-subtle: #1a1a2e; --paddle-color-text-primary: #f7fafc; --paddle-color-text-secondary: #a0aec0; --paddle-color-text-tertiary: #718096; --paddle-color-background-overlay: rgba(15, 15, 26, 0.6); } }
Paddle Design Tokens Reference
Color Tokens
| Token | Value | Usage |
|---|---|---|
| --paddle-color-brand-primary | #1a1a2e | Nav, hero background |
| --paddle-color-brand-accent | #2ecc71 | Primary CTA, success, links |
| --paddle-color-brand-accent-hover | #27ae60 | CTA hover state |
| --paddle-color-background-page | #ffffff | Default page bg |
| --paddle-color-background-section-alt | #f7f8fa | Alternating sections |
| --paddle-color-background-hover | #f0f2f5 | Table row hover (confirmed in eng blog) |
| --paddle-color-background-dark | #0f0f1a | Hero / sidebar |
| --paddle-color-background-overlay | rgba(255,255,255,0.6) | Pending state overlay + blur |
| --paddle-color-text-primary | #0f0f1a | Headings, body |
| --paddle-color-text-secondary | #4a5568 | Labels, secondary copy |
| --paddle-color-text-inverse | #ffffff | Text on dark backgrounds |
| --paddle-color-text-destructive | #e53e3e | Destructive menu items |
| --paddle-color-border-default | #e2e8f0 | Card edges, dividers |
| --paddle-color-status-success | #2ecc71 | Active badge |
| --paddle-color-status-warning | #f6ad55 | Expiring Soon badge |
| --paddle-color-status-error | #e53e3e | Error / failed payment |
| --paddle-color-status-revoked | #718096 | Revoked / disabled state |
Spacing Scale (4px base grid)
| Token | rem | px | Usage |
|---|---|---|---|
| --paddle-space-1 | 0.25rem | 4px | Micro gaps |
| --paddle-space-2 | 0.5rem | 8px | Icon padding |
| --paddle-space-3 | 0.75rem | 12px | Compact padding |
| --paddle-space-4 | 1rem | 16px | Default padding |
| --paddle-space-6 | 1.5rem | 24px | Card inner padding |
| --paddle-space-8 | 2rem | 32px | Section gaps |
| --paddle-space-12 | 3rem | 48px | Large section padding |
| --paddle-space-16 | 4rem | 64px | XL section gaps |
| --paddle-space-20 | 5rem | 80px | Sticky offset (spinner top) |
| --paddle-space-30 | 7.5rem | 120px | Overlay push-down |
Typography Scale
| Token | Value | Usage |
|---|---|---|
| --paddle-font-size-xs | 0.75rem / 12px | Meta, captions |
| --paddle-font-size-sm | 0.875rem / 14px | Table cells, secondary |
| --paddle-font-size-base | 1rem / 16px | Body copy |
| --paddle-font-size-lg | 1.25rem / 20px | Card headings |
| --paddle-font-size-xl | 1.5rem / 24px | Section subheadings |
| --paddle-font-size-2xl | 1.875rem / 30px | H3 / feature titles |
| --paddle-font-size-3xl | 2.25rem / 36px | H2 section headings |
| --paddle-font-size-4xl | 3rem / 48px | H1 hero display |
| --paddle-font-weight-regular | 400 | Body |
| --paddle-font-weight-semibold | 600 | Labels, nav items |
| --paddle-font-weight-bold | 700 | Headings, CTAs |
| --paddle-line-height-normal | 1.5 | Body paragraphs |
| --paddle-line-height-tight | 1.2 | Display headings |
| --paddle-font-family-base | system-ui / sans-serif stack | All UI text |
| --paddle-font-family-mono | JetBrains Mono / Fira Code | Code, API keys |
Border Radius
| Token | Value | Usage |
|---|---|---|
| --paddle-radius-sm | 4px | Input fields, small chips |
| --paddle-radius-md | 8px | Cards, dropdowns |
| --paddle-radius-lg | 12px | Large cards, modals |
| --paddle-radius-xl | 16px | Feature panels |
| --paddle-radius-full | 9999px | Status pills / badges |
Shadows
| Token | Value | Usage |
|---|---|---|
| --paddle-shadow-sm | 0 1px 2px rgba(0,0,0,0.05) | Subtle card lift |
| --paddle-shadow-md | 0 4px 6px rgba(0,0,0,0.07) | Dropdowns, card hover |
| --paddle-shadow-lg | 0 10px 15px rgba(0,0,0,0.1) | Modals, overlays |
| --paddle-shadow-xl | 0 20px 25px rgba(0,0,0,0.1) | Full-screen drawers |
Transition Tokens
| Token | Value | Usage |
|---|---|---|
| --paddle-transition-fast | 100ms ease | Micro interactions |
| --paddle-transition-base | 150ms ease | Row hover, button states (confirmed) |
| --paddle-transition-slow | 300ms ease | Modal open/close |
Paddle Design Notes
Framework \- Marketing site: Next.js (React, App Router) โ confirmed via \_next/static paths and meta-next-size-adjust tag \- Engineering blog: Astro v6.4.8 โ confirmed via meta-generator \- CMS: Prismic โ all editorial images served from images.prismic.io and paddle.cdn.prismic.io \- Dashboard/app: React + React Aria as the component foundation โ explicitly stated in the Mar 2026 design system engineering post
Theme Support \- Dual-mode confirmed: Two logo SVG variants exist (paddle-logo.svg for light, paddle-logo-inverted.svg for dark/inverted nav) \- The marketing site uses a dark inverted nav bar over white page content โ not a full dark mode toggle, but the dashboard (Paddle Billing) likely supports dark mode via design system tokens \- CSS @property is actively used for animatable gradient custom properties, suggesting a modern CSS baseline (Chrome 85+, Safari 15.4+)
Data Source Confidence \- High confidence: Color philosophy (dark navy + green accent), component architecture (React Aria, compositional tables), spacing offsets (80px, 120px sticky/overlay values), transition duration (150ms), overlay backdrop-filter blur, status pill variants (Active/Expiring Soon/Revoked) โ all confirmed from the engineering blog source code snippets \- Medium confidence: Exact font family (no found; likely system font stack or self-hosted), specific hex values for green accent and navy (inferred from visual brand analysis) \- Inferred: Border radius scale, shadow scale, full spacing system โ derived from design patterns observed in screenshots and standard Next.js SaaS conventions
Notable Patterns \- Composition over configuration: Tables (and likely all components) use a composable sub-component API rather than props-heavy monolithic components โ mirrors Radix UI / shadcn/ui patterns \- CSS-first approach: Team explicitly prefers pure CSS over JavaScript for animations and layout (row hover extended backgrounds use box-shadow + clip-path trick; loading spinner uses position: sticky; gradient animation uses @property). Performance justification: CSS runs on GPU vs JS on CPU \- React Portals for z-index avoidance: Dropdowns and overlays are portalled to DOM root to avoid z-index escalation wars โ clean stacking context architecture \- Cursor-based pagination: Matches the public Paddle API โ the team eats their own dog food (dashboard uses the same API customers use) \- Platform-native interaction model: Trackpad momentum, mouse wheel, touch flick, and keyboard nav all handled via React Aria with zero custom reimplementation \- Accessibility-first: React Aria chosen explicitly for WCAG-compliant table navigation (20+ keyboard shortcuts, screen reader modes, focus management) \- URL-driven state: Pagination writes to URL params, enabling deep-linking and tab sharing across team members


.webp)


.webp)













SaaSFrame subscriptions are sold on Lemon Squeezy, a secured online selling platform for creators.
SaaSFrame gets updated all the time! Every new update and version will immediately be made available to all SaaSFrame users.
You can generate an invoice on your Lemon Squeezy portal once you purchased SaaSFrame. You will find the link in the order confirmation email.
You can cancel your membership subscription at any moment on your profile page.โ
If you're not satisfied, you can ask for a refund within 7 days. Just send me an email at antoine[at]unmake[dot]io
You can send me an email at antoine[at]unmake[dot]io, I'll be happy to help with any questions.