DEV Community

Cover image for Create APIs for a Blog with NodeJS and Express with JSON file
Sarfaraz Unar
Sarfaraz Unar

Posted on • Updated on

Create APIs for a Blog with NodeJS and Express with JSON file

In the fast-evolving landscape of web development, creating a seamless and dynamic blogging experience is crucial for engaging users and delivering content effectively. One key aspect of achieving this is by developing a powerful Application Programming Interface (API) that serves as the backbone for your blog. In this tutorial, we will dive into the world of Node.js and Express to guide you through the process of building a robust API for your blog.

Why Node.js and Express?

Node.js, known for its event-driven, non-blocking I/O model, is a popular choice for building scalable and high-performance applications. When paired with Express, a minimal and flexible Node.js web application framework, you get a powerful combination that simplifies the process of developing APIs and handling HTTP requests effortlessly.

What to Expect in This Tutorial

In the upcoming sections, we will embark on a step-by-step journey, covering everything from setting up your development environment to implementing crucial API endpoints for your blog. Whether you're a seasoned developer looking to expand your skill set or a newcomer eager to grasp the fundamentals, this tutorial aims to be your comprehensive guide.

Here's a sneak peek into what we'll cover:

  1. Setting Up Your Development Environment: Get started with installing Node.js, initializing your project, and setting up the essential tools for seamless development.

  2. Understanding RESTful API Design: Explore the principles of RESTful architecture and learn how to design clean and scalable APIs that adhere to industry best practices.

  3. Creating Express Routes: Dive into the heart of Express by defining routes for handling various HTTP methods, allowing your API to interact with different parts of your blog.

  4. Using JSON file as Database: We will use JSON file as database we will get and data from file and also we will add data to it on post request.

  5. Implementing CRUD Operations: Learn how to perform Create, Read, Update, and Delete operations on your blog data through well-defined API endpoints.

By the end of this tutorial, you'll have a solid foundation for building APIs with Node.js and Express, empowering you to enhance the functionality and interactivity of your blog. So, without further ado, let's dive into the exciting world of blog API development!

Setting Up Development Environment

First of all let's install NodeJS if you have not installed yet!
Visit Official NodeJS website and download Recommended for most user version of NodeJS Download. And then create a new folder named Blog Backend.
Now Open this folder in VS-Code. Download VS code.
After that press Ctrl + J to open terminal. Before moving further it is recommended to check the path and name of your folder in terminal. If you are seeing your folder's name in terminal then it's OK. Otherwise use cd [directory name] to move your working folder.

Tip: You can use Replit for this project. Just Visit Replit.com create new repl and select NodeJS template and then your environment is ready to use!

Installing Dependencies For our Project

In this project we will use express, bodyparser, fs, jsonfile in this project. Let's install them open terminal and paste this by right-click on terminal.

npm install express body-parser jsonfile fs
Enter fullscreen mode Exit fullscreen mode

Now let them install.

Setting up Project Directory Structure

In this project we will create a simple UI so that you can easily interact with APIs and check them or allow your friends to check your APIs.
After installing your dependencies now type npm init in terminal then enter details about your project like project name, author, version etc.

Setting up folder structure

Let's create a simple UI so that you can interact with APIs visually and can easily share it with your friends.
We will create three folders named db, public, views. In db folder we will put our db.json file which will be used as database and we will put our some html content in views folder and css in public. Now create index.js file in root which is main file for our project and then create db.json file in db folder and paste content like this

[
{"id":1,
"title":"Titanic",
"content":"A timeless love story unfolds against the backdrop of the ill-fated maiden voyage of the Titanic. Tragedy strikes, but love prevails in unexpected ways.",
"category":"romance",
"tags":["love story","Titanic","maiden voyage","tragedy","love prevails","romance"]
},

{"id":2,
"title":"The Great Gatsby",
"content":"Amid the glitz of the roaring '20s, Jay Gatsby pursues the American Dream. But beneath the opulence lies a tale of love, obsession, and shattered illusions.",
"category":"drama",
"tags":["roaring '20s","Jay Gatsby","American Dream","love","obsession","shattered illusions"]
},
// Other Posts
]
Enter fullscreen mode Exit fullscreen mode

