Creator Hub — Design System¶
Link-in-bio platform design system. Mobile-first, 375px minimum. Tailwind CSS + vanilla HTML/JS. Competitors studied: Beacons.ai, Linktree, Stan Store, Koji, Carrd.
1. Color Palette¶
Brand Tokens¶
| Token | Hex | Tailwind Custom | Usage |
|---|---|---|---|
--color-primary |
#6C47FF |
primary |
CTAs, active states, brand accent |
--color-primary-hover |
#5535E0 |
primary-hover |
Button hover |
--color-primary-light |
#EEE9FF |
primary-light |
Tinted backgrounds, pills |
--color-secondary |
#FF6B6B |
secondary |
Social link accents, tips/payments |
--color-accent |
#00D4AA |
accent |
Success emphasis, live indicators |
--color-surface |
#FFFFFF |
surface |
Cards, modals, inputs |
--color-bg |
#F7F7FB |
bg |
Page background |
--color-border |
#E4E4F0 |
border-base |
Dividers, input outlines |
--color-text-primary |
#1A1A2E |
text-primary |
Headings |
--color-text-secondary |
#6B6B8A |
text-secondary |
Body, labels |
--color-text-muted |
#A5A5C0 |
text-muted |
Captions, placeholders |
Semantic Tokens¶
| Token | Hex | Usage |
|---|---|---|
--color-success |
#00D4AA |
Checkmarks, publish confirmed |
--color-success-bg |
#E6FAF6 |
Toast bg, status chips |
--color-error |
#FF4D6A |
Validation errors, delete actions |
--color-error-bg |
#FFF0F3 |
Error toast bg |
--color-warning |
#FFB020 |
Unsaved changes, quota warnings |
--color-warning-bg |
#FFF8E6 |
Warning toast bg |
Dark Theme Overrides (see Section 6 for full token map)¶
Primary brand purple holds in dark mode. Backgrounds invert to #0E0E1A (page) and #1A1A2E (surface).
2. Typography¶
Font Stack¶
--font-heading: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-body: 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
Google Fonts import:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@600;700;800&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
Scale¶
| Role | Size | Weight | Line-height | Tailwind classes |
|---|---|---|---|---|
display |
clamp(40px, 8vw, 64px) |
800 | 1.1 | text-5xl lg:text-7xl font-extrabold |
h1 |
clamp(32px, 5vw, 48px) |
700 | 1.2 | text-4xl lg:text-5xl font-bold |
h2 |
clamp(24px, 4vw, 36px) |
700 | 1.25 | text-3xl lg:text-4xl font-bold |
h3 |
24px |
600 | 1.3 | text-2xl font-semibold |
h4 |
20px |
600 | 1.35 | text-xl font-semibold |
body-lg |
18px |
400 | 1.6 | text-lg font-normal |
body |
16px |
400 | 1.6 | text-base font-normal |
body-sm |
14px |
400 | 1.5 | text-sm font-normal |
caption |
12px |
500 | 1.4 | text-xs font-medium |
label |
13px |
600 | 1.3 | text-[13px] font-semibold |
mono |
13px |
400 | 1.5 | text-[13px] font-mono |
3. Spacing Scale¶
Base unit: 4px
| Token | px | Tailwind |
|---|---|---|
space-1 |
4px | p-1 / m-1 |
space-2 |
8px | p-2 / m-2 |
space-3 |
12px | p-3 / m-3 |
space-4 |
16px | p-4 / m-4 |
space-5 |
20px | p-5 / m-5 |
space-6 |
24px | p-6 / m-6 |
space-8 |
32px | p-8 / m-8 |
space-10 |
40px | p-10 / m-10 |
space-12 |
48px | p-12 / m-12 |
space-16 |
64px | p-16 / m-16 |
space-20 |
80px | p-20 / m-20 |
4. Component Inventory¶
4.1 Buttons¶
Primary Button¶
bg: --color-primary (#6C47FF)
text: white, 14px font-semibold
padding: 12px 24px (py-3 px-6)
border-radius: 10px (rounded-[10px])
shadow: 0 4px 14px rgba(108,71,255,0.35)
hover: bg --color-primary-hover, shadow intensifies (0 6px 20px rgba(108,71,255,0.45))
active: scale(0.97), shadow reduced
disabled: opacity-40, cursor-not-allowed
transition: all 150ms ease
Secondary Button¶
bg: white
text: --color-primary, 14px font-semibold
border: 1.5px solid --color-primary
padding: 11px 24px (compensate for border)
border-radius: 10px
hover: bg --color-primary-light
active: scale(0.97)
shadow: none
Ghost Button¶
bg: transparent
text: --color-text-secondary, 14px font-medium
border: 1.5px solid --color-border
padding: 11px 20px
border-radius: 10px
hover: bg --color-bg, text --color-text-primary
active: scale(0.97)
Danger Button¶
bg: --color-error (#FF4D6A)
text: white, 14px font-semibold
padding: 12px 24px
border-radius: 10px
shadow: 0 4px 14px rgba(255,77,106,0.3)
hover: bg #E83055
Icon Button (square)¶
size: 40px x 40px
bg: --color-bg
border: 1.5px solid --color-border
border-radius: 10px
icon: 18px, --color-text-secondary
hover: bg white, border-color --color-primary, icon color --color-primary
4.2 Cards¶
Base Card¶
bg: white
border: 1px solid --color-border
border-radius: 16px (rounded-2xl)
padding: 24px (p-6)
shadow: 0 1px 4px rgba(0,0,0,0.06)
hover (interactive): shadow 0 8px 24px rgba(0,0,0,0.10), translateY(-2px)
transition: all 200ms ease
Profile Link Card (public page block)¶
bg: white
border: none
border-radius: 14px
padding: 16px 20px
shadow: 0 2px 8px rgba(0,0,0,0.08)
hover: shadow 0 6px 20px rgba(0,0,0,0.12), translateY(-1px)
height: min 60px
layout: flex, items-center, gap-3
left: 40px icon area (optional)
center: title (16px semibold), subtitle (13px muted)
right: chevron icon 16px
Stat Card (dashboard)¶
bg: white
border: 1px solid --color-border
border-radius: 16px
padding: 20px 24px
layout: flex-col gap-1
label: 12px font-medium text-muted uppercase tracking-wide
value: 32px font-bold text-primary
delta: 13px, green/red pill with arrow
Embed Block Card¶
bg: --color-bg
border: 1px solid --color-border
border-radius: 14px
overflow: hidden
header: 48px, platform icon + title + collapse button
body: aspect-video for video, auto for others
padding: 0 (content bleeds to edges)
4.3 Input Fields¶
Text Input¶
height: 44px
padding: 0 14px
bg: white
border: 1.5px solid --color-border
border-radius: 10px
font: 15px, --color-text-primary
placeholder: --color-text-muted
focus: border-color --color-primary, box-shadow 0 0 0 3px rgba(108,71,255,0.15)
error: border-color --color-error, box-shadow 0 0 0 3px rgba(255,77,106,0.12)
disabled: bg --color-bg, opacity 0.6
transition: border-color 150ms, box-shadow 150ms
Textarea¶
Input with Prefix/Suffix¶
wrapper: flex, border 1.5px solid --color-border, border-radius 10px
prefix: 44px wide, bg --color-bg, border-right 1px --color-border, text-muted centered
input: flex-1, border 0, focus: no shadow on input (shadow on wrapper)
suffix: same as prefix, border-left instead
Select / Dropdown¶
4.4 Toggle¶
track: 44px x 24px, border-radius 12px
bg off: --color-border
bg on: --color-primary
thumb: 20px circle, white, shadow 0 1px 3px rgba(0,0,0,0.2)
thumb position off: translateX(2px)
thumb position on: translateX(22px)
transition: background 200ms, transform 200ms
focus-visible: outline 2px --color-primary, outline-offset 2px
4.5 Avatar¶
Sizes:
xs: 24px
sm: 32px
md: 48px
lg: 64px
xl: 96px
2xl: 128px
Shape: circle (rounded-full)
Border: 2px solid white
Shadow: 0 2px 8px rgba(0,0,0,0.12)
Fallback: gradient bg using primary + secondary, initials in white
Profile hero avatar: 96px with 3px gradient ring (primary → secondary) as border, gap 2px white inset
4.6 Social Link Pill¶
height: 36px
padding: 0 14px
border-radius: 999px (rounded-full)
bg: platform-specific (see below) or --color-primary-light
icon: 16px, left-aligned, gap 8px
text: 13px font-semibold
hover: brightness(1.08), scale(1.02)
Platform colors:
Instagram: linear-gradient(135deg, #833AB4, #FD1D1D, #F77737)
TikTok: #010101
YouTube: #FF0000
Twitter/X: #000000
LinkedIn: #0A66C2
Spotify: #1DB954
Twitch: #9146FF
Discord: #5865F2
GitHub: #24292F
Custom: --color-primary
4.7 Sidebar Nav¶
width: 240px (desktop), full-screen overlay (mobile)
bg: white
border-right: 1px solid --color-border
padding: 16px 12px
Nav item:
height: 40px
padding: 0 12px
border-radius: 8px
icon: 18px, gap 10px
text: 14px font-medium text-secondary
hover: bg --color-bg, text-primary
active: bg --color-primary-light, text --color-primary, icon color primary, font-semibold
Section label:
10px font-semibold text-muted uppercase tracking-widest
padding: 8px 12px
margin-top: 16px
4.8 Modal¶
Overlay: rgba(0,0,0,0.5) backdrop-blur-sm
Container:
bg: white
border-radius: 20px
padding: 0
width: min(520px, calc(100vw - 32px))
max-height: calc(100vh - 64px)
overflow-y: auto
shadow: 0 24px 64px rgba(0,0,0,0.18)
Header:
padding: 24px 24px 0
layout: flex justify-between items-center
title: h3
close: icon-button (32px variant)
Body:
padding: 20px 24px
Footer:
padding: 0 24px 24px
layout: flex gap-3 justify-end
border-top: 1px solid --color-border (if content scrolls)
Animation:
enter: fade + scale(0.95 → 1) 200ms ease-out
exit: fade + scale(1 → 0.97) 150ms ease-in
4.9 Toast Notification¶
position: fixed, bottom 24px right 24px (mobile: bottom 16px, full-width minus 16px margin)
width: 360px (mobile: 100%)
border-radius: 14px
padding: 14px 16px
shadow: 0 8px 32px rgba(0,0,0,0.14)
layout: flex, gap 12px, items-start
Icon area: 20px icon, colored per type
Content: title 14px semibold + body 13px text-secondary
Dismiss: 16px x icon, top-right
Variants:
success: left-border 4px --color-success, icon-bg --color-success-bg
error: left-border 4px --color-error, icon-bg --color-error-bg
warning: left-border 4px --color-warning, icon-bg --color-warning-bg
info: left-border 4px --color-primary, icon-bg --color-primary-light
Animation:
enter: translateX(110%) → translateX(0) 300ms spring
exit: translateX(0) → translateX(110%) 200ms ease-in
Auto-dismiss: 4000ms, progress bar optional
5. Page Wireframes (Structured Text)¶
5.1 Public Profile Page¶
Viewport: 375px mobile, max-width 480px centered (not full-bleed)
┌─────────────────────────────────┐
│ THEME HEADER │ ← full-width, height 180px
│ gradient/image background │ theme color bleeds to top of screen
│ │
│ [AVATAR 96px] │ ← centered, overlaps into content area
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ [Name h2] │ ← text-center, mt-12 (for avatar overlap)
│ [Username @handle caption] │
│ [Bio body-sm text-secondary] │ ← max 160 chars, 3-line clamp
│ │
│ [Social Pills row, scroll x] │ ← horizontal scroll on mobile
│ IG TK YT TW SP │
│ │
│ ── LINK BLOCKS ────────────────│ ← full-width cards, 12px gap
│ [Link Card 1] │
│ [Link Card 2] │
│ [Embed Card - YouTube] │
│ [Email Capture Card] │
│ [Tip Jar Card] │
│ [Scheduling Card] │
│ ... │
│ │
│ [Powered by Creator Hub] │ ← 12px caption, bottom 16px, centered
└─────────────────────────────────┘
Desktop (640px+): max-width 480px, centered horizontally, sidebar hidden (profile is standalone).
Key layout decisions: - Avatar overlaps hero by 48px (negative margin-top on content area) - Link blocks are full-width within the 480px container, no side-by-side columns - Embed blocks auto-expand inline, no modal - Theme color applies to hero + link block accents + CTA buttons
5.2 Dashboard / Analytics Page¶
Full app layout: sidebar 240px (desktop) + main content area
[SIDEBAR] [MAIN CONTENT]
Logo ┌────────────────────────────────────────┐
───── │ Page header: "Analytics" [Date range] │
Overview ◀ active ├────────────────────────────────────────┤
Editor │ STAT CARDS ROW (4 cards, responsive) │
Appearance │ Views | Clicks | CTR | Earnings │
Settings ├────────────────────────────────────────┤
───── │ TIME-SERIES CHART (full-width) │
Domains │ line chart, 30-day default │
Billing │ hover tooltip with date/values │
───── ├────────────────────────────────────────┤
[Avatar] Justin │ TWO-COL: [Top Links table] [Referrers] │
@handle │ │
[Signout] │ link title | clicks | %bar │
│ ───────────────────────────────────── │
│ source | visits | % │
├────────────────────────────────────────┤
│ DEVICE BREAKDOWN (donut + legend) │
└────────────────────────────────────────┘
Mobile: Sidebar collapses to bottom tab bar (5 icons). Stat cards stack 2x2. Charts full-width. Tables become cards.
5.3 Block Editor Page¶
Full app layout: sidebar + editor canvas + properties panel
[SIDEBAR 240px] [CANVAS 480px max centered] [PROPERTIES PANEL 280px]
Block Library ┌────────────────────────┐ [Context-sensitive]
───────────── │ PROFILE PREVIEW HEADER │
+ Link │ [Avatar + Name] │ When block selected:
+ Header │ [Bio] │ Block type label
+ Embed │ [Social pills] │ ─────────────────
+ Email Capture ├────────────────────────┤ [Title input]
+ Scheduling │ ▓▓ LINK BLOCK ◀drag │ [URL input]
+ Tip Jar │ "My Website" │ [Icon picker]
+ Spacer │ ────────────────────── │ [Visible toggle]
+ Divider │ ▒▒ HEADER BLOCK │ [Schedule toggle]
───────────── │ "Shop Now ↓" │ ─────────────────
Saved Blocks │ ────────────────────── │ [Delete block]
│ ▒▒ EMBED BLOCK │
│ YouTube [thumbnail] │ When nothing selected:
│ ────────────────────── │ Page settings
│ [+ Add block] button │ Theme picker
└────────────────────────┘ SEO settings
↑ live preview
of public profile
Drag handle: left edge of each block, 4px wide drag zone, 20px handle icon on hover. Block selection: click → 2px primary border around block, properties panel updates. Mobile editor: single column, properties panel slides up as bottom sheet.
5.4 Landing / Signup Page¶
No sidebar. Full-bleed marketing layout.
[NAV]
Logo (left) [Sign In] [Get Started →]
[HERO SECTION] full-height viewport
headline (display clamp): "Your entire brand, one link."
subhead (body-lg): "Launch your page in 2 minutes..."
[CTA button primary: Get Started Free]
[Ghost: See example →]
hero visual: mockup of profile page on phone (right, desktop)
or below headline (mobile)
[SOCIAL PROOF BAR]
"Trusted by 10,000+ creators" | star ratings | logos
[FEATURES GRID]
3-col (desktop) / 1-col (mobile)
Each: icon (48px) + h4 + body-sm
Features: Custom Domain, Analytics, Embed Content, Email Capture,
Payments, Drag-Drop Editor, Custom Themes, SEO
[COMPARISON TABLE]
Creator Hub vs Linktree vs Beacons
rows: price, custom domain, analytics depth, embeds, payments,
email capture, scheduling
[THEME SHOWCASE]
horizontal scroll gallery of 6 preset themes
[TESTIMONIALS]
3-card grid, avatar + quote + name + handle
[PRICING]
3 cards: Free / Pro ($9/mo) / Business ($29/mo)
primary card = Pro (elevated, purple border)
[SIGNUP FORM]
email input + [Create Free Account] centered, max-width 480px
[FOOTER]
4-col links + social icons + copyright
6. Theme System¶
Token Architecture¶
Two layers: global (palette, never used directly in components) and semantic (what components reference).
:root {
/* Spacing */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-6: 24px;
--space-8: 32px;
--space-12: 48px;
/* Radius */
--radius-sm: 6px;
--radius-md: 10px;
--radius-lg: 14px;
--radius-xl: 16px;
--radius-2xl: 20px;
--radius-full: 9999px;
/* Shadows */
--shadow-sm: 0 1px 4px rgba(0,0,0,0.06);
--shadow-md: 0 4px 14px rgba(0,0,0,0.08);
--shadow-lg: 0 8px 32px rgba(0,0,0,0.12);
--shadow-xl: 0 24px 64px rgba(0,0,0,0.18);
--shadow-primary: 0 4px 14px rgba(108,71,255,0.35);
}
Light Theme (default)¶
[data-theme="light"], :root {
--color-bg: #F7F7FB;
--color-surface: #FFFFFF;
--color-surface-2: #F0F0F8;
--color-border: #E4E4F0;
--color-text-primary: #1A1A2E;
--color-text-secondary: #6B6B8A;
--color-text-muted: #A5A5C0;
--color-primary: #6C47FF;
--color-primary-hover: #5535E0;
--color-primary-light: #EEE9FF;
--color-secondary: #FF6B6B;
--color-accent: #00D4AA;
}
Dark Theme¶
[data-theme="dark"] {
--color-bg: #0E0E1A;
--color-surface: #1A1A2E;
--color-surface-2: #242438;
--color-border: #2E2E4A;
--color-text-primary: #F0F0F8;
--color-text-secondary: #9090B8;
--color-text-muted: #5A5A7A;
--color-primary: #7C5CFF; /* slightly lighter for dark bg contrast */
--color-primary-hover: #6C47FF;
--color-primary-light: #2A2044;
--color-secondary: #FF7B7B;
--color-accent: #00E4BC;
--shadow-sm: 0 1px 4px rgba(0,0,0,0.3);
--shadow-md: 0 4px 14px rgba(0,0,0,0.4);
--shadow-lg: 0 8px 32px rgba(0,0,0,0.5);
}
Profile Page Themes (user-selectable)¶
Each profile theme overrides hero bg and link-block accent color only. App chrome stays in system theme.
| Theme Name | Hero BG | Link Block | Text on Hero |
|---|---|---|---|
aurora |
linear-gradient(135deg, #6C47FF, #FF6B6B) |
white | white |
midnight |
#0E0E1A |
#1A1A2E |
white |
cotton |
#FFF0F5 |
white | #1A1A2E |
forest |
linear-gradient(135deg, #134E4A, #065F46) |
white/translucent | white |
paper |
#FFFEF7 |
#FFFFF0 |
#1A1A2E |
carbon |
#111111 |
#1C1C1C |
white |
7. Breakpoints¶
screens: {
'sm': '640px', // large phones, small tablets (landscape)
'md': '768px', // tablets
'lg': '1024px', // small laptops, iPad Pro
'xl': '1280px', // standard desktop
}
Mobile-first patterns:
- Grid: grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3
- Sidebar: hidden on mobile (bottom tab bar), lg:flex for sidebar
- Profile canvas: max-w-[480px] mx-auto w-full
- Analytics stat cards: grid grid-cols-2 lg:grid-cols-4
- Typography: all heading sizes use clamp() to avoid breakpoint jumps
8. Tailwind Config Addons¶
// tailwind.config.js additions
module.exports = {
theme: {
extend: {
colors: {
primary: {
DEFAULT: '#6C47FF',
hover: '#5535E0',
light: '#EEE9FF',
},
secondary: '#FF6B6B',
accent: '#00D4AA',
surface: '#FFFFFF',
'bg-base': '#F7F7FB',
'border-base': '#E4E4F0',
'text-primary': '#1A1A2E',
'text-secondary': '#6B6B8A',
'text-muted': '#A5A5C0',
},
fontFamily: {
heading: ['Plus Jakarta Sans', 'system-ui', 'sans-serif'],
body: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'Fira Code', 'monospace'],
},
borderRadius: {
'4xl': '2rem',
},
boxShadow: {
'primary': '0 4px 14px rgba(108,71,255,0.35)',
'primary-lg': '0 6px 20px rgba(108,71,255,0.45)',
},
maxWidth: {
'profile': '480px',
},
},
},
}
9. Motion Defaults¶
All interactive elements use transition-all duration-150 ease-out as default.
Elevation lifts use duration-200. Modal/drawer animations use duration-300.
Respect prefers-reduced-motion: wrap entrance animations in a media query check.