In short
A blog API adds what the todo app doesn't have: users, ownership, relationships and public versus private data. It feels much closer to a real product backend.
A backend for a blog — posts, comments, and categories — practice for relational data modeling and nested resource routes.

Think of it like this
The college notice board
Anyone can read the notice board. Only the person who pinned a notice can take it down, and students leave comment slips under popular ones. A blog API works the same: public reading, owner-only editing, comments attached to posts.
Watch it happen
Build plan
1/5Set up routes/posts.js and routes/comments.js with express.Router and an error handler.
The big ideas
What you need to know
Readable URLs with slugs
/posts/my-first-api reads better than /posts/8213. Make slugs unique and generate them from titles.
Ownership checks
401 means 'who are you?'. 403 means 'I know you, but this isn't yours'. Use both correctly.
Public vs draft
Drafts are visible only to their author. The public list shows only published: true posts.
Related resources
Comments belong to a post. Deleting a post should also handle its comments.
See it in code
Walk through the code
1function requireOwner(req, res, next) {2 const post = posts.find((p) => p.slug === req.params.slug);3 if (!post) return res.status(404).json({ error: "Post not found" });4 if (post.authorId !== req.user.id) {5 return res.status(403).json({ error: "You can only edit your own posts" });6 }7 req.post = post;8 next();9}10 11postsRouter.patch("/:slug", requireAuth, requireOwner, (req, res) => {12 const { title, body, published } = req.body;13 Object.assign(req.post, { title, body, published, updatedAt: new Date() });14 res.json(req.post);15});1/4Load the post by slug, or 404 if it doesn't exist.
In a real project, validate the body first so undefined fields don't overwrite real values. This snippet keeps the focus on ownership.
Save yourself the pain
Common mistakes
Oops
Checking only that the user is logged in before letting them edit any post.
Do this instead
Also check post.authorId matches req.user.id. Logged in is not the same as allowed.
Oops
Returning drafts in the public posts list.
Do this instead
Filter by published: true for public lists, and show drafts only to their author.
Your mission
Milestone 1: posts with owners
Quick check
A logged-in user tries to delete someone else's post. Which status is right?
Go deeper
- 1Model the relationship between posts, comments and authors properly.
- 2Build nested routes, e.g. `/posts/:id/comments`, for related resources.
- 3Add pagination for the posts listing endpoint.
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.