This is for sample we will also create endpoint for it.
Now open index.js file and import the packages that we will use in this project and db.json file.

const express = require("express");
const bodyparser = require("body-parser");
const jsonfile = require("jsonfile");
const db = require("./db/db.json");
Enter fullscreen mode Exit fullscreen mode

Let's Code

Now first of all we will add sample express code. First create app variable as express function then port number and after that listen that port.

const app = express();
const port = process.env.PORT || 3000;

//APIs will be here...

app.listen(port, () => {
  console.log(`${port} is running...`);
});
Enter fullscreen mode Exit fullscreen mode

Here we will install another package that will help us to restart server every time when we make any change. For this Open terminal and paste this: npm i nodemon.

Now we can easily start our work!
now type nodemon index.js in terminal to start server. You will see message [PORT] is running....
Congrats You Done It!

Body parser is a specific middleware is provided by the body-parser package, which helps parse the incoming request bodies in middleware before your handlers, making it easier to work with the data contained in the request. Now use it in our app here is how:

app.use(bodyparser.urlencoded({ extended: true }));
Enter fullscreen mode Exit fullscreen mode

just add this line and then our basic work is done!

I have created some pages so that we can interact with APIs visually so first here is index.html file and here is html code add this after head tag.

index.html code

<body>
    <div class="container">
        <h3>Welcome to Blog APIs</h3>
        <p>Here is APIs that is developed for portflio perpose.</p>
          <input id='parameter' onkeyup="setParam()" name="parameter" placeholder="Enter Paremter..."   />
        <div class="btn-section">
            <a href="/postform"><button>Create Post</button></a>
            <a href="/posts"><button>Get Posts</button></a>
            <a href="/updateform"><button>Update Post</button></a>
            <button onclick="openURL('/deletepost')">Delete Post</button>
        </div>
        <div class="btn-section" style="margin-top: -30px;">
            <button onclick="openURL('/posts-c')">Posts By Category</button>
            <button onclick="openURL('/posts-t')">Posts By tags</button>
            <button onclick="openURL('/posts')">Post By ID</button>
            <button onclick="openURL('/posts-title')">Post By Title</button>
        </div>
        <button class="follow" style="margin-left: 280px;">Contact Me</button>
    </div>
</body>
Enter fullscreen mode Exit fullscreen mode

and also create two other files in same views folder named postform.html updateform.html there is forms that we will use to post and update blogs.

postform.html code

<body>
    <div class="container" style="margin-top: 25px; padding: 5px;">
        <h3>Create A Post</h3>
        <p>Here is a sample post creator your created post will be deleted after 10 minutes.</p>
        <form action="/newpost" method="POST">
            <label for="title">Write Post Title</label>
            <input type="text" name="title" id="title" placeholder="Enter Post title here...">
            <label for="post-content">Post Content</label>
            <textarea name="content" id="content" cols="30" rows="10" placeholder="Enter Content Here..."></textarea>
            <label for="category">Category</label>
            <input type="text" id="category" name="category" placeholder="Enter Category">
            <label for="tags">#Tags</label>
            <input type="text" id="tags" name="tags" placeholder="Enter Tags Here">
            <button class="follow" type="submit">Post Now</button>
        </form>
    </div>
</body>


Enter fullscreen mode Exit fullscreen mode

updateform.html code

<body>
    <div class="container" style="margin-top: 25px; padding: 5px;">
        <h3>Update Post</h3>
        <p>Here is a sample post creator your created post will be deleted after 10 minutes.</p>
        <form action="/updatepost" method="POST">
            <label for="ID">ID</label>
            <input type="number" name="id" id="id" placeholder="Enter Post ID here...">
            <label for="title">Write Post Title</label>
            <input type="text" name="title" id="title" placeholder="Enter Post title here...">
            <label for="post-content">Post Content</label>
            <textarea name="content" id="content" cols="30" rows="10" placeholder="Enter Content Here..."></textarea>
            <label for="category">Category</label>
            <input type="text" id="category" name="category" placeholder="Enter Category">
            <label for="tags">#Tags</label>
            <input type="text" id="tags" name="tags" placeholder="Enter Tags Here">
            <button class="follow" type="submit">Update Now</button>
        </form>
    </div>
