Skip to content

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:

  1. SEO-Friendly: Marketing pages must rank in Google (organic traffic critical)
  2. Performance: Fast page loads (< 2s) for chatbot interface
  3. 3D Rendering: Support Three.js for 3D avatar chatbots
  4. Real-Time: WebSocket support for voice chatbot streaming
  5. Developer Experience: Fast development, good tooling
  6. Team Expertise: Leverage existing React knowledge
  7. 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:

  1. Both use React components (portable)
  2. Rewrite routing (different conventions)
  3. Migrate data fetching (loaders vs. getServerSideProps)
  4. Estimated time: 8 weeks

Scenario 2: Migrate to Self-Hosted

If Vercel costs too high:

  1. Deploy to Azure Container Apps
  2. Use Docker + Node.js server
  3. Configure CDN (Azure CDN)
  4. 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)

  • 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:


Last Updated: 2025-12-26
Review Date: 2025-08-31
Status: Active and successful


"Next.js: React on rails."