Better-In design system — tokens, typography, layout, components, motion, accessibility. Load when building any UI.
Better-In is a social network that respects users. The UI is clean, fast, and purposeful. No dark patterns, no engagement bait, no visual noise.
Personality: Calm confidence. Bloomberg-dense information but Vercel-clean chrome.
Define in src/styles.css under @layer base { :root { ... } }:
:root {
/* Brand */
--color-brand: #2563EB; /* blue-600 — primary CTA, links, active states */
--color-brand-hover: #1D4ED8; /* blue-700 */
--color-brand-subtle: #EFF6FF; /* blue-50 — hover bg on light */
/* Surface */
--color-bg: #FFFFFF;
--color-bg-secondary: #F9FAFB; /* gray-50 — sidebar, right panel */
--color-bg-tertiary: #F3F4F6; /* gray-100 — hover, input bg */
/* Border */
--color-border: #E5E7EB; /* gray-200 */
--color-border-strong: #D1D5DB; /* gray-300 — focused inputs */
/* Text */
--color-text: #111827; /* gray-900 */
--color-text-secondary:#6B7280; /* gray-500 */
--color-text-tertiary: #9CA3AF; /* gray-400 — timestamps, placeholders */
--color-text-inverted: #FFFFFF;
/* Semantic */
--color-success: #16A34A; /* green-600 */
--color-warning: #D97706; /* amber-600 */
--color-error: #DC2626; /* red-600 */
--color-info: #2563EB; /* same as brand */
/* Salary (jobs) */
--color-salary: #059669; /* emerald-600 — always visible, never hidden */
}
.dark {
--color-brand: #4C9AFF;
--color-brand-hover: #6BAFFF;
--color-brand-subtle: #1E3A5F;
--color-bg: #0A0A0A;
--color-bg-secondary: #111111;
--color-bg-tertiary: #1A1A1A;
--color-border: #2A2A2A;
--color-border-strong: #3A3A3A;
--color-text: #F9FAFB;
--color-text-secondary:#A1A1AA;
--color-text-tertiary: #71717A;
--color-text-inverted: #0A0A0A;
--color-success: #4ADE80;
--color-warning: #FCD34D;
--color-error: #F87171;
--color-salary: #34D399;
}
Rules:
text-[var(--color-text)] or map tokens to Tailwind utilities via @theme.#2563EB is the only accent color. No secondary accent.Font: Geist Sans (primary), Geist Mono (metrics, code, timestamps).
/* src/styles.css */
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap');
:root {
--font-sans: 'Geist', system-ui, -apple-system, sans-serif;
--font-mono: 'Geist Mono', 'Fira Code', monospace;
}
| Token | Size | Weight | Leading | Use |
|---|---|---|---|---|
--text-xs | 11px | 400 | 1.4 | Timestamps, badges |
--text-sm | 13px | 400 | 1.5 | Secondary labels, metadata |
--text-base | 15px | 400 | 1.6 | Body text, post content |
--text-md | 16px | 500 | 1.5 | UI labels, nav items |
--text-lg | 18px | 600 | 1.4 | Card titles, section headers |
--text-xl | 22px | 700 | 1.3 | Page titles |
--text-2xl | 28px | 700 | 1.2 | Hero/display |
Rules:
--font-mono at --text-xs.Desktop (≥1024px):
┌──────────────────────────────────────────────────────────┐
│ TopNav (h-14, sticky) │
├──────────┬───────────────────────────┬───────────────────┤
│ Sidebar │ Main (flex-1, max-w-2xl) │ Right (w-80) │
│ w-60 │ px-4 py-6 │ hidden <1280px │
│ sticky │ │ sticky │
│ top-14 │ │ top-14 │
└──────────┴───────────────────────────┴───────────────────┘
Mobile (<768px):
┌──────────────────┐
│ TopNav (h-14) │
├──────────────────┤
│ Main (full width)│
│ px-4 py-4 │
├──────────────────┤
│ BottomNav (h-16) │
└──────────────────┘
// AppShell.tsx pattern
<div className="min-h-screen bg-[var(--color-bg)]">
<TopNav />
<div className="mx-auto max-w-screen-xl px-4">
<div className="flex gap-6 pt-14"> {/* pt = topnav height */}
<Sidebar className="hidden lg:block w-60 shrink-0 sticky top-14 h-[calc(100vh-3.5rem)]" />
<main className="flex-1 min-w-0 max-w-2xl py-6">{children}</main>
<aside className="hidden xl:block w-80 shrink-0 sticky top-14 h-[calc(100vh-3.5rem)] py-6">{rightPanel}</aside>
</div>
</div>
<BottomNav className="lg:hidden" />
</div>
Use Tailwind's 4px-base scale. Key values:
2 (8px) — tight: icon padding, badge padding3 (12px) — compact: list item padding4 (16px) — default: card padding, section gaps6 (24px) — comfortable: section spacing8 (32px) — loose: page-level separationAll feed items, job listings, profile summaries, and conversation previews use the Card primitive.
┌─ card ─────────────────────────────────────────────────┐
│ bg-white dark:bg-[--color-bg-secondary] │
│ border border-[--color-border] │
│ rounded-xl │
│ p-4 or p-5 │
│ hover:shadow-sm transition-shadow │
│ │
│ ┌─ card-header ──────────────────────────────────────┐ │
│ │ [Avatar 40px] [Name 500] · [Timestamp mono] │ │
│ │ [Headline secondary] │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ ┌─ card-body ────────────────────────────────────────┐ │
│ │ Post content, 15px, line-clamp-5 by default │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ ┌─ card-actions ─────────────────────────────────────┐ │
│ │ [👍 Like] [💬 Comment] [↗ Share] │ │
│ │ text-sm text-[--color-text-secondary] │ │
│ └────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘
Rules:
rounded-xl on all cards (12px radius). Never rounded-lg (too small) or rounded-2xl (too bubbly).shadow-sm on hover only.divide-y divide-[--color-border].┌─ job card ──────────────────────────────────────────────┐
│ [Company logo 48px] Title (600 weight) │
│ Company · Location · Remote badge │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ │
│ 💰 $120k – $160k (emerald, --font-mono, always shown) │
│ 📅 Posted 2 days ago · Expires in 28 days │
│ [Apply] [Save] │
└─────────────────────────────────────────────────────────┘
Salary is always text-[var(--color-salary)] in --font-mono. Never hidden. If somehow missing, show "Salary not disclosed" in --color-error.
// Three sizes only
<Avatar size="sm" /> // 32px — comment threads, compact lists
<Avatar size="md" /> // 40px — feed cards, nav
<Avatar size="lg" /> // 96px — profile page header
// Always with initials fallback:
// bg-[--color-brand-subtle] text-[--color-brand] font-medium
Rules:
rounded-full.alt text: "Avatar for {name}".ring-2 ring-white dark:ring-[--color-bg].// Primary — brand blue, white text
<Button variant="primary">Connect</Button>
// bg-[--color-brand] text-white hover:bg-[--color-brand-hover]
// px-4 py-2 rounded-lg font-medium text-sm
// Secondary — border, transparent bg
<Button variant="secondary">Message</Button>
// border border-[--color-brand] text-[--color-brand] bg-transparent
// hover:bg-[--color-brand-subtle]
// Ghost — no border, text only
<Button variant="ghost">View profile</Button>
// text-[--color-text-secondary] hover:bg-[--color-bg-tertiary]
// Destructive
<Button variant="destructive">Disconnect</Button>
// bg-[--color-error] text-white hover:bg-red-700
All buttons: transition-colors duration-150 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[--color-brand]
/* Base input styles */
border border-[--color-border]
bg-[--color-bg]
rounded-lg
px-3 py-2
text-base /* 15px */
text-[--color-text]