</body>
  <script>
    let parameter = '';
    function setParam(){
      parameter = document.getElementById('parameter').value;
    }
    function openURL(api){
      window.open(api + "/" + parameter);
    }
  </script>
Enter fullscreen mode Exit fullscreen mode

After that create a style.css file in public folder and add following css:

style.css code

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    background-color: black;
}
.container{
    width: 60vw;
    height: auto;
    margin: 150px auto;
    padding: 30px;
    background-color: rgb(34, 33, 33);
    border: none;
    border-radius: 10px;
    box-shadow: 0px 0px 10px 0px rgb(35, 35, 35);
}
.container h3{
    color: white;
    background-color: transparent;
    text-align: center;
    font-size: 30px;
    font-family: 'Montserrat';
    padding: 20px 0px;
}
.container p{
    color: white;
    text-align: center;
    font-family: 'Montserrat';
    background-color: transparent;
    font-size: 15px;
}
.btn-section{
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: transparent;
    margin: 30px 0px;
}
.btn-section a{
    background-color: transparent;
}
.btn-section button{
    margin: 10px 5px;
    padding: 5px 10px;
    background-color: white;
    color: black;
    font-family: 'Montserrat';
    font-size: 20px;
    font-weight: 500;
    transition: 0.5s;
}
.btn-section button:hover{
    color: rgb(185, 255, 80);
    background-color: black;
    border: 2px solid rgb(185, 255, 80);
    border-radius: 10px;
    transform: translateY(-3px);
    box-shadow: 0px 4px 2px 0px rgb(185, 255, 80);
}
.follow{
    margin: 10px 5px;
    padding: 10px 50px;
    display: flex;
    justify-content: center;
    color: rgb(185, 255, 80);
    background-color: black;
    border: 2px solid rgb(185, 255, 80);
    border-radius: 10px;
    font-family: 'Montserrat';
    font-size: 20px;
    font-weight: 500;
    box-shadow: 0px 4px 2px 0px rgb(185, 255, 80);
    transition: 0.5s;
}
.follow:hover{
    color: black;
    background-color: rgb(185, 255, 80);
}
form{
    width: 60%;
    background-color: transparent;
    margin: 10px auto;
    padding: 10px;
}
form label{
    display: block;
    color: white;
    font-size: 14px;
    font-family: Verdana, Geneva, Tahoma, sans-serif;
    background-color: transparent;
    padding: 5px;
}
form input {
    width: 90%;
    padding: 10px;
    outline: none;
    border: 1px solid white;
    border-radius: 5px;
    color: white;
    font-family: Verdana, Geneva, Tahoma, sans-serif;
}
form input:focus{
    border: 1px solid rgb(185, 255, 80);
}
form textarea{
    width: 90%;
    padding: 10px;
    outline: none;
    border: 1px solid white;
    border-radius: 5px;
    color: white;
    font-family: Verdana, Geneva, Tahoma, sans-serif;
}
form textarea:focus{
    border: 1px solid rgb(185, 255, 80);
}
#parameter{
  width: 60%;
  margin-left: 160px;
  margin-top: 20px;
  padding: 10px;
  outline: none;
  border: 1px solid white;
  border-radius: 5px;
  color: white;
  font-family: Verdana, Geneva, Tahoma, sans-serif;
}
Enter fullscreen mode Exit fullscreen mode

Now let's use these files.
In index.js file first use public folder's content as static

//replace your directory / folder name with process.cwd()

app.use("/public", express.static(process.cwd() + "/public"));

Enter fullscreen mode Exit fullscreen mode

Create First API

Certainly! Let's start with the first API in the given code:

API 1: GET /

Description:

This API serves the main index.html file to the client. It is a simple endpoint that sends the main page of our application to users when they access the root URL.

