DEV Community

Samuel Oyerinde
Samuel Oyerinde

Posted on

Building an API with Express.js and Connecting It to the Frontend

Building an API with Express.js and Connecting It to the Frontend

When building modern web applications, APIs serve as the bridge between the backend (server-side logic) and the frontend (user interface). In this blog post, we’ll break down how an Express.js-based API works, its key components, and how it connects to a frontend application.

1. What is a Router in Express.js?

A router in Express.js is a way to organize API endpoints into modular and reusable components. Think of it as a "sub-application" that groups related routes together.

  • Why Use Routers?
    • Keeps code clean and modular.
    • Allows you to separate concerns (e.g., authentication routes in auth.js, product routes in products.js).

Example:

const express = require('express');
const router = express.Router();

// Define routes
router.post('/register', (req, res) => {
  res.send('Register endpoint');
});
router.post('/login', (req, res) => {
  res.send('Login endpoint');
});

// Export the router
module.exports = router;
Enter fullscreen mode Exit fullscreen mode

This router can then be mounted in the main app:

const authRouter = require('./routes/auth');
app.use('/api/auth', authRouter);
Enter fullscreen mode Exit fullscreen mode

2. Backend API Workflow

Here’s how a typical authentication API works:

a. POST /api/auth/register

  • Purpose: Registers a new user.
  • Steps:
    1. Check if the email already exists in the database.
    2. Hash the password using bcrypt.
    3. Save the user to the database.
    4. Return a JWT token for future authenticated requests.

b. POST /api/auth/login

  • Purpose: Logs in an existing user.
  • Steps:
    1. Verify if the email exists.
    2. Compare the provided password with the hashed password stored in the database.
    3. If valid, return a JWT token.

c. GET /api/auth/user

  • Purpose: Fetches data of the logged-in user.
  • Steps:
    1. Validate the JWT token using middleware.
    2. Return user data, excluding sensitive information like passwords.

Code Example for /register:

const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const User = require('./models/User'); // Mongoose model

router.post('/register', async (req, res) => {
  const { email, password } = req.body;

  // Check if user exists
  const existingUser = await User.findOne({ email });
  if (existingUser) return res.status(400).send('User already exists');

  // Hash password
  const hashedPassword = await bcrypt.hash(password, 10);

  // Save user to database
  const newUser = new User({ email, password: hashedPassword });
  await newUser.save();

  // Generate JWT token
  const token = jwt.sign({ id: newUser._id }, 'secretKey', { expiresIn: '1h' });

  res.status(201).json({ token });
});
Enter fullscreen mode Exit fullscreen mode

3. Connecting the Backend to the Frontend

The frontend communicates with this API through HTTP requests.

Step 1: Registration/Login

The frontend sends a POST request to /api/auth/register or /api/auth/login with user credentials.

Example Frontend Code:

// Register a user
const response = await fetch('/api/auth/register', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'test@example.com', password: '123456' }),
});

const data = await response.json();
console.log(data.token); // JWT token
Enter fullscreen mode Exit fullscreen mode

Step 2: Storing JWT Token

After receiving the JWT token, store it securely (e.g., in localStorage or cookies):

localStorage.setItem('token', data.token);
Enter fullscreen mode Exit fullscreen mode

Step 3: Making Authenticated Requests

For protected routes like /api/auth/user, include the JWT token in the request headers:

const token = localStorage.getItem('token');

const response = await fetch('/api/auth/user', {
  headers: { Authorization: `Bearer ${token}` },
});

const userData = await response.json();
console.log(userData);
Enter fullscreen mode Exit fullscreen mode

4. Key Components of an Express API

Component Role
Express Router Organizes routes into modules for cleaner code.
Bcrypt Hashes passwords securely before storing them in a database.
JWT (JSON Web Token) Generates tokens for authenticating users across sessions.
Mongoose Models Defines schemas for MongoDB collections (e.g., users).
Auth Middleware Validates JWT tokens for protected routes like /api/auth/user.

Summary: Frontend vs Backend Roles

Frontend Backend
Sends HTTP requests to API endpoints. Handles requests and sends responses with data/logic.
Stores and uses tokens for auth. Generates and validates tokens using JWTs.
Displays user data (e.g., profile). Fetches and secures data from databases like MongoDB.

Why This Matters

  1. Security: Passwords are hashed, and JWT ensures only authenticated users access protected routes.
  2. Scalability: Modular routing and middleware make it easier to grow your application.
  3. Separation of Concerns: The frontend focuses on UI/UX while the backend handles logic and data.

This approach forms the backbone of most modern web apps, enabling seamless communication between frontend interfaces and backend systems.


Tags:

#NodeJS #ExpressJS #API #Authentication #WebDevelopment #FrontendBackendIntegration

Citations:
[1] https://rapidapi.com/blog/nodejs-express-rest-api-example/
[2] https://www.freecodecamp.org/news/the-express-handbook/
[3] https://dev.to/mrrishimeena/understanding-expressjs-router-nodejs-a-comprehensive-guide-59o8
[4] https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction
[5] https://dev.to/reiallenramos/create-an-express-api-static-and-dynamic-routes-33lb
[6] https://www.codecademy.com/article/what-is-express-js
[7] https://www.youtube.com/watch?v=1XxQBXl4Lv8
[8] https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/
[9] https://www.topcoder.com/thrive/articles/routing-in-express-js
[10] https://kinsta.com/knowledgebase/what-is-express-js/

Top comments (0)