Build a Node.js Interactive Web-Based Note-Taking App

Written by

in

In the digital age, we’re constantly bombarded with information. From fleeting thoughts to crucial project details, the need to capture and organize this data is paramount. Traditional methods like pen and paper, while reliable, can quickly become disorganized and difficult to search. This is where a digital note-taking application shines. In this tutorial, we’ll build a web-based note-taking application using Node.js, providing a practical and engaging project for both beginners and intermediate developers to hone their skills. We’ll explore fundamental concepts, best practices, and address common pitfalls, all while creating a functional and useful application.

Why Build a Note-Taking App?

Building a note-taking app offers several advantages. Firstly, it’s a relatively straightforward project, making it ideal for learning the basics of Node.js, Express.js (a popular web framework), and front-end technologies like HTML, CSS, and JavaScript. Secondly, it allows you to practice key programming concepts such as routing, handling user input, working with databases (we’ll use a simple file-based approach for this tutorial), and front-end interaction. Finally, a note-taking app is a genuinely useful tool that you can customize and extend to fit your specific needs, whether for personal use or for managing project information.

Prerequisites

Before we dive in, ensure you have the following installed on your system:

  • Node.js and npm (Node Package Manager): You can download these from the official Node.js website (nodejs.org).
  • A code editor: Visual Studio Code, Sublime Text, or any editor of your choice.

Project Setup

Let’s begin by setting up our project directory and installing the necessary dependencies. Open your terminal or command prompt and execute the following commands:

  1. Create a new project directory: mkdir node-note-app
  2. Navigate into the directory: cd node-note-app
  3. Initialize a Node.js project: npm init -y (This creates a package.json file with default settings.)
  4. Install Express.js: npm install express
  5. Install a templating engine (we’ll use EJS): npm install ejs

Your project structure should now look something like this:

node-note-app/
├── node_modules/
├── package.json
└── package-lock.json

Creating the Server (app.js)

Now, let’s create our main server file, which we’ll name app.js. This file will handle all the server-side logic, including routing and request handling. Create a new file named app.js in your project directory and add the following code:

// app.js
const express = require('express');
const fs = require('fs');
const path = require('path');

const app = express();
const port = 3000;

app.set('view engine', 'ejs'); // Set EJS as the view engine
app.use(express.urlencoded({ extended: true })); // Middleware to parse URL-encoded bodies
app.use(express.static('public')); // Serve static files from the 'public' directory

// --- Data Storage (Simple File-Based) ---
const dataFilePath = path.join(__dirname, 'notes.json');

// Function to read notes from the file
function readNotes() {
 try {
 const data = fs.readFileSync(dataFilePath, 'utf8');
 return JSON.parse(data) || [];
 } catch (error) {
 // If the file doesn't exist or there's an error, return an empty array
 return [];
 }
}

// Function to write notes to the file
function writeNotes(notes) {
 fs.writeFileSync(dataFilePath, JSON.stringify(notes, null, 2), 'utf8');
}

// --- Routes ---

// Home page (display notes)
app.get('/', (req, res) => {
 const notes = readNotes();
 res.render('index', { notes }); // Render the 'index' view with the notes
});

// Add a new note (display the form)
app.get('/add', (req, res) => {
 res.render('add'); // Render the 'add' view
});

// Handle the form submission to add a note
app.post('/add', (req, res) => {
 const { title, content } = req.body;
 const notes = readNotes();
 notes.push({ id: Date.now(), title, content }); // Generate a unique ID
 writeNotes(notes);
 res.redirect('/'); // Redirect back to the home page
});

// Delete a note
app.get('/delete/:id', (req, res) => {
 const noteId = parseInt(req.params.id, 10); // Convert ID to integer
 let notes = readNotes();
 notes = notes.filter(note => note.id !== noteId);
 writeNotes(notes);
 res.redirect('/');
});

// Start the server
app.listen(port, () => {
 console.log(`Server listening at http://localhost:${port}`);
});