app.get("/", (req, res) => {
  res.sendFile(process.cwd() + "/views/index.html");
});
Enter fullscreen mode Exit fullscreen mode
  1. Endpoint Path: /

    • This defines the root path, meaning it will respond when users access the main URL.
  2. HTTP Method: GET

    • This API responds to HTTP GET requests.
  3. Handler Function:

    • (req, res) => {...}: This is the callback function that gets executed when a GET request is made to the root path. It uses res.sendFile() to send the index.html file to the client.
  4. File Path:

    • process.cwd() + "/views/index.html": It constructs the absolute path to the index.html file. process.cwd() returns the current working directory, and /views/index.html is the relative path to the HTML file.

API 2: GET all posts

The GET /posts endpoint, is designed to retrieve all posts stored in the database (db.json). When a client makes a GET request to this endpoint, the server responds with a JSON array containing information about each post. The code for this API is as follows:

app.get("/posts", (req, res) => {
  res.json(db);
});
Enter fullscreen mode Exit fullscreen mode

Here's a breakdown of the key components:

  1. Endpoint Path: /posts

    • This path specifies that the API will be triggered when a GET request is made to the "/posts" endpoint.
  2. HTTP Method: GET

    • This API responds to HTTP GET requests.
  3. Handler Function:

    • (req, res) => {...}: This function is executed when a GET request is made to "/posts". It simply sends the entire database (db.json) as a JSON response using res.json(db).

API 3: GET Post By Id

The GET /posts/:id endpoint, is designed to retrieve a specific post based on the provided post ID. When a client makes a GET request to this endpoint with a specific ID parameter, the server searches the database (db.json) for a matching post and responds with the details of that post or a message indicating that no post was found. The code for this API is as follows:

app.get("/posts/:id", (req, res) => {
  let id = req.params.id;
  let post = db.find((post) => post.id == id);
  if (!post) {
    res.json({ Message: "Not Found Any Post Related to Your ID" });
  } else {
    res.json(post);
  }
});
Enter fullscreen mode Exit fullscreen mode

Here's a breakdown of the key components:

  1. Endpoint Path: /posts/:id

    • This path includes a parameter :id, indicating that the API expects a specific post ID to be provided in the URL.
  2. HTTP Method: GET

    • This API responds to HTTP GET requests.
  3. Handler Function:

    • (req, res) => {...}: This function is executed when a GET request is made to "/posts/:id". It retrieves the provided post ID from the URL using req.params.id and then searches the database for a post with a matching ID using db.find(). If a matching post is found, it is sent as a JSON response; otherwise, a message indicating the absence of the post is sent.

API 4: GET all posts by Author

The GET /posts-author/:author endpoint, is designed to retrieve posts written by a specific author. When a client makes a GET request to this endpoint with a specific author parameter, the server searches the database (db.json) for posts authored by the specified author and responds with the details of those posts or a message indicating that no posts were found for that author. The code for this API is as follows:

app.get("/posts-author/:author", (req, res) => {
  let author = req.params.author;
  let posts = db.find((post) => post.author == author);
  if (!posts) {
    res.json({ Message: `No Posts Found Against This Author ${author}` });
  } else {
    res.json(posts);
  }
});
Enter fullscreen mode Exit fullscreen mode

Here's a breakdown of the key components:

  1. Endpoint Path: /posts-author/:author

    • This path includes a parameter :author, indicating that the API expects a specific author name to be provided in the URL.
  2. HTTP Method: GET

    • This API responds to HTTP GET requests.
  3. Handler Function:

    • (req, res) => {...}: This function is executed when a GET request is made to "/posts-author/:author". It retrieves the provided author name from the URL using req.params.author and then searches the database for posts authored by that specific author using db.find(). If posts are found, they are sent as a JSON response; otherwise, a message indicating the absence of posts for that author is sent.

This API is valuable for retrieving a collection of posts written by a particular author, enabling clients to explore content created by a specific contributor.

API 5: Show Blog Post Form
Description:
This API serves the postform.html file, allowing users to access a form for creating new posts. When a client makes a GET request to this endpoint, the server responds by sending the HTML form, enabling users to input details such as title, content, category, and tags for a new post.

How to Create:


app.get("/postform", (req, res) => {
  res.sendFile("views/postform.html", { root: __dirname });
});
Enter fullscreen mode Exit fullscreen mode

