DEV Community

Aaron Leopold
Aaron Leopold

Posted on

Minimal REST API Template using Express

πŸ‘‹ Hello everybody! I recently helped a friend who is very new to web development get started with creating an express REST API for the mobile application they are creating. I figured I would share how I created the base template I drafted in case it can help anyone else!

Overview ✨

At the end of this, you will have a very minimal template for scaling up your node/express application. Everything will be in JavaScript, however I encourage you to instead consider learning/using TypeScript for the enhanced safety benefits and developer experience. Since this was for an absolute beginner, I omitted TypeScript.

The API we create will be a simple hello world example, however the larger point is to showcase how I typically structure these types of projects to allow for an organized way of scaling it up to something larger. I'm always learning, so please let me know if you have any thoughts throughout this!

Project Structure 🧬

.
β”œβ”€β”€ package.json
β”œβ”€β”€ pnpm-lock.yaml
└── src
    β”œβ”€β”€ application.js
    β”œβ”€β”€ controllers
    β”‚Β Β  β”œβ”€β”€ ApiController.js
    β”‚Β Β  └── HelloController.js
    β”œβ”€β”€ endpoints
    β”‚Β Β  └── hello
    β”‚Β Β      └── helloWorld.js
    └── index.js

4 directories, 7 files
Enter fullscreen mode Exit fullscreen mode

Setup πŸ”¨

Initialize the project

Go ahead and create a new project folder and initialize it with a package.json using your package manager of choice. I've been experimenting with pnpm lately so the commands shown will be using that:

mkdir express-template && cd express-template
pnpm init -y
Enter fullscreen mode Exit fullscreen mode

There are very few dependencies we need, so let's go ahead and install the following:

pnpm add express cors
pnpm add --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Now, let's add two scripts to run our application:

"scripts": {
  "dev": "nodemon ./src/index.js",
  "start": "node ./src/index.js"
},
Enter fullscreen mode Exit fullscreen mode

Nodemon allows us restart the server automatically whenever
we make changes to our codebase.

Before we write some code, let's add some of the folder structure to the project:

mkdir src
mkdir src/controllers
mkdir src/endpoints
mkdir src/endpoints/hello
Enter fullscreen mode Exit fullscreen mode

Create the application class

I typically like to wrap my express application in a class that manages the server and database connection. While we won't be connecting a database in this template, we will create an empty function that would contain the connection logic.

create src/application.js and src/index.js and add the following:

// application.js
const express = require("express");
const cors = require("cors");

class Application {
  expressApp;

  async connect() {
    // your database connection code would go here
  }

  init() {
    this.expressApp = express();

    this.expressApp.use(express.json());
    this.expressApp.use(express.urlencoded({ extended: true }));

    const corsOptions = {
      // this allows from all origins, you probably want to restrict this
      origin: "*", // FIXME: change me to fit your configuration
    };

    this.expressApp.use(cors(corsOptions));

    this.expressApp.get("/hello", (_, res) => res.send("Hello World!"));
  }

  start() {
    const PORT = process.env.PORT || 5000;

    this.expressApp.listen(PORT, () => {
      console.log(`Server listening at http://localhost:${PORT}`);
    });
  }
}

module.exports = Application;
Enter fullscreen mode Exit fullscreen mode
// index.js
const Application = require('./application');

async function main() {
  const application = new Application();
  await application.connect();
  application.init();
  application.start();
}

main();
Enter fullscreen mode Exit fullscreen mode

To see that everything is working as expected, go to http://localhost:5000/hello in your browser and you should see 'Hello World' display on your screen.

Create an endpoint function

I like to organize my endpoints in the endpoints folder, nested in a subfolder that matches the controller it belongs to. For this simple application, we will just have a hello folder for the HelloController we will create in the next step.

Let's create a function to send a simple text response:

src/endpoints/hello/helloWorld.js

const helloWorld = async (_req, res) => {
  res.send("Hello World!");
};

module.exports = helloWorld;
Enter fullscreen mode Exit fullscreen mode

Now that we have a simple endpoint function, let's create our controllers to hook this up to our app.

Create the controllers

I usually have one parent controller I call the ApiController, which is then broken up into more controllers. To demonstrate this, create the following files:

src/controllers/ApiController.js

const { Router } = require("express");
const HelloController = require("./HelloController");

const ApiController = new Router();

ApiController.use("/hello", HelloController);

module.exports = ApiController;
Enter fullscreen mode Exit fullscreen mode

This will pass all requests with the /hello prefix to the HelloController.

src/controllers/HelloController.js

const { Router } = require("express");
const helloWorld = require("../endpoints/hello/helloWorld");

const HelloController = new Router();

HelloController.get("/", helloWorld);

module.exports = HelloController;
Enter fullscreen mode Exit fullscreen mode

When a GET request to /hello is made, our helloWorld function will now get run.

Wrapping it all up

To finalize everything, we need to actually use our ApiController in the Application class. We can now replace the inline GET request definition with our controller:

//     this.expressApp.get("/hello", (_, res) => res.send("Hello World!"));

this.expressApp.use("/api", ApiController);
Enter fullscreen mode Exit fullscreen mode

And with that, we're done! You now have a very small, minimal template for getting started with REST APIs using Express. If you go to http://localhost:5000/api/hello in your browser, you should see the 'Hello World!' message.

Let me know if this was helpful or if you have any notes (I love notes - it's how we all get better!)

Discussion (0)