Turning Learners Into Developers
Codekilla
CODEKILLA
// projects.express

10 Best Express JS Projects

Hand-picked and ordered easiest → hardest — each with complete code and expected output. Build these to turn lessons into a portfolio.

Back to Express JS course
// solution.code
express
// RESTful Blog API with CRUD Operations
const express = require('express');
const app = express();

// Middleware to parse JSON
app.use(express.json());

// In-memory data store
let posts = [
  { id: 1, title: 'First Post', content: 'Hello World', author: 'John' },
  { id: 2, title: 'Second Post', content: 'Learning Express', author: 'Jane' }
];
let nextId = 3;

// GET all posts
app.get('/api/posts', (req, res) => {
  res.json({ success: true, data: posts });
});

// GET single post by ID
app.get('/api/posts/:id', (req, res) => {
  const post = posts.find(p => p.id === parseInt(req.params.id));
  if (!post) return res.status(404).json({ success: false, message: 'Post not found' });
  res.json({ success: true, data: post });
});

// CREATE new post
app.post('/api/posts', (req, res) => {
  const { title, content, author } = req.body;
  if (!title || !content) {
    return res.status(400).json({ success: false, message: 'Title and content required' });
  }
  const newPost = { id: nextId++, title, content, author: author || 'Anonymous' };
  posts.push(newPost);
  res.status(201).json({ success: true, data: newPost });
});

// UPDATE post
app.put('/api/posts/:id', (req, res) => {
  const post = posts.find(p => p.id === parseInt(req.params.id));
  if (!post) return res.status(404).json({ success: false, message: 'Post not found' });
  
  const { title, content, author } = req.body;
  if (title) post.title = title;
  if (content) post.content = content;
  if (author) post.author = author;
  
  res.json({ success: true, data: post });
});

// DELETE post
app.delete('/api/posts/:id', (req, res) => {
  const index = posts.findIndex(p => p.id === parseInt(req.params.id));
  if (index === -1) return res.status(404).json({ success: false, message: 'Post not found' });
  
  const deleted = posts.splice(index, 1);
  res.json({ success: true, message: 'Post deleted', data: deleted[0] });
});

// Start server
const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Blog API running on http://localhost:${PORT}`);
  console.log('Available endpoints:');
  console.log('  GET    /api/posts');
  console.log('  GET    /api/posts/:id');
  console.log('  POST   /api/posts');
  console.log('  PUT    /api/posts/:id');
  console.log('  DELETE /api/posts/:id');
});
output
Blog API running on http://localhost:3000
Available endpoints:
  GET    /api/posts
  GET    /api/posts/:id
  POST   /api/posts
  PUT    /api/posts/:id
  DELETE /api/posts/:id

Testing with curl would show: GET /api/posts returns all posts in JSON format, POST creates new posts, PUT updates existing posts, and DELETE removes posts with appropriate HTTP status codes.