Endpoint Path: /postform

This path specifies that the API will be triggered when a GET request is made to the /postform endpoint.
HTTP Method: GET

This API responds to HTTP GET requests.
Handler Function:

(req, res) => {...}: This function is executed when a GET request is made to "/postform". It uses res.sendFile() to send the postform.html file to the client.
File Path:

Certainly! Here is the information about API 6: GET /updateform:

API 6: Show Update Post Form

Description:

This API serves the postupdate.html file, allowing users to access a form for updating existing posts. When a client makes a GET request to this endpoint, the server responds by sending the HTML form, which likely contains input fields for modifying the title, content, category, and tags of an existing post.

How to Create:

app.get("/updateform", (req, res) => {
  res.sendFile("views/postupdate.html", { root: __dirname });
});
Enter fullscreen mode Exit fullscreen mode
  1. Endpoint Path: /updateform

    • This path specifies that the API will be triggered when a GET request is made to the "/updateform" endpoint.
  2. HTTP Method: GET

    • This API responds to HTTP GET requests.
  3. Handler Function:

    • (req, res) => {...}: This function is executed when a GET request is made to "/updateform". It uses res.sendFile() to send the postupdate.html file to the client.

This API provides a user-friendly interface for users to modify the content of an existing post. The HTML form likely includes input fields pre-populated with the current details of the post, allowing users to make changes and submit updates.

Certainly! Here is the information about API 7: POST /newpost:

API 7: POST /newpost Create New Post

This API handles the creation of a new post. When a client makes a POST request to this endpoint with the required data (title, content, category, and tags), the server creates a new post object, assigns it a unique ID, adds it to the database (db.json), and responds with a message indicating the success or failure of the operation.

How to Create:

app.post("/newpost", (req, res) => {
  const newPost = {
    id: db.length + 1,
    title: req.body.title,
    content: req.body.content,
    category: req.body.category,
    tags: req.body.tags.split(","),
  };
  db.push(newPost);
  jsonfile.writeFile("./db/db.json", db, (err) => {
    if (err) {
      console.error(err);
      res.json({ message: "Error writing to database" });
    } else {
      res.json({
        message: `Post added successfully! Your Post Id is ${newPost.id}`,
      });
    }
  });
});
Enter fullscreen mode Exit fullscreen mode
  1. Endpoint Path: /newpost

    • This path specifies that the API will be triggered when a POST request is made to the "/newpost" endpoint.
  2. HTTP Method: POST

    • This API responds to HTTP POST requests.
  3. Handler Function:

    • (req, res) => {...}: This function is executed when a POST request is made to "/newpost". It creates a new post object with a unique ID, extracts the necessary information from the request body, adds the new post to the database (db.json), and responds with a message indicating the success or failure of the operation.
  4. Data Handling:

    • The post information (title, content, category, and tags) is obtained from the request body (req.body).
  5. Database Update:

    • The new post is pushed into the db array, and the updated database is written to the db.json file using jsonfile.writeFile().
  6. Response:

    • The API responds with a JSON object containing a message indicating whether the post was added successfully and providing the new post's ID.

This API is crucial for allowing users to submit new content to the application. It captures user input, adds a new post to the database, and provides feedback on the success of the operation along with the assigned post ID.

API 9: POST /updatepost Update Post

Description:

This API handles the update of an existing post. When a client makes a POST request to this endpoint with the required data (post ID, updated title, content, category, and tags), the server searches for the post in the database (db.json), updates its details, writes the changes to the database, and responds with a message indicating the success or failure of the update.

How to Create:

