Skip to content

⚡ Next.js

📋 Overview

Next.js 13+ introduces the App Router, which provides a more intuitive file-system based routing system with React Server Components.

🏗️ App Router Architecture

📁 Directory Structure

src/app/
├── (frontend)/          # Frontend route group
│   ├── layout.tsx      # Root layout
│   ├── page.tsx        # Home page
│   ├── events/         # Events route
│   │   ├── page.tsx    # Events listing
│   │   └── [id]/       # Dynamic route
│   │       └── page.tsx # Individual event
│   └── about/          # About route
│       └── page.tsx    # About page
├── (admin)/            # Admin route group
│   ├── layout.tsx      # Admin layout
│   └── dashboard/      # Admin dashboard
│       └── page.tsx    # Dashboard page
└── api/                # API routes
    ├── events/         # Events API
    │   └── route.ts    # Events endpoint
    └── health/         # Health check
        └── route.ts    # Health endpoint

🔗 Route Groups

Route groups (parentheses) allow us to organize routes without affecting the URL structure:

tsx
export default function FrontendLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div className="frontend-layout">
      <Header />
      <main>{children}</main>
      <Footer />
    </div>
  )
}

🖥️ Server vs Client Components

🖥️ Server Components (Default)

Server Components render on the server and send HTML to the client:

tsx
// Server Component - renders on server
async function EventList() {
  const events = await getEvents() // Server-side data fetching
  
  return (
    <div>
      {events.map(event => (
        <EventCard key={event.id} event={event} />
      ))}
    </div>
  )
}

💻 Client Components

Client Components render in the browser and handle interactivity:

tsx
'use client' // Mark as client component

function EventForm() {
  const [title, setTitle] = useState('')
  const [description, setDescription] = useState('')

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()
    // Handle form submission
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        placeholder="Event title"
      />
      <textarea
        value={description}
        onChange={(e) => setDescription(e.target.value)}
        placeholder="Event description"
      />
      <button type="submit">Create Event</button>
    </form>
  )
}

📡 Data Fetching

🖥️ Server-Side Data Fetching

tsx
async function EventsPage() {
  const events = await getEvents()
  
  return (
    <div>
      <h1>Upcoming Events</h1>
      <EventList events={events} />
    </div>
  )
}

🔌 API Routes

tsx
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
  try {
    const events = await getEvents()
    return NextResponse.json(events)
  } catch (error) {
    return NextResponse.json(
      { error: 'Failed to fetch events' },
      { status: 500 }
    )
  }
}

export async function POST(request: NextRequest) {
  try {
    const body = await request.json()
    const event = await createEvent(body)
    return NextResponse.json(event, { status: 201 })
  } catch (error) {
    return NextResponse.json(
      { error: 'Failed to create event' },
      { status: 500 }
    )
  }
}

🖼️ Image Optimization

Next.js provides automatic image optimization:

tsx
import Image from 'next/image'

function EventImage({ event }: { event: Event }) {
  return (
    <Image
      src={event.imageUrl}
      alt={event.title}
      width={400}
      height={300}
      className="rounded-lg"
      priority={event.isFeatured} // Load featured images immediately
    />
  )
}

🔤 Font Optimization

tsx
import { Inter, Poppins } from 'next/font/google'

const inter = Inter({ 
  subsets: ['latin'],
  variable: '--font-inter'
})

const poppins = Poppins({
  weight: ['400', '500', '600', '700'],
  subsets: ['latin'],
  variable: '--font-poppins'
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={`${inter.variable} ${poppins.variable}`}>
      <body className="font-sans">
        {children}
      </body>
    </html>
  )
}

⚡ Performance Optimization

✂️ Code Splitting

Next.js automatically code-splits by route and component:

tsx
// Lazy load heavy components
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <div>Loading...</div>,
  ssr: false // Disable server-side rendering for client-only components
})

📊 Bundle Analysis

bash
# Analyze bundle size
pnpm run build
pnpm run analyze

📈 Core Web Vitals

We monitor and optimize for Core Web Vitals:

  • LCP (Largest Contentful Paint) - < 2.5s
  • FID (First Input Delay) - < 100ms
  • CLS (Cumulative Layout Shift) - < 0.1

Released under the MIT License.