Next.js
Final Project
Build a complete NewsWave application from setup to production, integrating all Next.js features learned throughout the course
Time to put everything together. The final project brings together every concept you've learned — from basic routing to advanced authentication. Think of it like building a house after learning individual skills like plumbing, wiring, and carpentry. The NewsWave project you've been working on piece by piece becomes a fully integrated application. No more isolated features. Everything connects to create a professional news platform that could compete with sites like TechCrunch or Dev.to. This lesson walks through the complete build process from scratch. You'll see how all the pieces fit together in a real production application. And discover patterns that make Next.js applications scalable and maintainable.Project Structure Overview
Building NewsWave requires careful organization. Unlike a simple React app where components can live anywhere, Next.js applications need structured architecture. The App Router makes this even more important because file placement determines functionality. The complete NewsWave structure spans multiple directories. Each serves a specific purpose in the Next.js ecosystem. Some handle routing, others manage data, and a few control styling and assets. Organization becomes critical when your application grows. A well-structured Next.js project makes debugging easier, collaboration smoother, and deployment predictable. Poor structure leads to confusion about where features live and how components interact.Initial Setup and Dependencies
Creating NewsWave starts with the right foundation. Unlike Create React App, Next.js offers several starter templates and configuration options. The initial setup determines which features become available later. Dependencies matter more in Next.js because of server-side rendering. Some packages work only on the client, others only on the server. Choosing the wrong ones creates runtime errors that only appear during deployment. The NewsWave setup includes additional packages beyond basic Next.js. These handle styling, data management, and development tools. Each dependency serves a specific purpose in the final application.# Create the NewsWave project with latest Next.js
npx create-next-app@latest newswave --typescript --tailwind --eslint --app
# Navigate to project directory
cd newswave# Install additional dependencies for NewsWave
npm install date-fns clsx lucide-react
# Install development dependencies
npm install -D @types/nodeThe create-next-app command generated a complete Next.js project with TypeScript support, Tailwind CSS for styling, and ESLint for code quality. The additional packages provide date formatting (date-fns), conditional class handling (clsx), and beautiful icons (lucide-react). Try this: run npm run dev to see the default Next.js welcome page.
Root Layout Implementation
The root layout defines structure shared across all NewsWave pages. Unlike React where you manually wrap components, Next.js automatically applies layouts. The root layout becomes particularly important because it controls the HTML document structure. Every page in NewsWave shares common elements — navigation header, footer, and basic styling. The root layout prevents code duplication and ensures consistent user experience. Changes here affect the entire application. The App Router makes layouts more powerful than the Pages Router. You can nest layouts, add loading states, and handle errors at different levels. The root layout sits at the top of this hierarchy.// app/layout.js - Root layout for all NewsWave pages
import './globals.css' // Import global styles
import { Inter } from 'next/font/google' // Google Fonts integration
// Configure Inter font with Latin subset
const inter = Inter({ subsets: ['latin'] })
export const metadata = {
title: 'NewsWave - Breaking News & Analysis', // Default page title
description: 'Stay informed with breaking news, tech updates, and expert analysis', // SEO description
}export default function RootLayout({ children }) {
return (
<html lang="en"> {/* Document language for accessibility */}
<body className={inter.className}> {/* Apply Inter font */}
<div className="min-h-screen bg-gray-50"> {/* Full height container */}
{children} {/* All page content renders here */}
</div>
</body>
</html>
)
}Global Navigation Component
Navigation ties the NewsWave experience together. Users need consistent access to all sections — homepage, categories, search, and user features. The navigation component becomes the roadmap for your entire application. Next.js navigation differs from React Router. The Link component provides client-side routing with prefetching. This makes page transitions faster and more responsive. Understanding these optimizations separates good Next.js developers from great ones. The navigation component handles both desktop and mobile layouts. Responsive design becomes more important when server-side rendering means users might load pages on any device. The component needs to work without JavaScript initially, then enhance with interactivity.// components/Header.js - Main navigation component
'use client' // Enable client-side features
import Link from 'next/link' // Next.js optimized linking
import { useState } from 'react' // React hooks for state
import { Menu, X, Search } from 'lucide-react' // Icons
export default function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false) // Mobile menu state
return (
<header className="bg-white shadow-sm border-b"> {/* Header container */}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> {/* Responsive container */} <div className="flex items-center justify-between h-16"> {/* Header content */}
<Link href="/" className="text-2xl font-bold text-blue-600"> {/* Logo link */}
NewsWave
</Link>
<nav className="hidden md:flex space-x-8"> {/* Desktop navigation */}
<Link href="/category/tech" className="text-gray-700 hover:text-blue-600">Tech</Link>
<Link href="/category/world" className="text-gray-700 hover:text-blue-600">World</Link>
<Link href="/category/business" className="text-gray-700 hover:text-blue-600">Business</Link>
<Link href="/search" className="text-gray-700 hover:text-blue-600">Search</Link>
</nav> <button
className="md:hidden" {/* Show on mobile only */}
onClick={() => setIsMenuOpen(!isMenuOpen)} {/* Toggle mobile menu */}
>
{isMenuOpen ? <X size={24} /> : <Menu size={24} />} {/* Menu icon */}
</button>
</div>
</div>
</header>
)
}Homepage with Featured Articles
The NewsWave homepage showcases featured content and breaking news. This page demonstrates static site generation — articles are fetched at build time for maximum performance. The homepage sets the tone for the entire user experience. Homepage design balances information density with readability. Too much content overwhelms users. Too little makes the site appear empty. The layout needs to work across devices while highlighting important stories. Data fetching on the homepage uses getStaticProps patterns adapted for the App Router. Articles come from a mock data source initially, but the structure supports real APIs later. This approach lets you build without depending on external services.// app/page.js - NewsWave homepage
import Header from '../components/Header' // Import navigation
import ArticleCard from '../components/ArticleCard' // Import article display
import { getFeaturedArticles } from '../lib/articles' // Data fetching function
export default async function HomePage() {
const featuredArticles = await getFeaturedArticles() // Fetch articles at build time
return (
<div> {/* Page container */}
<Header /> {/* Navigation component */} <main className="max-w-7xl mx-auto px-4 py-8"> {/* Main content */}
<section className="mb-12"> {/* Hero section */}
<h1 className="text-4xl font-bold text-gray-900 mb-4">Breaking News</h1>
<p className="text-xl text-gray-600 mb-8">Stay informed with the latest updates</p>
</section>
<section> {/* Featured articles section */}
<h2 className="text-2xl font-bold mb-6">Featured Stories</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {/* Responsive grid */} {featuredArticles.map((article) => ( // Render each article
<ArticleCard
key={article.id} // Unique React key
article={article} // Pass article data
/>
))}
</div>
</section>
</main>
</div>
)
}Article Detail Pages with Dynamic Routing
Individual article pages showcase Next.js dynamic routing capabilities. Each article gets its own URL using the slug pattern. These pages demonstrate static site generation for dynamic content — articles are pre-rendered at build time for optimal performance. Dynamic routing in the App Router uses file-based conventions. The[slug] folder tells Next.js to generate routes for each article automatically. This pattern scales from dozens to thousands of articles without manual route configuration.
Article pages need rich metadata for SEO and social sharing. Next.js provides built-in support for generating meta tags, Open Graph images, and structured data. These features help NewsWave articles rank well in search results and look professional when shared.
// app/articles/[slug]/page.js - Dynamic article pages
import Header from '../../../components/Header' // Navigation component
import { getArticleBySlug, getAllArticleSlugs } from '../../../lib/articles' // Data functions
import { formatDate } from '../../../lib/utils' // Date formatting utility
// Generate static paths for all articles at build time
export async function generateStaticParams() {
const slugs = await getAllArticleSlugs() // Get all article slugs
return slugs.map((slug) => ({ slug })) // Return array of slug objects
}// Generate metadata for each article page
export async function generateMetadata({ params }) {
const article = await getArticleBySlug(params.slug) // Get article data
return {
title: `${article.title} | NewsWave`, // Dynamic page title
description: article.excerpt, // Article excerpt as description
openGraph: { // Social media preview
title: article.title,
description: article.excerpt,
type: 'article',
}
}
}export default async function ArticlePage({ params }) {
const article = await getArticleBySlug(params.slug) // Get article by slug
return (
<div>
<Header /> {/* Navigation */}
<article className="max-w-4xl mx-auto px-4 py-8"> {/* Article container */}
<header className="mb-8"> {/* Article header */}
<h1 className="text-4xl font-bold text-gray-900 mb-4">{article.title}</h1>
<div className="text-gray-600 mb-4"> {/* Article metadata */}
<span>By {article.author}</span> •
<span> {formatDate(article.publishedAt)}</span> •
<span> {article.readTime}</span>
</div>
</header>
<div className="prose max-w-none"> {/* Article content */}
{article.content}
</div>
</article>
</div>
)
}The dynamic route generates individual pages for each article using the slug parameter. The generateStaticParams function pre-renders all article pages at build time, while generateMetadata creates SEO-optimized meta tags for each article. Try this: create mock articles and test different URL slugs to see how the routing responds.
API Routes and Newsletter Integration
API routes turn NewsWave into a full-stack application. The newsletter signup demonstrates how to handle form submissions, validate data, and integrate with external services. These routes run on the server and can connect to databases or third-party APIs securely. Newsletter functionality requires both frontend forms and backend processing. The form captures user email addresses with proper validation. The API route processes submissions, handles errors gracefully, and provides feedback to users. API routes in the App Router use the new route.js convention. Each HTTP method becomes an exported function. This approach provides better TypeScript support and clearer separation between different request types.// app/api/newsletter/route.js - Newsletter signup API
import { NextResponse } from 'next/server' // Next.js response utilities
// Handle POST requests to /api/newsletter
export async function POST(request) {
try {
const { email } = await request.json() // Parse request body
// Validate email format
if (!email || !email.includes('@')) {
return NextResponse.json(
{ error: 'Valid email address required' }, // Error message
{ status: 400 } // Bad request status
)
} // Simulate newsletter service integration
console.log(`Newsletter signup: ${email}`) // Log for development
// In production, integrate with email service like:
// await mailchimp.lists.addListMember(listId, { email_address: email })
return NextResponse.json(
{ message: 'Successfully subscribed to newsletter!' }, // Success message
{ status: 200 } // Success status
)
} catch (error) {
console.error('Newsletter signup error:', error) // Log error
return NextResponse.json(
{ error: 'Failed to process subscription' }, // Generic error message
{ status: 500 } // Server error status
)
}
}// components/NewsletterForm.js - Frontend form component
'use client' // Enable client-side features
import { useState } from 'react' // React state hook
export default function NewsletterForm() {
const [email, setEmail] = useState('') // Email input state
const [status, setStatus] = useState('idle') // Form submission status
const [message, setMessage] = useState('') // Feedback message
const handleSubmit = async (e) => {
e.preventDefault() // Prevent default form submission
setStatus('loading') // Show loading state try {
const response = await fetch('/api/newsletter', { // Call API route
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }) // Send email data
})
const data = await response.json() // Parse response
if (response.ok) {
setStatus('success') // Success state
setMessage(data.message) // Show success message
setEmail('') // Clear form
} else {
setStatus('error') // Error state
setMessage(data.error) // Show error message
}
} catch (error) {
setStatus('error') // Network error state
setMessage('Network error occurred') // Generic error
}
}Testing and Development Workflow
Testing NewsWave ensures features work correctly before deployment. The development workflow includes running local servers, testing API endpoints, and validating responsive design. Proper testing prevents bugs from reaching production users. The Next.js development server provides hot reloading and error reporting. Changes appear instantly in the browser without manual refresh. This feedback loop accelerates development and makes debugging easier. Testing covers different aspects — component rendering, API functionality, and user interactions. Start with manual testing during development, then add automated tests for critical features. This approach balances speed with reliability.# Start NewsWave development server
npm run dev
# Build production version for testing
npm run build- Homepage loads with featured articles
- Navigation links work correctly
- Article pages render with proper metadata
- Newsletter form submits successfully
- Responsive design works on mobile
- Build process completes without errors
Quiz
1. What is the purpose of the components/ directory in the NewsWave project structure?
2. Which function is used to pre-render dynamic article pages at build time in Next.js App Router?
3. What file naming convention does the App Router use for API routes?
Up Next: Deployment with Vercel
Take your completed NewsWave application live with Vercel's seamless deployment platform and production optimizations.