Let’s break down this code:

  • Importing Modules: We import the necessary modules: express (for the web framework), fs (for file system operations), and path (for working with file paths).
  • Creating the App and Setting the Port: We create an Express application instance (app) and set the port number to 3000.
  • Setting up the View Engine: app.set('view engine', 'ejs'); configures EJS as our templating engine. This allows us to use HTML files with dynamic content.
  • Middleware:
    • express.urlencoded({ extended: true }): This middleware is crucial for parsing data submitted through HTML forms. It makes the form data available in the req.body object.
    • express.static('public'): This middleware serves static files like CSS, JavaScript, and images from a directory named ‘public’.
  • Data Storage (File-Based): We’re using a simple file-based approach to store our notes.
    • dataFilePath: Defines the path to our notes.json file.
    • readNotes(): Reads notes from the notes.json file and parses the JSON data. If the file doesn’t exist, it returns an empty array.
    • writeNotes(): Writes notes to the notes.json file, formatting the JSON for readability.
  • Routes: We define the routes for our application:
    • GET /: Renders the home page (index.ejs) and displays the notes.
    • GET /add: Renders the add note form (add.ejs).
    • POST /add: Handles the form submission for adding a new note. It reads the form data, creates a new note object, adds it to the notes array, and writes the updated array back to the file. It then redirects the user back to the home page.
    • GET /delete/:id: Handles deleting a note. It extracts the note ID from the URL, filters the notes array to remove the note with the matching ID, and writes the updated array back to the file. It then redirects the user back to the home page.
  • Starting the Server: app.listen(port, () => { ... }); starts the server and listens for incoming requests on the specified port.

Creating the Views (EJS Templates)

Next, we’ll create the EJS templates for our views. These templates will contain the HTML structure and display the dynamic content. Create a directory named views in your project directory. Inside the views directory, create two files: index.ejs and add.ejs.

index.ejs

This template will display the list of notes and provide a link to add new notes. Here’s the code:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Node.js Note-Taking App</title>
 <link rel="stylesheet" href="/style.css"> <!-- Link to your stylesheet -->
</head>
<body>
 <h1>My Notes</h1>
 <a href="/add">Add New Note</a>
 <ul>
  <% notes.forEach(note => { %>
  <li>
   <h3><%= note.title %></h3>
   <p><%= note.content %></p>
   <a href="/delete/<%= note.id %>" onclick="return confirm('Are you sure you want to delete this note?')">Delete</a>
  </li>
  <% }); %>
 </ul>
</body>
</html>

Key points in index.ejs:

  • HTML Structure: Standard HTML structure with a title and heading.
  • Link to Add Note: A link to the /add route, which will display the add note form.
  • Iterating Through Notes: <% notes.forEach(note => { %> ... <% }); %> loops through the notes array (passed from the server) and displays each note.
  • Displaying Note Content: <%= note.title %> and <%= note.content %> display the title and content of each note.
  • Delete Link: Each note has a delete link that calls the /delete/:id route. The onclick="return confirm(...)" adds a confirmation dialog before deleting.
  • Linking CSS: <link rel="stylesheet" href="/style.css"> links to a stylesheet (which we’ll create later).

add.ejs

This template will display the form for adding a new note. Here’s the code:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Add New Note</title>
 <link rel="stylesheet" href="/style.css"> <!-- Link to your stylesheet -->
</head>
<body>
 <h1>Add New Note</h1>
 <form action="/add" method="POST">
  <label for="title">Title:</label><br>
  <input type="text" id="title" name="title" required><br><br>
  <label for="content">Content:</label><br>
  <textarea id="content" name="content" rows="4" cols="50" required></textarea><br><br>
  <input type="submit" value="Submit">
 </form>
 <a href="/">Back to Notes</a>
</body>
</html>

Key points in add.ejs:

  • HTML Structure: Standard HTML structure.
  • Form: A form with action="/add" (the route to handle form submission) and method="POST".
  • Input Fields: Input fields for the note title and content. The required attribute ensures that the user must fill in these fields.
  • Submit Button: A submit button to send the form data.
  • Back Link: A link to return to the home page (/).

Creating the Stylesheet (style.css)

Create a directory named public in your project directory. Inside the public directory, create a file named style.css. This file will contain the CSS styles for your application. Here’s some basic CSS to get you started:

/* style.css */
body {
 font-family: sans-serif;
 margin: 20px;
}

h1 {
 color: #333;
}

ul {
 list-style: none;
 padding: 0;
}

li {
 border: 1px solid #ccc;
 margin-bottom: 10px;
 padding: 10px;
}

a {
 text-decoration: none;
 color: blue;
}

