On day 54, my goal was to create a basic blog app using Next.js, applying the concepts I had learned so far. I focused on the fundamentals of Next.js, including how it operates, the differences between server and client components, the Link component, and App Router routing. This blog app served as a practical way to integrate all these concepts into a single real project, rather than working through isolated examples.
What I Built
A simple blog app using Next.js App Router. It has a home page that lists all posts, a dedicated blog section for reading individual posts, and separate pages for About and Contact, all wrapped in a shared Header and Footer layout.
🛠️ Concepts Used
- Next.js App Router & file-based routing
- Root layout with shared Header & Footer
- Server-side vs client-side components
-
Linkcomponent for navigation - Dynamic routing with
[slug]
Folder Structure
app/
├── layout.jsx --> Root layout (with Header and Footer)
├── page.jsx --> Home page — lists all posts
├── about/
│ └── page.jsx --> About me page
├── contact/
│ └── page.jsx --> Contact page
├── blog/
│ ├── page.jsx --> All posts listing
│ └── [slug]/
│ ├── not-found.jsx
│ └── page.jsx --> Individual post (dynamic route)
│
├── data/
│ └── posts.js --> Post data
│
│
├── components/
│ ├── Header.jsx --> Header component
│ └── Footer.jsx --> Footer component
The root layout.jsx wraps the entire app with a shared Header and Footer from the components/ directory. The home page (app/page.jsx) lists all posts, while dedicated routes exist for /about and /contact. The /blog route has its own listing page, and dynamic post pages are handled via the [slug] segment, where each post is rendered based on its URL slug, with a not-found.jsx as a fallback for invalid slugs.
The Interesting Part: [slug] Dynamic Routing
The thing that actually made sense to me through building this was how Next.js handles dynamic routes. Instead of creating a separate page file for every blog post, you create a single folder named [slug] and Next.js does the rest.
blog/
└── [slug]/
├── page.jsx --> renders the individual post
└── not-found.jsx --> handles invalid slugs
Define all the posts inside the posts.js file and import it in page.jsx file. Inside page.jsx, you get the slug from params and use it to fetch or find the right post:
export default function BlogPost({ params }) {
const { slug } = params;
// use slug to find and display the correct post
}
And if someone visits a slug that doesn't exist, not-found.jsx kicks in automatically. Clean and simple.
What I Struggled With
Understanding when the not-found.jsx file gets triggered took me some time. I initially thought I needed to handle redirects manually, but Next.js takes care of it for you as long as the file is correctly placed within the [slug] folder.
Link
Final Thoughts
Building this blog app was a solid checkpoint in my 100 Days of Code journey. It's one thing to understand routing or layouts in theory, but actually wiring them together into a real project makes everything stick differently.
Thanks for reading. Feel free to share your thoughts!
Top comments (0)