DEV Community

Voke
Voke

Posted on • Edited on

Building in Public: CV Analyzer - Act 5 · Scene 2 : From Setup to The First Backend Surface

This post documents how I put together a TypeScript based Nodejs Express backend, wiring middleware, startup scripts, routing structure, and validating the server end-to-end before introducing the coding logic.

Click here for Act 5 · Scene 1

Table of Contents

Act 5 · Scene 2: From Setup to The First Backend Surface

This scene focuses on establishing a stable backend foundation: a TypeScript Express server that boots cleanly, applies middleware in the right order, exposes its first routes, and can be validated end to end without a frontend.

Overview

With the required Node.js packages installed in the previous scene and version control already in place, the next step was to bring the backend to life.

This scene focuses on initializing the server entry point, configuring core middleware, resolving startup issues, and exposing the first backend surface through structured routes and controllers.

The index.ts

I created a src folder and dropped an index.ts file inside it.
That file is the server’s front door.

Initial imports went in immediately:

import express from "express";
import cors from "cors";
import "dotenv/config";
import { Request, Response } from "express";
import mongoose from "mongoose";
import cookieParser from "cookie-parser";
Enter fullscreen mode Exit fullscreen mode

Just importing some basic packages, no biggie.

Middleware Setup

Before routes, before features, I stopped to wire some middlewares.

A middleware runs between the incoming request and the final response. In Express, it has access to req, res, and next.

Error Handler

Created a middleware folder in the src folder and added errHandlerMiddleware.ts in it.

Here is its content:

import { Request, Response, NextFunction } from "express";

export const errorHandlerMiddleware = (
  error: unknown,
  req: Request,
  res: Response,
  _next: NextFunction
) => {
  console.log("error message from errorHandlerMiddleware:", error);

  res
 .status(500)
 .json({ msg: error instanceof Error ? error.message : "something went wrong" });
};
Enter fullscreen mode Exit fullscreen mode

Express only recognizes an error handler if it accepts four parameters, even if next is unused.

Not Found Middleware

This middleware handles unmatched routes:

import { Request, Response } from "express";

export const notFoundMiddleware = (req: Request, res: Response) => {
  res.status(404).send({ msg: "Route doesn't exist..." });
};
Enter fullscreen mode Exit fullscreen mode

Both middlewares were imported and registered at the bottom of index.ts.

Startup: Failure

With those middlewares in place, I wired up a minimal server configuration:

const app = express();

app.use(cors({ origin: "http://localhost:3000", credentials: true }));
app.use(cookieParser());
app.use(express.json());

app.get("/", (_req: Request, res: Response) => {
  res.send("<h1>This is the index.ts route...</h1>");
});

app.use(notFoundMiddleware);
app.use(errorHandlerMiddleware);

const PORT = Number(process.env.PORT) || 5000;
Enter fullscreen mode Exit fullscreen mode

Here's the Startup logic:

const start = async () => {
  try {
    app.listen(PORT, "localhost", () => {
      console.log(`server listening on port ${PORT}`);
 });
 } catch (error) {
    console.log("startupError:", error);
 }
};

start();
Enter fullscreen mode Exit fullscreen mode

I then ran:

npm run dev
Enter fullscreen mode Exit fullscreen mode

It resulted in:

npm error Missing script: "dev"
Enter fullscreen mode Exit fullscreen mode

Fixing It

Fixed it by updating package.json:

"scripts": {
  "dev": "nodemon src/index.ts",
  "build": "tsc",
  "start": "npm run build && node dist/index.js"
}
Enter fullscreen mode Exit fullscreen mode

Retried it:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Server started successfully.

Routes and Controllers

Once the server stayed up, I went on to create a controllers folder and a routes folder.

Controllers handle behavior.
Routes decide where requests go.

Controllers

controllers/authController.ts:

export const registerController = (_req: Request, res: Response) => {
  res.status(200).json({ msg: "This is the register route" });
};

export const loginController = (_req: Request, res: Response) => {
  res.status(200).json({ msg: "This is the login route" });
};

export const logoutController = (_req: Request, res: Response) => {
  res.status(200).json({ msg: "This is the logout route" });
};
Enter fullscreen mode Exit fullscreen mode

Routes

routes/auth-route.ts:

const authRouter = Router();

authRouter.post("/register", registerController);
authRouter.post("/login", loginController);
authRouter.get("/logout", logoutController);

export default authRouter;
Enter fullscreen mode Exit fullscreen mode

Testing with Postman

Before introducing the frontend to the backend, I verified backend behavior using Postman.

I then sent Requests:

Here is a picture of postman when first opened:

Made a request to the home route:

Meaning, this line ran:

app.get("/", (_req: Request, res: Response) => {
  res.send("<h1>This is the index.ts route...</h1>");
});
Enter fullscreen mode Exit fullscreen mode

I then tested the register route:

Meaning, this line ran:

export const registerController = (_req: Request, res: Response) => {
  res.status(200).json({ msg: "This is the register route" });
};
Enter fullscreen mode Exit fullscreen mode

Tested the login route:

Meaning, this line ran:

export const loginController = (_req: Request, res: Response) => {
  res.status(200).json({ msg: "This is the login route" });
};
Enter fullscreen mode Exit fullscreen mode

And the logout route followed the same pattern.

Requests hit.
Responses returned successfully.
The server didn't crash

This means that we are ready to rock and roll.

Mental Model

Right now:

  • The backend boots reliably

  • Middleware has been introduced

  • Routes and controllers are separated

  • The system is ready for real logic

Why This Scene Matters

This scene shows that I:

  • Bring backend systems online incrementally
  • Build for maintainability
  • Don’t rush features before foundations

Thanks for reading.
Let’s move on to the Next Act.

We in the Building…
Building in Progress…

Click here for Act 6 · Scene 1

Top comments (0)