Next.js Lesson 37 – Final Project | Dataplexa
LESSON 37

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.
📁 NewsWave Project Structure
📁 newswave/
📁 app/
📄 layout.js
📄 page.js
📄 globals.css
📁 articles/
📄 [slug]/page.js
📁 category/
📄 [name]/page.js
📁 search/
📄 page.js
📁 api/
📁 articles/
📄 route.js
📁 newsletter/
📄 route.js
📁 components/
📄 Header.js
📄 ArticleCard.js
📄 NewsletterForm.js
📁 lib/
📄 articles.js
📄 utils.js
📁 public/
📄 logo.png
📄 favicon.ico

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
Terminal
$ npx create-next-app@latest newswave --typescript --tailwind --eslint --app
Creating a new Next.js app in ./newswave
Installing dependencies...
✓ Created NewsWave project successfully
# Install additional dependencies for NewsWave
npm install date-fns clsx lucide-react

# Install development dependencies
npm install -D @types/node
Terminal
$ npm install date-fns clsx lucide-react
added 8 packages, and audited 234 packages in 3s
✓ Dependencies installed successfully
What just happened?

The 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>
  )
}
localhost:3000 — NewsWave

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>
  )
}
localhost:3000 — NewsWave

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>
  )
}
localhost:3000 — NewsWave

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>
  )
}
localhost:3000/articles/nextjs-14-release — NewsWave
What just happened?

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
    )
  }
}
Terminal
$ curl -X POST http://localhost:3000/api/newsletter -d '{"email":"user@example.com"}'
{"message":"Successfully subscribed to newsletter!"}
✓ API route working correctly
// 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
    }
  }
localhost:3000 — NewsWave Newsletter

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
Terminal
$ npm run dev
▲ Next.js 14.0.0
- Local: http://localhost:3000
- ready in 2.3s
✓ NewsWave development server running
Development Checklist
  • 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.