ADR-005: Next.js for Frontend Framework¶
Status: ✅ Accepted
Date: 2024-02-28 (Q1 2024)
Decision Makers: CTO, Frontend Lead
Consulted: UI/UX Designer, Full Stack Engineers
Informed: Engineering Team
Context¶
MachineAvatars needed a modern, production-ready frontend framework for building the customer-facing web application.
Requirements:
- SEO-Friendly: Marketing pages must rank in Google (organic traffic critical)
- Performance: Fast page loads (< 2s) for chatbot interface
- 3D Rendering: Support Three.js for 3D avatar chatbots
- Real-Time: WebSocket support for voice chatbot streaming
- Developer Experience: Fast development, good tooling
- Team Expertise: Leverage existing React knowledge
- Production-Ready: Battle-tested at scale
Constraints:
- Team size: 2 frontend engineers
- Timeline: MVP in 8 weeks
- Budget: Minimize infrastructure costs
Decision¶
We selected Next.js 14 (App Router) with TypeScript and Tailwind CSS.
Technology Stack¶
{
"next": "14.1.6",
"react": "18.2.0",
"typescript": "5.x",
"three": "0.171.0", // 3D avatars
"framer-motion": "^11.0.8", // Animations
"axios": "^1.6.7", // API calls
"tailwindcss": "^3.4.1" // Styling
}
Architecture Pattern¶
machineagents-fe/
├── app/ # Next.js 14 App Router
│ ├── (marketing)/ # Public pages (SSG)
│ │ ├── page.tsx # Homepage
│ │ ├── about/ # About page
│ │ └── pricing/ # Pricing page
│ ├── dashboard/ # Auth-required (SSR)
│ │ ├── page.tsx
│ │ └── chatbots/
│ └── api/ # API Routes (BFF pattern)
├── components/ # React components
│ ├── 3d/ # Three.js components
│ └── chat/ # Chat UI
├── lib/ # Utilities
└── public/ # Static assets
Alternatives Considered¶
Alternative 1: Create React App (CRA)¶
Evaluated: Standard React with CRA tooling
Pros:
- ✅ Simple, minimal setup
- ✅ Team already familiar
- ✅ No server-side complexity
- ✅ Client-side only (simple deployment)
Cons:
- ❌ No SSR: Poor SEO (marketing pages won't rank)
- ❌ No SSG: Can't pre-render pages
- ❌ Slow initial load: Large JS bundle
- ❌ No built-in routing: Need React Router
- ❌ No API routes: Need separate backend
- ❌ CRA deprecated: Meta no longer maintains
SEO Impact:
- CRA: Google sees blank page initially (bad rankings)
- Next.js: Google sees full HTML (good rankings)
Why Rejected: Poor SEO, CRA is effectively deprecated
Alternative 2: Vite + React¶
Evaluated: Vite for build tooling + React
Pros:
- ✅ Fastest build times (esbuild)
- ✅ Modern tooling
- ✅ Excellent developer experience
- ✅ Active development (maintained)
Cons:
- ❌ No SSR built-in: Manual setup required
- ❌ No routing: Need React Router
- ❌ No SEO solution: Client-side only by default
- ❌ Manual configuration: More setup vs. Next.js
Setup Time:
- Vite + React: 2-3 weeks (configure SSR, routing, etc.)
- Next.js: 2 days (batteries included)
Why Rejected: Too much manual work vs. Next.js out-of-box features
Alternative 3: Remix¶
Evaluated: Remix (modern fullstack React framework)
Pros:
- ✅ Excellent SSR performance
- ✅ Progressive enhancement
- ✅ Nested routing (powerful)
- ✅ Great developer experience
- ✅ Focus on web fundamentals
Cons:
- ❌ Less mature: Newer framework (2021)
- ❌ Smaller ecosystem: Fewer plugins vs. Next.js
- ❌ Learning curve: Different mental model
- ❌ Team unfamiliarity: No prior experience
- ❌ Deployment complexity: Node.js server required
Community Size:
- Next.js: 120K GitHub stars, massive ecosystem
- Remix: 29K stars, smaller but growing
Why Rejected: Too risky for production timeline, smaller ecosystem
Alternative 4: SvelteKit¶
Evaluated: SvelteKit (Svelte framework)
Pros:
- ✅ Excellent performance (smallest bundle sizes)
- ✅ Great developer experience
- ✅ Less boilerplate than React
- ✅ Built-in SSR
Cons:
- ❌ Team doesn't know Svelte: Learning curve
- ❌ Smaller ecosystem: Fewer libraries
- ❌ Three.js integration: Less documented
- ❌ Hiring challenge: Harder to find Svelte devs
Retraining Cost:
- 2 engineers × 4 weeks learning = 320 hours
- Opportunity cost: ~$15K
Why Rejected: Team knows React, can't afford learning curve
Alternative 5: Astro (Static Site Generator)¶
Evaluated: Astro for content-heavy marketing site
Pros:
- ✅ Extremely fast (0 JS by default)
- ✅ Perfect for marketing pages
- ✅ Can embed React components
- ✅ Excellent SEO
Cons:
- ❌ Not a full framework: Need separate app for dashboard
- ❌ Two codebases: Marketing (Astro) + App (React)
- ❌ Team coordination: Maintain consistency across 2 projects
Why Rejected: Split architecture too complex for small team
Decision Rationale¶
Why Next.js?¶
1. SEO + Performance (Best of Both Worlds)
// Static Site Generation (SSG) for marketing pages
export async function generateStaticParams() {
return [{ slug: "pricing" }, { slug: "about" }];
}
// Pre-rendered at build time → instant load, perfect SEO
export default function MarketingPage({ params }) {
return <div>Content</div>;
}
// Server-Side Rendering (SSR) for dynamic pages
export default async function DashboardPage() {
const data = await fetchUserData();
return <Dashboard data={data} />;
}
Result:
- Marketing pages: Instant load (pre-rendered HTML)
- Dashboard: Fresh data on every request
- SEO: 95/100 Lighthouse score
2. Zero Configuration (Batteries Included)
# Out of the box:
✅ File-based routing
✅ API routes (backend-for-frontend)
✅ Image optimization
✅ Font optimization
✅ CSS/Sass support
✅ TypeScript support
✅ Fast Refresh (HMR)
✅ Production builds optimized
vs. Vite/CRA: Manual setup for each ❌
3. Vercel Deployment (Free Tier Perfect for Us)
# .github/workflows/deploy.yml (auto-deploy on push)
- name: Deploy to Vercel
run: vercel --prod
# Free tier includes:
- Unlimited bandwidth
- 100GB/month
- Auto SSL
- Global CDN
- Preview deployments
Cost Comparison:
- Vercel free tier: $0/month
- AWS Amplify: $15+/month
- Self-hosted: $50+/month (VM + CDN)
4. Three.js Integration (Proven)
// 3D Avatar Component (works perfectly)
import { Canvas } from "@react-three-fiber";
import { useGLTF } from "@react-three/drei";
export default function Avatar3D() {
return (
<Canvas>
<Model url="/avatar.glb" />
</Canvas>
);
}
Ecosystem:
- React Three Fiber: 25K stars (mature)
- Drei helpers: 7K stars
- Works seamlessly with Next.js
5. Huge Ecosystem
Next.js plugins used:
- next-auth (authentication)
- next-sitemap (SEO)
- @vercel/analytics
- react-hot-toast (notifications)
- framer-motion (animations)
All battle-tested with Next.js
Consequences¶
Positive Consequences¶
✅ Fast Development: MVP in 8 weeks (vs. 12 with manual setup)
✅ SEO Success: Homepage ranks #3 for "AI chatbot" (organic traffic)
✅ Performance: Lighthouse 95/100 (excellent UX)
✅ Developer Experience: Hot reload <200ms, TypeScript autocomplete
✅ Free Hosting: Vercel free tier sufficient for current scale
✅ Three.js Works: 3D avatars render perfectly
✅ Team Productivity: Familiar React, no learning curve
Negative Consequences¶
❌ Vendor Lock-in: Some Vercel-specific features (edge functions)
❌ Bundle Size: React + Next.js = 80KB+ (vs. Svelte 5KB)
❌ Server Costs (Future): Will need paid tier beyond 100GB/month
❌ App Router Learning Curve: New paradigm (vs. Pages Router)
Mitigation Strategies¶
For Vendor Lock-in:
- Can deploy to Netlify, AWS, self-hosted
- Avoid Vercel-specific APIs where possible
For Bundle Size:
- Code splitting (dynamic imports)
- Tree shaking
- Image optimization
Implementation Details¶
Project Structure¶
machineagents-fe/
├── app/
│ ├── (marketing)/
│ │ ├── layout.tsx # Marketing layout
│ │ ├── page.tsx # Homepage (SSG)
│ │ ├── pricing/page.tsx # Pricing (SSG)
│ │ └── features/ # Feature pages
│ ├── dashboard/
│ │ ├── layout.tsx # Auth-required layout
│ │ ├── page.tsx # Dashboard home
│ │ ├── chatbots/ # Chatbot management
│ │ └── settings/ # User settings
│ └── api/ # Backend-for-frontend
│ ├── auth/route.ts
│ └── chatbots/route.ts
├── components/
│ ├── 3d/
│ │ └── AvatarCanvas.tsx # Three.js 3D avatar
│ ├── chat/
│ │ ├── ChatInterface.tsx
│ │ └── MessageBubble.tsx
│ └── ui/ # Reusable UI
├── lib/
│ ├── api.ts # API client (Axios)
│ └── auth.ts # Auth helpers
└── public/
├── avatars/ # GLB 3D models
└── images/
Performance Optimizations¶
// Image optimization (automatic)
import Image from "next/image";
<Image
src="/avatar.png"
width={300}
height={300}
alt="Avatar"
priority // Preload critical images
/>;
// Code splitting (dynamic import)
const Avatar3D = dynamic(() => import("@/components/3d/Avatar"), {
loading: () => <Spinner />,
ssr: false, // Don't render on server (Three.js client-only)
});
// Font optimization
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
Compliance & Security¶
Authentication:
- NextAuth.js (session management)
- HTTP-only cookies (no localStorage)
- CSRF protection built-in
API Security:
- Rate limiting (middleware)
- Input validation (Zod)
- CORS properly configured
SEO:
- Automatic sitemap generation
- Structured data (JSON-LD)
- Open Graph tags
Migration Path¶
Scenario 1: Migrate to Remix¶
If Next.js becomes limiting:
- Both use React components (portable)
- Rewrite routing (different conventions)
- Migrate data fetching (loaders vs. getServerSideProps)
- Estimated time: 8 weeks
Scenario 2: Migrate to Self-Hosted¶
If Vercel costs too high:
- Deploy to Azure Container Apps
- Use Docker + Node.js server
- Configure CDN (Azure CDN)
- Estimated time: 2 weeks
Review Schedule¶
Next Review: 2025-08-31 (18 months after implementation)
Review Criteria:
- Performance still excellent (Lighthouse > 90)
- Team velocity still high (> 10 features/month)
- No major framework limitations encountered
- Hosting costs manageable (< $500/month)
Related ADRs¶
- ADR-004: Microservices Architecture - API Gateway pattern
- ADR-008: Payment Integration - API routes pattern (planned)
Evidence & Metrics¶
Development Metrics (12 months):
- Time to MVP: 8 weeks (vs. 12 weeks estimated for alternatives)
- Features shipped: 145 features
- Build time: 45 seconds (optimized)
- Developer satisfaction: 4.6/5
Production Metrics:
- Lighthouse Score: 95/100
- Core Web Vitals:
- LCP: 1.2s (Good)
- FID: 8ms (Good)
- CLS: 0.05 (Good)
- Uptime: 99.98% (Vercel)
- Bandwidth: 65GB/month (within free tier)
External References:
- Next.js Showcase - Companies using Next.js
- Vercel Analytics - Performance monitoring
Last Updated: 2025-12-26
Review Date: 2025-08-31
Status: Active and successful
"Next.js: React on rails."