Tech Stack
Tech Stack
Frontend Framework
Next.js 15 (App Router)
-
Server Components by default
-
Server Actions for MVP (BFF pattern)
-
Progressive migration to REST API calls post-MVP
-
File-based routing in
app/directory
Styling & Design System
Tailwind CSS v4 + shadcn/ui
-
Utility-first CSS framework (v4)
-
shadcn/ui for pre-built accessible components
-
Custom design tokens in
tailwind.config.ts -
Global styles in
app/globals.css
Form Management
react-hook-form + zod
-
Type-safe form validation
-
Schema-based validation with Zod
-
Minimal re-renders
-
Built-in error handling
Example Pattern:
// Define schema
const campaignSchema = z.object({
name: z.string().min(1, "Campaign name required"),
subject: z.string().min(1, "Subject required"),
recipients: z.array(z.string().email()).min(1)
});
// Use in form
const form = useForm({
resolver: zodResolver(campaignSchema)
});
Icons
lucide-react
-
Consistent icon library
-
Tree-shakeable
-
TypeScript support
-
Example:
import { Mail, Send, Users } from 'lucide-react'
Animation & Motion
tw-animate-css + CSS Transitions
-
Use
tw-animate-cssfor standard animations (fade, slide, bounce) -
Use standard CSS transitions for hover states and micro-interactions
-
Avoid heavy JS animation libraries like Framer Motion unless absolutely necessary for complex gestures
Dark Mode
Tailwind Dark Mode (selector strategy)
-
Use
darkMode: 'selector'in Tailwind config -
Toggle class
darkon the<html>element -
Use
dark:prefix for dark mode styles (e.g.,bg-white dark:bg-slate-900)
State Management
React Context (for simple global state)
-
Theme preferences
-
User session
-
Feature flags
Zustand (for complex state, if needed)
-
Campaign editor state
-
Multi-step form state
Data Fetching
MVP: Server Actions (Next.js 15)
'use server';
export async function getCampaigns() {
const data = await db.campaigns.findMany();
return data;
}
Post-MVP: REST API with fetch/axios
const campaigns = await fetch('/api/v1/campaigns').then(r => r.json());