← back to blog

Create a fast backend with ExpressJS

Jul 27, 2024 • 3min read

I started this video because many times we want to build a backend for an idea or an MVP and we get lost in giant “boilerplates”. Here I'm going to keep it simple: Pure Express, clear structure and minimal decisions to get going in minutes. This is what I have been using and it works for me to iterate quickly without mortgaging the future of the project.

Why Express and for whom?

* Because it is minimalist: you choose the pieces.

* Ideal for MVPs, internal APIs, webhooks, small and medium services.

* If you later want to climb, the structure is already organized.

The minimal structure I use

I like to separate the app from the server, and have routes, controllers and middlewares in separate folders. Something like this:

project/

├─ package.json

├─ .env

└─ src/

├─ app.js

├─ server.js

├─ routes/

│ └─ index.js

├─ controllers/

│ └─ health.controller.js

├─ middlewares/

│ └─ notFound.js

└─ config/

└─ env.js

Base dependencies

* Production: express, cors, morgan, dotenv

* Dev: nodemon

Quick commands:

npm i express cors morgan dotenv

npm i -D nodemon

In package.json:

"scripts": {

"dev": "nodemon src/server.js",

"start": "node src/server.js"

}

separate app.js and server.js

Keeping them separate lets you test the app without setting up the server and makes scaling easier.

src/app.js:

const express = require('express');

const morgan = require('morgan');

const cors = require('cors');

const routes = require('./routes');

const notFound = require('./middlewares/notFound');

const app = express();

app.use(cors());

app.use(express.json());

app.use(morgan('dev'));

app.use('/api', routes);

app.use(notFound);

module.exports = app;

src/server.js:

require('dotenv').config();

const app = require('./app');

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {

console.log(Server listening on http://localhost:${PORT});

});

Simple routes and controllers

src/routes/index.js:

const { Router } = require('express');

const { health } = require('../controllers/health.controller');

const router = Router();

router.get('/health', health);

module.exports = router;

src/controllers/health.controller.js:

function health(req, res) {

res.json({ ok: true, uptime: process.uptime() });

}

module.exports = { health };

404 Middleware

src/middlewares/notFound.js:

module.exports = (req, res, next) => {

res.status(404).json({ error: 'Path not found' });

};

Environment variables

In .env:

PORT=3000

NODE_ENV=development

And a little helper in case you want to centralize:

src/config/env.js:

module.exports = {

port: process.env.PORT || 3000,

nodeEnv: process.env.NODE_ENV || 'development',

};

What's left for next?

Error handling. It's a big topic: error middlewares, categories, HTTP codes, logging, and consistent responses. We see it in depth in the next part of the minicourse.

##Video

Below I leave you the full episode so you can see it step by step.

Bonus: fast deploy

If you want to take this to production in minutes, I have a video where I show how to deploy with Ubuntu + Docker. It can save you if you are validating an idea quickly:

Watch on YouTube (spanish)

---

Thanks for banking on the other side. If it helped you, leave a like and tell me in comments what you want to see in the next parts of the Express mini-course. Big hug and see you in the next one, which comes with errors... but well handled.

---

> Original article in Spanish: Crea un backend rapido con ExpressJS