How to Build a Command-Line (CLI) To-Do List with Node.js

Posted Date: 2025-10-31

This tutorial is different from the others. HTML, CSS, JavaScript, and React are frontend technologies; they run in the user's browser to create a visual interface (UI). Node.js is a backend runtime. It runs JavaScript on a server or in your terminal, not in the browser. It cannot create visual websites by itself.

Therefore, a "to-do list only with Node.js" is a Command-Line Interface (CLI) application. You will run it from your terminal. This is the foundation of all backend development: managing data, files, and logic. We will use the built-in fs (File System) module to save your tasks in a JSON file.

The Full Node.js Code (Save as 'app.js')

This single file is your entire application. You will also need an empty tasks.json file in the same directory (just create a file with tasks.json in it).


const fs = require('fs');
const path = require('path');

const tasksFilePath = path.join(__dirname, 'tasks.json');

// Helper function to load tasks from tasks.json
function loadTasks() {
  try {
    const data = fs.readFileSync(tasksFilePath, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    // If file doesn't exist or is empty, return empty array
    return [];
  }
}

// Helper function to save tasks to tasks.json
function saveTasks(tasks) {
  fs.writeFileSync(tasksFilePath, JSON.stringify(tasks, null, 2));
}

// Get command-line arguments
const [,, command, ...args] = process.argv;
const taskText = args.join(' ');

// Load tasks
let tasks = loadTasks();

switch (command) {
  case 'add':
    const newTask = { text: taskText, completed: false };
    tasks.push(newTask);
    saveTasks(tasks);
    console.log(`Task added: "${taskText}"`);
    break;

  case 'list':
    console.log('Your To-Do List:');
    if (tasks.length === 0) {
      console.log('No tasks found. Add one with: node app.js add "My task"');
    }
    tasks.forEach((task, index) => {
      const status = task.completed ? '[x]' : '[ ]';
      console.log(`${index}. ${status} ${task.text}`);
    });
    break;

  case 'complete':
    const completeIndex = parseInt(taskText, 10);
    if (!isNaN(completeIndex) && tasks[completeIndex]) {
      tasks[completeIndex].completed = true;
      saveTasks(tasks);
      console.log(`Task ${completeIndex} marked as complete.`);
    } else {
      console.log('Invalid task number.');
    }
    break;

  case 'delete':
    const deleteIndex = parseInt(taskText, 10);
    if (!isNaN(deleteIndex) && tasks[deleteIndex]) {
      const deletedTask = tasks.splice(deleteIndex, 1);
      saveTasks(tasks);
      console.log(`Deleted task: "${deletedTask[0].text}"`);
    } else {
      console.log('Invalid task number.');
    }
    break;

  default:
    console.log('--- Node.js To-Do List ---');
    console.log('Usage:');
    console.log('  node app.js list');
    console.log('  node app.js add "Your new task"');
    console.log('  node app.js complete ');
    console.log('  node app.js delete ');
}

  

How to Use Your CLI To-Do List

Open your terminal in the same directory as app.js and tasks.json. Run the following commands:


# See all tasks
$ node app.js list
Your To-Do List:
No tasks found. Add one with: node app.js add "My task"

# Add a new task
$ node app.js add "Learn Node.js fs module"
Task added: "Learn Node.js fs module"

# Add another task
$ node app.js add "Build a CLI app"
Task added: "Build a CLI app"

# List all tasks
$ node app.js list
Your To-Do List:
0. [ ] Learn Node.js fs module
1. [ ] Build a CLI app

# Complete a task
$ node app.js complete 0
Task 0 marked as complete.

# List tasks again
$ node app.js list
Your To-Do List:
0. [x] Learn Node.js fs module
1. [ ] Build a CLI app

# Delete a task
$ node app.js delete 1
Deleted task: "Build a CLI app"

  

Code Breakdown

1. Importing Modules ('fs' and 'path')

We use require('fs') to get the built-in File System module, which lets us read and write files. require('path') helps build file paths that work on any operating system (Windows, macOS, Linux).

2. Reading Command-Line Arguments ('process.argv')

process.argv is an array containing all the command-line arguments.
When you run node app.js add "My task":
- process.argv[0] is "node"
- process.argv[1] is "app.js"
- process.argv[2] is "add" (our command)
- process.argv[3] is "My task" (our args)

3. Persisting Data ('fs.readFileSync' and 'fs.writeFileSync')

This is our "database." loadTasks reads the tasks.json file, parses the JSON text into a JavaScript array, and returns it. saveTasks does the opposite: it takes the JavaScript array, turns it into a formatted JSON string (JSON.stringify), and writes it back to the file, overwriting the old one.

Bringing it Local: Node.js for Madrid's Backend

What you've just built is a simple "server-side" application. This is the heart of backend development. In Madrid, Node.js is a dominant technology for building the APIs and microservices that power the React frontends of major companies. The React app (client) calls a Node.js API (server) to get and save data. This is the full-stack connection.

This SEO-focused section links the tutorial (Node.js) to high-value local career paths ("Node.js jobs Madrid," "backend developer Madrid").

Top Backend/Node.js Communities in Madrid

To move from a simple script to building robust APIs, connecting with the local backend community is key.

Community Name Focus Area Why It's Worth Joining
Node.js Madrid Backend JavaScript, APIs, Performance The official, premier community for all things Node.js in Madrid. Essential for backend developers.
MadridJS General JavaScript, Full-Stack Covers both frontend and backend JavaScript, making it great for understanding the full picture, from React to Node.js.

Madrid Tech Companies Building APIs with Node.js

The same companies known for React frontends rely on Node.js for their fast, scalable backends.

Company Name Relevance to Node.js
Cabify A pioneer in using Node.js for its microservices architecture, handling millions of requests for its ride-hailing platform.
Idealista Uses Node.js to build and maintain the high-performance APIs that feed data to its React-based web applications.
Telefonica Tech Employs Node.js extensively in its digital transformation projects for building modern, scalable backend services.

SEO Strategy for This Tutorial

  • Primary Keywords: "node.js cli tutorial," "node.js todo list," "node.js fs module," "node.js read write file," "process.argv tutorial."
  • Secondary/Long-Tail Keywords: "build cli app with node.js," "node.js save data to json," "backend developer madrid," "node.js jobs madrid."
  • User Intent: Targets beginners in backend development. It clarifies the "Node.js only" misconception and provides a practical, real-world example of what Node.js is used for (scripts, file manipulation, CLIs).

Conclusion: You're Now a Backend Developer

You have successfully used JavaScript on both the client (with React) and the server (with Node.js). You've learned how to read from and write to the file system, process terminal commands, and manage data outside of a browser.

The next logical step is to combine them: build a Node.js API (using a framework like Express.js) that your React app can fetch data from. This is the essence of a full-stack application.