Turning Learners Into Developers
Codekilla
CODEKILLA
// projects.nodejs

10 Best Node 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 Node JS course
// solution.code
node.js
// REST API with Express and File Storage
// A task management API using JSON file persistence

const express = require('express');
const fs = require('fs').promises;
const path = require('path');

const app = express();
const PORT = 3000;
const DATA_FILE = path.join(__dirname, 'tasks.json');

// Middleware
app.use(express.json());

// Initialize data file if it doesn't exist
const initDataFile = async () => {
  try {
    await fs.access(DATA_FILE);
  } catch {
    await fs.writeFile(DATA_FILE, JSON.stringify([]));
  }
};

// Helper to read tasks
const readTasks = async () => {
  const data = await fs.readFile(DATA_FILE, 'utf8');
  return JSON.parse(data);
};

// Helper to write tasks
const writeTasks = async (tasks) => {
  await fs.writeFile(DATA_FILE, JSON.stringify(tasks, null, 2));
};

// GET all tasks
app.get('/api/tasks', async (req, res) => {
  try {
    const tasks = await readTasks();
    res.json(tasks);
  } catch (error) {
    res.status(500).json({ error: 'Failed to read tasks' });
  }
});

// POST create task
app.post('/api/tasks', async (req, res) => {
  try {
    const tasks = await readTasks();
    const newTask = {
      id: Date.now().toString(),
      title: req.body.title,
      completed: false,
      createdAt: new Date().toISOString()
    };
    tasks.push(newTask);
    await writeTasks(tasks);
    res.status(201).json(newTask);
  } catch (error) {
    res.status(500).json({ error: 'Failed to create task' });
  }
});

// PUT update task
app.put('/api/tasks/:id', async (req, res) => {
  try {
    const tasks = await readTasks();
    const index = tasks.findIndex(t => t.id === req.params.id);
    if (index === -1) return res.status(404).json({ error: 'Task not found' });
    tasks[index] = { ...tasks[index], ...req.body };
    await writeTasks(tasks);
    res.json(tasks[index]);
  } catch (error) {
    res.status(500).json({ error: 'Failed to update task' });
  }
});

// DELETE task
app.delete('/api/tasks/:id', async (req, res) => {
  try {
    const tasks = await readTasks();
    const filtered = tasks.filter(t => t.id !== req.params.id);
    if (tasks.length === filtered.length) return res.status(404).json({ error: 'Task not found' });
    await writeTasks(filtered);
    res.status(204).send();
  } catch (error) {
    res.status(500).json({ error: 'Failed to delete task' });
  }
});

// Start server
initDataFile().then(() => {
  app.listen(PORT, () => console.log(`Task API running on port ${PORT}`));
});
output
Task API running on port 3000

Test with curl:
$ curl -X POST http://localhost:3000/api/tasks -H "Content-Type: application/json" -d '{"title":"Learn Node.js"}'
{"id":"1704067200000","title":"Learn Node.js","completed":false,"createdAt":"2024-01-01T00:00:00.000Z"}

$ curl http://localhost:3000/api/tasks
[{"id":"1704067200000","title":"Learn Node.js","completed":false,"createdAt":"2024-01-01T00:00:00.000Z"}]