Build a Blog With Next.js: Step-by-Step Project
SkillVeris Team
Engineering Team

You build a blog with Next.js by creating a project with the App Router, storing posts as Markdown files, and rendering them as statically generated pages for speed and SEO.
In this guide, you'll learn:
- Next.js handles routing, static generation, and metadata out of the box, so you focus on content and layout rather than infrastructure.
- Markdown files with front matter give you a simple, version-controlled content source without a database.
- Dynamic routes with generateStaticParams turn each Markdown file into its own pre-rendered page.
- The Metadata API adds per-post titles and descriptions for strong SEO with minimal code.
1How Do You Build a Blog With Next.js?
You build a blog with Next.js by scaffolding a project with the App Router, storing each post as a Markdown file with front matter, reading those files at build time, and rendering them as statically generated pages. The result is a fast, SEO-friendly site with no database and no server to manage.
This project is ideal for beginners because it touches the core Next.js concepts — routing, static generation, dynamic routes, and metadata — in a small, satisfying build you can extend later. By the end you will have a working blog you understand end to end.
2What You Will Build
The finished project is a minimal blog with a home page listing posts and an individual page for each article. Everything is generated statically, which keeps it fast and cheap to host.
- A home page that lists all blog posts with titles and dates.
- A dynamic post page rendered from a Markdown file.
- Markdown content with front matter for title, date, and excerpt.
- Per-post SEO metadata for search engines and social sharing.
- A static build you can deploy to any modern host.
💡Prerequisites
You need Node.js installed and a basic grasp of React and JavaScript. No prior Next.js experience is required — this project introduces its core ideas one at a time.
3Step 1: Create the Project
Next.js ships with a setup command that scaffolds everything you need, including the App Router, which is the modern routing system built on React Server Components. Run the creator and accept the defaults for a TypeScript project with the App Router enabled.
- npx create-next-app@latest my-blog # scaffold a new Next.js app
- cd my-blog # move into the project
- npm run dev # start the dev server at localhost:3000
Understanding the Structure
The App Router uses the app directory, where folders become routes and a page.tsx file renders a page. This convention-based routing means you create pages by creating files, with no separate route configuration to maintain.
4Step 2: Add Markdown Content
Store each post as a Markdown file in a posts directory at the project root. Front matter — a small block of metadata at the top of the file between triple-dashed lines — holds the title, date, and excerpt, keeping content and metadata together.
To read these files you install two small libraries: gray-matter parses the front matter, and a Markdown-to-HTML converter turns the body into rendered content. Because the files live in your repository, your content is version-controlled alongside your code.
- npm install gray-matter # parse front matter from Markdown
- npm install remark remark-html # convert Markdown body to HTML
- posts/hello-world.md # a sample post file
- --- title: Hello World # front matter fields
- date: 2026-01-15 --- # closes the front matter block
5Step 3: Read Posts at Build Time
Create a small helper module that reads the posts directory, parses each file's front matter, and returns the data. Because Next.js runs this on the server at build time, you can use Node's file-system APIs directly.
🔑Server Components by Default
In the App Router, components are server components unless you add 'use client'. That is why you can read the file system directly in a page — it never runs in the browser.
A Posts Helper
Put a lib/posts.ts module in charge of all file access. One function lists every post's metadata for the home page; another loads a single post's content by its slug for the detail page.
import fs from 'fs' # read files at build time
import matter from 'gray-matter' # parse front matter
export function getAllPosts() { /* read and sort posts */ }
export function getPostBySlug(slug) { /* load one post */ }6Step 4: Build the Pages
With the data layer in place, the pages are straightforward. The home page maps over the post list to render links, and a dynamic route renders each individual post.
- app/page.tsx # home page listing all posts
- app/posts/[slug]/page.tsx # dynamic route for each post
- generateStaticParams() # pre-render a page per slug at build time
- params.slug # the current post's slug from the URL
Static Generation With generateStaticParams
Exporting generateStaticParams from the dynamic route tells Next.js which slugs exist, so it pre-renders one static HTML page per post at build time. Static pages load instantly and are trivial to cache on a CDN.
7Step 5: Add SEO Metadata
Next.js includes a Metadata API that generates the right HTML head tags for you. For dynamic pages, export a generateMetadata function that returns a title and description based on the post's front matter.
This gives each post a unique, descriptive title and meta description — the foundation of on-page SEO — with only a few lines of code. Search engines and social platforms read these tags to display your content correctly.
- export async function generateMetadata({ params }) {
- const post = getPostBySlug(params.slug)
- return { title: post.title, description: post.excerpt }
- }
8Best Practices for a Production Blog
A few habits take this from a toy project to something you would genuinely publish.
- Prefer static generation — keep pages statically rendered so they load fast and cache well.
- Optimize images with the next/image component to serve modern formats and correct sizes.
- Set explicit metadata on every page, including canonical URLs, to help search engines.
- Keep content in version control so every change is reviewable and reversible.
- Add a sitemap and RSS feed to help discovery once you have real posts.
9Common Mistakes to Avoid
Beginners tend to trip over the same Next.js pitfalls on their first blog.
- Adding 'use client' to whole pages unnecessarily, losing the benefits of server rendering.
- Trying to read the file system inside a client component, which fails in the browser.
- Forgetting generateStaticParams, so dynamic routes are not pre-rendered.
- Skipping per-post metadata and shipping every page with the same title.
- Hardcoding content in components instead of sourcing it from Markdown files.
⚠️Client vs Server
Reaching for 'use client' too early is the most common Next.js mistake. Only the smallest interactive pieces need it — data fetching and file reading belong in server components.
10Deploy and Extend
Once the blog runs locally, deploying is quick. Push the project to a Git repository and connect it to a host like Vercel, which builds and serves Next.js apps with no server configuration. Every push can trigger a fresh static build.
From here you can extend the project incrementally — add categories and tags, syntax highlighting for code blocks, a search feature, or a comment system. Because the foundation is solid, each addition is a small, self-contained step.
11Key Takeaways
This project teaches the core Next.js workflow through a real, useful build.
- The App Router turns folders and files into routes with server components by default.
- Markdown files with front matter make a simple, version-controlled content source.
- generateStaticParams pre-renders one fast static page per post at build time.
- The Metadata API adds strong per-post SEO with minimal code.
- You can deploy the finished blog to a host like Vercel in minutes.
12Frequently Asked Questions
Q: Do I need a database for a Next.js blog? A: No. Storing posts as Markdown files with front matter is a common, database-free approach that keeps content in version control and works perfectly with static generation. You can always add a database or CMS later if your needs grow.
Q: Should I use the App Router or the Pages Router? A: For new projects, the App Router is the recommended default. It is built on React Server Components, ships less JavaScript to the browser, and offers a cleaner data-fetching model. This project uses the App Router throughout.
Q: How does Next.js make the blog good for SEO? A: Static generation produces fast, fully rendered HTML pages that search engines can crawl easily, and the built-in Metadata API lets you set a unique title, description, and canonical URL per post. Together these cover the on-page SEO fundamentals.
Q: Can I add code syntax highlighting? A: Yes. You can extend the Markdown-to-HTML step with a syntax-highlighting plugin so code blocks render with colors. It is a natural next addition once the core blog is working, and it does not change the overall architecture.
Related Reading
Get The Print Version
Download a PDF of this article for offline reading.
About the Publisher
SkillVeris Team
Engineering Team
Our engineering team documents real build journeys so you can learn by doing, not just reading.
View all postsRelated Posts
Never miss an update
Get the latest tutorials and guides delivered to your inbox.
No spam. Unsubscribe anytime.