DocsSection 6
6Section 6 of 10
Frontend Architecture
Frontend Architecture
6.1 Component Hierarchy
Root Layout (app/layout.tsx)
↓
Page Layout (app/(admin)/admin/layout.tsx)
↓
Page (app/(admin)/admin/dashboard/page.tsx)
↓
Components (StatCard, ActivityFeed, etc.)
↓
UI Primitives (Button, Card, Input from app/components/ui/)
6.2 UI Component Library
Location: app/components/ui/
Philosophy: Headless-style with Tailwind
// app/components/ui/Button.tsx
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
loading?: boolean;
children: React.ReactNode;
onClick?: () => void;
}
export function Button({ variant = 'primary', size = 'md', ...props }: ButtonProps) {
const baseClasses = 'rounded-lg font-medium transition-colors';
const variantClasses = {
primary: 'bg-indigo-600 hover:bg-indigo-700 text-white',
secondary: 'bg-slate-200 hover:bg-slate-300 text-slate-900',
danger: 'bg-red-600 hover:bg-red-700 text-white',
};
const sizeClasses = {
sm: 'px-3 py-1.5 text-sm',
md: 'px-4 py-2 text-base',
lg: 'px-6 py-3 text-lg',
};
return (
<button
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`}
{...props}
/>
);
}
Usage:
<Button variant="primary" size="lg" onClick={handleSave}>
Save Changes
</Button>
6.3 State Management
No Redux! We use:
- React useState: Local component state
- React useContext: Shared state (auth, theme)
- Server state: Database is source of truth
- SWR/React Query: (Future) Data fetching/caching
Example: Auth context
// app/components/AuthProvider.tsx
const AuthContext = createContext(null);
export function AuthProvider({ children }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch('/api/me').then(r => r.json()).then(setUser);
}, []);
return (
<AuthContext.Provider value={{ user, setUser }}>
{children}
</AuthContext.Provider>
);
}
// Usage in component
const { user } = useContext(AuthContext);
6.4 Styling with Tailwind
Color scheme (Dark mode default):
Background: slate-950 (very dark)
Cards: slate-900
Borders: slate-800
Text: slate-100 (headings), slate-300 (body)
Primary: indigo-600
Success: emerald-500
Warning: amber-500
Error: red-500
Common pattern:
<div className="min-h-screen bg-slate-950 text-slate-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="bg-slate-900 rounded-xl border border-slate-800 p-6">
<h1 className="text-2xl font-bold text-white">Dashboard</h1>
<p className="mt-2 text-slate-400">
Welcome back!
</p>
</div>
</div>
</div>