app.post("/updatepost", (req, res) => {
  let id = req.body.id;
  let post = db.find((post) => post.id == id);
  if (!post) {
    res.status(404).json({ message: "Not Found Any Post Related to Your ID" });
  } else {
    post.title = req.body.title;
    post.content = req.body.content;
    post.category = req.body.category;
    post.tags = req.body.tags.split(",");
    jsonfile.writeFile("./db/db.json", db, (err) => {
      if (err) {
        console.error(err);
        res.status(500).json({ message: "Error writing to database" });
      } else {
        res.json({
          message: `Post updated successfully! Your Post Id is ${id} `,
        });
      }
    });
  }
});
Enter fullscreen mode Exit fullscreen mode
  1. Endpoint Path: /updatepost

    • This path specifies that the API will be triggered when a POST request is made to the "/updatepost" endpoint.
  2. HTTP Method: POST

    • This API responds to HTTP POST requests.
  3. Handler Function:

    • (req, res) => {...}: This function is executed when a POST request is made to "/updatepost". It retrieves the post ID from the request body, finds the corresponding post in the database using db.find(), updates its details, writes the changes to the database, and responds with a message indicating the success or failure of the update.
  4. Data Handling:

    • The post information (ID, title, content, category, and tags) is obtained from the request body (req.body).
  5. Database Update:

    • The post details are updated in the db array, and the updated database is written to the db.json file using jsonfile.writeFile().
  6. Response:

    • The API responds with a JSON object containing a message indicating whether the post was updated successfully and providing the post ID.

Note:

  • Ensure that the request body contains the necessary data (ID, title, content, category, and tags) for updating a post.
  • Update the path and filename in the jsonfile.writeFile() function based on your file structure.

This API is crucial for allowing users to modify the content of an existing post, providing a mechanism for editing and updating posts within the application. The response includes a message confirming the success of the update and the post's ID.

API 10: GET /deletepost/:id

Description:

This API handles the deletion of an existing post. When a client makes a GET request to this endpoint with the post ID to be deleted, the server searches for the post in the database (db.json), removes it from the array, writes the changes to the database, and responds with a message indicating the success or failure of the deletion.

How to Create:

app.get("/deletepost/:id", (req, res) => {
  let id = req.params.id;
  let post = db.find((post) => post.id == id);
  if (!post) {
    res.status(404).json({ message: "Not Found Any Post Related to Your ID" });
  } else {
    let index = db.indexOf(post);
    db.splice(index, 1);
    jsonfile.writeFile("./db/db.json", db, (err) => {
      if (err) {
        console.error(err);
        res.status(500).json({ message: "Error writing to database" });
      } else {
        res.json({
          message: `Post deleted successfully! Your Post Id was ${id} `,
        });
      }
    });
  }
});
Enter fullscreen mode Exit fullscreen mode
  1. Endpoint Path: /deletepost/:id

    • This path specifies that the API will be triggered when a GET request is made to the "/deletepost/:id" endpoint.
  2. HTTP Method: GET

    • This API responds to HTTP GET requests.
  3. Handler Function:

    • (req, res) => {...}: This function is executed when a GET request is made to "/deletepost/:id". It retrieves the post ID from the URL parameters (req.params.id), finds the corresponding post in the database using db.find(), removes it from the array, writes the changes to the database, and responds with a message indicating the success or failure of the deletion.
  4. Data Handling:

    • The post ID is obtained from the URL parameters.
  5. Database Update:

    • The post is removed from the db array, and the updated database is written to the db.json file using jsonfile.writeFile().
  6. Response:

    • The API responds with a JSON object containing a message indicating whether the post was deleted successfully and providing the post ID.

Note:

  • Ensure that the URL parameters contain the necessary post ID for deletion.
  • Update the path and filename in the jsonfile.writeFile() function based on your file structure.

This API is crucial for allowing users to remove unwanted posts from the application. The response includes a message confirming the success of the deletion and the post's ID.


Get All Source Code: Github | Replit

Thanks For Reading Follow me if there is any problem just comment below!

In the Next Post We will create same Blog Backend By Using MongoDB

Meet you next time!

Top comments (2)

Collapse
 
sidharrth profile image
Siv Deploys

** :~: Concept/Product/Architecture/Code Evaluator :~: **

*As is code Run Results *

  • github: start command in package.json is incorrect. Infinite loop (cyclical)

** :~: Concept/Product/Architecture/Code Evaluator :~: **

Collapse
 
sarfarazunarr profile image
Sarfaraz Unar

You can run node index.js but mainly developers use nodemon so you should run nodemon index.js after installing packages.