OfRoot Frontend Brand & UI Design Guide
> This guide is a living document for product design, marketing pages, and admin UI. Narrative first, code snippets second, so it reads as a handbook yet stays directly actionable.
---
1) Brand narrative and tone
- Position: Pragmatic, senior engineering partner. We ship secure, production-grade SaaS quickly.
- Voice: Clear, concise, direct. Prefer active voice. Avoid jargon; show proof.
- Personality: Calm confidence, high signal, humble expertise.
Use this to inform headings, CTAs, and microcopy. Examples:
- Headline: “Ship secure SaaS faster.”
- CTA: “Start free” (public), “Continue to checkout” (paid).
- Empty states: “No users yet. Invite your team to get started.”
---
2) Core visual identity
- Logo: Circular avatar found in `/public/ofroot-logo.png`. Keep generous whitespace around it (≥ logo height).
- Color system: Brand teal with neutral grays and purposeful accents.
Primary brand (teal)
- Base: `#20B2AA` (LightSeaGreen)
- Use for primary actions, focus states, and highlights.
Supporting accents
- Success: Emerald (`green-600`/`#059669`)
- Warn/Attention: Amber (`amber-600`/`#D97706`)
- Danger: Rose (`rose-600`/`#E11D48`)
- Info: Sky (`sky-600`/`#0284C7`)
Neutrals
- Use Tailwind `gray` family with accessible contrast (500–900 for text).
---
3) Design tokens (semantic, Tailwind-oriented)
Use semantic tokens in components; map them to Tailwind utilities. When needed, expose CSS variables for themeing (dark-mode, brand swaps).
CSS variables (drop into `app/globals.css` if desired):
:root {
--color-brand-50: #E6FAF7;
--color-brand-100: #CFF5F0;
--color-brand-200: #A0EBE0;
--color-brand-300: #72E1D0;
--color-brand-400: #44D7C1;
--color-brand-500: #20B2AA; /* primary */
--color-brand-600: #1B8F8A;
--color-brand-700: #166F6B;
--color-brand-800: #104E4C;
--color-brand-900: #0B3333;
--radius-card: 12px;
--radius-pill: 9999px;
--shadow-card: 0 1px 2px rgba(0,0,0,0.06), 0 2px 8px rgba(0,0,0,0.04);
}
Tailwind config extension (reference):
// tailwind.config.ts (reference snippet)
import type { Config } from 'tailwindcss';
export default {
theme: {
extend: {
colors: {
brand: {
50:'#E6FAF7',100:'#CFF5F0',200:'#A0EBE0',300:'#72E1D0',400:'#44D7C1',
500:'#20B2AA',600:'#1B8F8A',700:'#166F6B',800:'#104E4C',900:'#0B3333',
},
},
borderRadius: {
xl: '12px',
'2xl': '16px',
pill: '9999px',
},
boxShadow: {
card: 'var(--shadow-card)',
},
fontFamily: {
// Prefer system or Inter if available
sans: ['Inter', 'ui-sans-serif', 'system-ui', 'Apple Color Emoji', 'Segoe UI Emoji'],
},
},
},
} satisfies Config;
Semantic usage cheatsheet:
- Primary action: `bg-brand-600 hover:bg-brand-700 text-white`
- Subtle link: `text-brand-700 hover:text-brand-800 underline-offset-2`
- Focus ring: `focus:outline-none focus:ring-2 focus:ring-brand-500`
- Card: `rounded-xl border bg-white/80 backdrop-blur shadow-card`
---
4) Typography and rhythm
- Base size: 16px, scale using Tailwind (`text-sm`, `text-base`, `text-lg`, `text-xl`, `text-2xl`, …).
- Headings: Tight tracking for large display text; use gradient when hero emphasis is desired.
- Body: 1.5 line-height for readability. Keep line-length ≈ 60–80 characters.
Examples:
<h1 className="text-4xl sm:text-5xl md:text-6xl font-extrabold tracking-tight">
<span className="bg-gradient-to-b from-black to-gray-700 bg-clip-text text-transparent">Start your subscription</span>
</h1>
<p className="mt-3 text-base sm:text-lg text-gray-600 max-w-2xl">Concise value statement.</p>
---
5) Layout, spacing, and elevation
- Page container: `max-w-6xl mx-auto px-4 md:px-6`.
- Vertical rhythm: `py-12 md:py-16` for major sections.
- Cards: `rounded-xl border bg-white/80 backdrop-blur shadow-card`.
- Sticky asides: `md:sticky md:top-24` to keep value props visible.
---
6) Components (canonical recipes)
Buttons
<button className="inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm
bg-brand-600 text-white hover:bg-brand-700 focus:outline-none focus:ring-2 focus:ring-brand-500">
Primary
</button>
<button className="inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm
border text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-brand-500">
Secondary
</button>
Badges
<span className="inline-flex items-center rounded-full bg-black text-white px-2 py-0.5 text-[10px] leading-4">Most popular</span>
<span className="inline-flex items-center rounded-full border px-2 py-0.5 text-[10px] leading-4 text-amber-700 border-amber-200 bg-amber-50">Recommended</span>
Cards
<div className="rounded-xl border bg-white/80 backdrop-blur p-5 shadow-card">Content</div>
Forms
<input className="w-full rounded-md border px-3 py-2 text-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-brand-500" />
<label className="inline-flex items-center gap-2 text-sm"><input type="checkbox" /> Label</label>
Tables
<table className="w-full text-sm">
<thead className="text-left text-gray-500 border-b"><tr><th className="py-2">Name</th></tr></thead>
<tbody><tr className="border-b hover:bg-gray-50"><td className="py-2">Row</td></tr></tbody>
</table>
Modals
<div role="dialog" aria-modal className="w-full max-w-lg rounded-lg border bg-white shadow-lg" />
---
7) Accessibility (non-negotiable)
- Always label controls (`aria-label`, `<label for>`). Use `aria-live` for status.
- Manage focus for dialogs and menus; trap focus when open; restore on close.
- Maintain 4.5:1 contrast for body text; test dark text on light backgrounds.
- Keyboard first: all interactive elements reachable and operable via keyboard.
---
8) Motion and feel
- Use small, purposeful transitions: `transition-colors`, `transform-gpu`, subtle `hover:scale-[1.02]` for CTAs.
- Avoid parallax and heavy motion in app surfaces; prefer stability in admin.
---
9) Content patterns
- CTAs: one primary per surface. Secondary as plain or bordered buttons.
- Trust: proof bullets over marketing fluff. Show metrics and real screenshots.
- Error copy: human, actionable. E.g., “Subscription failed. Try again or contact support.”
---
10) Page archetypes
- Marketing/Subscribe: Hero, plan selector, form, sticky benefits aside.
- Auth (login/register): Minimal, with PublicNavbar and generous white space.
- Admin: Sidebar + toolbar + main content. Use SSR guards; honest zero states.
---
11) Implementation checklist
- Primary actions use brand color and accessible focus rings.
- Zero states show truthful empties; never dummy rows.
- Forms validate on blur and submit; errors announced in live regions.
- Dark mode (optional later): map CSS variables to dark palette.
---
12) Appendix: Example plan card (as shipped)
<label className="relative cursor-pointer text-left rounded-lg border p-4 block overflow-hidden
transition-colors hover:bg-gray-50">
{/* Optional centered badge */}
<div className="flex justify-center mb-2">
<span className="inline-flex items-center rounded-full bg-black text-white px-2 py-0.5 text-[9px] leading-4">Most popular</span>
</div>
<div className="flex items-center justify-between">
<div className="font-medium">Pro</div>
</div>
<div className="mt-1 text-2xl font-semibold">$19<span className="text-sm text-gray-500">/mo</span></div>
<ul className="mt-2 text-sm text-gray-600 space-y-1">
<li>• Unlimited projects</li>
<li>• Priority support</li>
<li>• Advanced analytics</li>
</ul>
</label>
---
Maintain this guide alongside code changes. When adding new components or pages, quote the relevant section here and link to concrete examples in `app/` or `components/`.