In short
A blog is a great first routing project. A list page, a page for each post, maybe some tags, and you'll be using URL params without thinking twice.
A blog frontend with a post list and detail view — practice for React Router, fetching data per route, and rendering rich content.

Think of it like this
The college magazine
The contents page lists every article with a title and a page number. Flip to one and you get the full piece. Your blog's home page is the contents, and each /posts/:slug URL is a page number pointing at one article.
Watch it happen
Matching /posts/react-hooks
1/5The URL is /posts/react-hooks. The router looks for the route that fits best.
The big ideas
What you need to know
List and detail pages
Home shows post cards, and each one links to its own page by slug.
Slugs in the URL
A slug is the readable part of a URL, like /posts/my-first-hackathon, instead of /posts?id=7.
Tags and categories
Filter posts by tag with a URL like /tag/react, so a filtered view can be shared.
Markdown content
Write posts in Markdown and render them with a library like react-markdown.
How it works
Build plan
- 1
Data
A posts array with slug, title, date, tags and body.
- 2
List page
A card for every post, newest first.
- 3
Detail page
A /posts/:slug route that finds the post by its slug.
- 4
404 and tags
A not found message and a page for each tag.
See it in code
Walk through the code
1import { Link, useParams } from "react-router";2import { posts } from "./posts";3 4export function PostPage() {5 const { slug } = useParams();6 const post = posts.find((p) => p.slug === slug);7 8 if (!post) return <p>Post not found. <Link to="/">Back to home</Link></p>;9 return (10 <article>11 <h1>{post.title}</h1>12 <time>{new Date(post.date).toLocaleDateString("en-IN")}</time>13 <p>{post.body}</p>14 </article>15 );16}1/4useParams reads slug from the URL.
useParams reads the slug from /posts/:slug. Always handle the not found case, because anyone can type any URL.
Save yourself the pain
Common mistakes
Oops
Assuming the post always exists and reading post.title straight away.
Do this instead
A wrong URL makes find return undefined and crashes the page. Check first and show a friendly message.
Oops
Keeping the selected tag only in state.
Do this instead
Put it in the URL, like /tag/react or ?tag=react, so refreshing and sharing keep the filter.
Your mission
First milestone: list and detail
Quick check
The URL is /posts/react-hooks and the route is path="/posts/:slug". What does useParams() return?
Go deeper
- 1Use dynamic routes (`/blog/:slug`) to render individual posts.
- 2Fetch post data per route and handle loading/error states.
- 3Render markdown or rich text content safely.
More projects at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.