Feel free to customize the CSS to your liking. The key is to ensure the <link rel="stylesheet" href="/style.css"> tag in your HTML templates correctly references the stylesheet.

Running the Application

Now that we’ve set up the server, views, and stylesheet, it’s time to run the application. Open your terminal or command prompt, navigate to your project directory (node-note-app), and run the following command:

node app.js

This will start the Node.js server. You should see the following message in your console:

Server listening at http://localhost:3000

Open your web browser and navigate to http://localhost:3000. You should see your note-taking application running! You can now add, view, and delete notes.

Common Mistakes and Troubleshooting

Here are some common mistakes and how to fix them:

  • Incorrect File Paths: Double-check that your file paths (e.g., in app.js and the HTML templates) are correct. Make sure the directories (views and public) are in the right place.
  • Missing Dependencies: Ensure you’ve installed all the required dependencies using npm install. If you’re missing a dependency, you’ll get an error message in the console.
  • Form Data Not Being Parsed: If your form data isn’t being parsed correctly, make sure you’ve included the express.urlencoded({ extended: true }) middleware in app.js.
  • EJS Syntax Errors: EJS templates can be sensitive to syntax errors. Carefully review your EJS code for any typos or incorrect syntax (e.g., missing closing tags or incorrect use of <%= ... %>).
  • Server Not Restarting: When you make changes to your app.js file, you’ll need to restart the server for the changes to take effect. Consider using a tool like nodemon (npm install -g nodemon) to automatically restart the server whenever you save changes. You would then run the server using nodemon app.js.
  • CORS Errors: If you are trying to access your application from a different domain, you might encounter CORS (Cross-Origin Resource Sharing) errors. This is less likely in this basic example, but if you do, you’ll need to configure CORS in your Express app.

Enhancements and Next Steps

This is a basic note-taking application. Here are some ideas for enhancements and next steps:

  • Database Integration: Instead of using a file-based approach, integrate a database like MongoDB or PostgreSQL for more robust data storage and management.
  • User Authentication: Implement user authentication so that users can create accounts and securely store their notes.
  • Note Organization: Add features to organize notes, such as tags, categories, or notebooks.
  • Rich Text Editor: Integrate a rich text editor (e.g., TinyMCE, Quill) to allow users to format their notes with bold, italics, and other rich text features.
  • Search Functionality: Implement a search feature to easily find notes based on keywords.
  • Mobile Responsiveness: Make the application responsive so that it looks good on different devices (desktops, tablets, and phones).
  • Deployment: Deploy your application to a platform like Heroku or Netlify so that it can be accessed online.

Summary / Key Takeaways

We’ve successfully built a functional note-taking application using Node.js, Express.js, and EJS. This project provided a hands-on experience in setting up a Node.js server, handling routes, creating views with a templating engine, and managing user input. By working through this tutorial, you’ve gained practical experience with fundamental web development concepts. The application is a starting point, and you can now expand upon it to create a more sophisticated and feature-rich note-taking tool tailored to your needs. Remember to practice regularly, experiment with different features, and embrace the learning process. The ability to build web applications with Node.js opens up a world of possibilities, and this project is a solid foundation for your future endeavors.

FAQ

  1. What is Node.js? Node.js is a JavaScript runtime environment that allows you to execute JavaScript code outside of a web browser. It’s built on Chrome’s V8 JavaScript engine and is widely used for building server-side applications.
  2. What is Express.js? Express.js is a fast, unopinionated, minimalist web framework for Node.js. It provides a robust set of features for building web applications and APIs, simplifying the process of handling routes, middleware, and request/response cycles.
  3. What is EJS? EJS (Embedded JavaScript) is a simple templating language that allows you to generate HTML markup with embedded JavaScript. It’s commonly used to separate the presentation logic from the application logic.
  4. How do I install dependencies? You install dependencies using npm (Node Package Manager). For example, to install Express.js, you would run npm install express in your project directory.
  5. What are routes? In web development, routes define how an application responds to a specific request made to a specific endpoint (URL) with a specific method (e.g., GET, POST). They map URLs to specific functions or actions within the application.

The journey of building web applications is a continuous learning process. Each project, no matter how small, offers opportunities to expand your knowledge and refine your skills. Embrace the challenges, celebrate the successes, and always strive to learn and improve. With each line of code you write and each problem you solve, you’re building not just applications, but also your expertise.