Next.js Frontend Website Development
Next.js is a React framework with SSR, SSG, ISR, App Router, and built-in optimization. The choice between Next.js and SPA depends on requirements: Next.js is needed where SEO, initial load time, and server-side business logic near the UI are important.
App Router vs Pages Router
Starting with Next.js 13+, the primary approach is App Router (/app directory):
app/
├── layout.tsx — root layout (html, body)
├── page.tsx — home page
├── blog/
│ ├── page.tsx — /blog
│ └── [slug]/
│ └── page.tsx — /blog/[slug]
└── api/
└── route.ts — API endpoint
Server components (RSC) by default — rendered on the server, don't include JS in the client bundle. Client-side — 'use client' directive.
Rendering strategies
// Static (SSG) — generated at build time
export default async function BlogPost({ params }) {
const post = await db.post.findUnique({ where: { slug: params.slug } });
return <article>{post.content}</article>;
}
export async function generateStaticParams() {
const posts = await db.post.findMany({ select: { slug: true } });
return posts.map(p => ({ slug: p.slug }));
}
// Dynamic (SSR) — rendered on each request
export const dynamic = 'force-dynamic';
// ISR — rebuild after N seconds
export const revalidate = 60;
Image optimization
<Image> component automatically:
- Converts to WebP/AVIF
- Generates
srcsetfor different resolutions - Lazy loading by default
- Prevent layout shift with explicit width/height
import Image from 'next/image';
<Image src="/hero.jpg" width={1200} height={630} alt="Hero" priority />
Metadata API
SEO via App Router Metadata API:
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Title | Site',
description: 'Page description',
openGraph: {
title: 'OG Title',
images: [{ url: '/og.jpg', width: 1200, height: 630 }],
},
};
// Dynamic metadata
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await fetchPost(params.slug);
return { title: post.title, description: post.excerpt };
}
Server Actions
Forms without API routes via Server Actions:
'use server';
async function submitForm(formData: FormData) {
const name = formData.get('name');
await db.contact.create({ data: { name } });
revalidatePath('/contacts');
}
// In component
<form action={submitForm}>
<input name="name" />
<button type="submit">Submit</button>
</form>
Performance
-
Bundle analyzer:
@next/bundle-analyzer— finds heavy dependencies - Partial Prerendering (PPR): static shell + dynamic suspense zones (Next.js 14+)
- React cache(): deduplication of fetch requests within one render
Deployment
Next.js natively deploys to Vercel (zero-config). Alternatives: Netlify, Docker container with next start, Coolify for self-hosted.
Timeline
Frontend on Next.js for informational site (5–10 pages, SSG, Tailwind CSS): 1–2 weeks. Full site with App Router, Server Actions, authorization, dynamic pages: 2–6 weeks depending on scope.







