Module F-8·28 min read

Building a content site end-to-end — layouts, dynamic routes, data fetching, generateMetadata for SEO, static vs dynamic rendering decisions, and what silently breaks when you deploy outside Vercel.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

F-8 — Your First Real Next.js Application

Who this is for: Developers who have completed F-1 through F-7 and want to see everything connect in a complete, working application before moving into the Practitioner phase. This is a build module — we're constructing a content site end-to-end, making real decisions along the way, and deploying it. No toy examples; a real architecture you'd actually ship.


What We're Building

A content site for a technical blog — the kind of thing you'd build for a personal site, a company engineering blog, or a documentation hub. It has:

  • A homepage with recent posts
  • A blog index page with category filtering
  • Individual blog post pages
  • An RSS feed endpoint
  • Full SEO metadata including Open Graph images
  • Static generation for published posts
  • Incremental static regeneration for the post listing

This covers the full Foundation toolkit: Server Components, file-system routing, dynamic params, data fetching, built-in components, the metadata API, a Route Handler, and deployment. After building this, you have a real reference architecture to adapt.


Project Setup

bash

The project structure we'll work toward:

text

The Data Layer

For this example we'll use a file-system based data layer — posts as Markdown files — which is a common real-world pattern for personal blogs and documentation sites.

ts
ts

Install gray-matter for Markdown frontmatter parsing:

bash

The Root Layout

The root layout sets up global font, navigation, and HTML structure:

tsx

metadataBase tells Next.js the base URL for resolving relative URLs in Open Graph images and other metadata. Set it to your production domain. In development it defaults to localhost:3000.


The Homepage

tsx

This page is statically generated — it fetches data at build time and produces a static HTML file. Because getAllPosts reads from the filesystem with no external dependencies, it runs at build time and the output never changes until you redeploy.


The Blog Index — With Category Filtering

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.