Build a Task Manager API with TypeScript

Build a REST API with TypeScript and Express handling GET, POST, PUT, and DELETE.

Introduction

30 Second Summary

Every app you use daily, from a to-do list to a social media feed, talks to a server behind the scenes to create, read, update, and delete your data. That communication happens through something called an API.

In this project, you will build a Task Manager API using TypeScript and Express that runs on your own computer. You'll create, list, update, and delete tasks entirely through HTTP requests.

What You'll Build

When you're done, you'll open your browser, type a URL, and see your task list appear as live JSON data that you created and managed entirely through your own API.

By the end of this project, you'll have:

  • A running Express server where you type http://localhost:3000/tasks in your browser and instantly see your task list returned as JSON.
  • POST, PUT, and DELETE endpoints that let you create new tasks, mark them as complete, and remove them by ID.
  • A structured TypeScript project with separate modules connected through imports and exports, mirroring how professional codebases are organized.
  • Secret Mission: Add query parameter filtering so you can fetch only completed or incomplete tasks.

Are there any prerequisites?

You should have basic JavaScript knowledge (variables, functions, objects) and Node.js already installed on your computer. No TypeScript or Express experience is needed.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters for your development skills.

Set Up Your TypeScript Project

Before you can write any server code, you need the right tools in place. TypeScript adds type safety to your JavaScript, Express handles incoming web requests, and a development tool called tsx runs your TypeScript files instantly as you code.

In this step, you will create a project folder, install all three tools, configure TypeScript, and confirm everything works by running your first TypeScript file.

In this step, get ready to:
  • Create a project folder with all dependencies installed.
  • Configure TypeScript with a tsconfig.json file.
  • Run your first TypeScript file and see output in the terminal.
Create your project folder and install dependencies

Every project starts with a dedicated folder and a package manager to track your dependencies. You will create the folder on your Desktop so it is easy to find.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Terminal and press Enter to open it.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir task-manager-api
cd task-manager-api
  • Initialize a new Node.js project and install all dependencies by running these commands:
npm init -y
npm install express
npm install -D typescript tsx @types/node @types/express

What do these commands do?

  • npm init -y creates a package.json file that tracks your project's name, version, and dependencies.
  • npm install express installs the Express web framework as a production dependency.
  • npm install -D installs development-only tools: TypeScript itself, tsx (a fast TypeScript runner), and type definitions for Node.js and Express.
  • Create the src folder where your TypeScript source files will live:
mkdir src
  • Confirm everything was created by running:
ls

You should see node_modules, package-lock.json, package.json, and src listed in the output.

Seeing 'command not found' for npm?

This means Node.js is not installed or not on your system PATH. Reinstall Node.js from nodejs.org and restart your terminal.

help me fix npm command not found

Open your project in VS Code
  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type VS Code and press Enter to open it.
  • Click File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the task-manager-api folder, then click Open.

You should see node_modules, package.json, and src in the Explorer sidebar on the left.

Create the TypeScript configuration

TypeScript needs a configuration file to know how to compile your code. This file tells TypeScript where your source files are, where to put compiled output, and what strictness rules to enforce.

  • In VS Code's Explorer sidebar, hover over the TASK-MANAGER-API heading and click the new file icon.
  • Name the file tsconfig.json and press Enter.
  • Paste the following configuration into tsconfig.json:
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "CommonJS",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "node"
  },
  "include": ["src"]
}

What do these options do?

  • target tells TypeScript which JavaScript version to compile down to.
  • rootDir and outDir separate your source code (src/) from compiled output (dist/).
  • strict: true enables all of TypeScript's type-checking rules so you catch mistakes early.
  • esModuleInterop lets you use import express from "express" syntax instead of the older require() style.
  • Save tsconfig.json with Cmd+S (macOS) or Ctrl+S (Windows).

You should see tsconfig.json appear in the Explorer sidebar next to package.json.

Don't see tsconfig.json in the sidebar?

Make sure you created the file at the top level of task-manager-api, not inside the src or node_modules folder. If you accidentally placed it in the wrong folder, drag it to the root level in the sidebar.

help me fix my tsconfig.json placement

Add the dev script and test your setup

Your project needs scripts that tell npm how to run your code. The most important one is the dev script, which uses tsx to run and automatically reload your TypeScript files whenever you save a change.

  • Open package.json by clicking it in the Explorer sidebar.
  • Find the "scripts" section. It currently looks like this:
"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1"
}
  • Replace the entire "scripts" block with these three scripts:
"scripts": {
  "dev": "tsx watch src/index.ts",
  "build": "tsc",
  "start": "node dist/index.js"
}

What do these scripts do?

  • dev runs your TypeScript file with tsx in watch mode. Every time you save a change, it automatically restarts.
  • build compiles your TypeScript into plain JavaScript (for production).
  • start runs the compiled JavaScript output directly with Node.js.
  • Save package.json.
  • Now create your first TypeScript file. Click on the src folder in the Explorer sidebar, then click the new file icon.
  • Name the file index.ts and press Enter.
  • Paste this single line into src/index.ts:
console.log("Hello TypeScript!");
  • Save src/index.ts.

Time to test. Before you run this, what do you think you will see in the terminal?

  • Open VS Code's integrated terminal by pressing Ctrl+` (backtick key, same on macOS and Windows).
  • Run your dev script:
npm run dev

You should see Hello TypeScript! printed in the terminal. This confirms that tsx is running your TypeScript file successfully.

Don't see Hello TypeScript! in the output?

  • Check that your file is saved as src/index.ts (inside the src folder, not in the project root).
  • Make sure the "dev" script in package.json reads exactly "tsx watch src/index.ts".
  • If you see a "Cannot find module" error, confirm that tsx is listed under devDependencies in package.json. If not, run npm install -D tsx again.

help me fix npm run dev not showing Hello TypeScript

  • Press Ctrl+C in the terminal to stop the dev script. You will need the terminal free for later steps.

✔️ Awesome, I've got everything!

Great. Make sure both package.json and src/index.ts are saved before moving on.

ⓧ I'd like to double check the full code

Here is what each file should look like at this point.

package.json:

{
  "name": "task-manager-api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^5.2.1"
  },
  "devDependencies": {
    "@types/express": "^5.0.6",
    "@types/node": "^24.0.0",
    "tsx": "^4.23.1",
    "typescript": "^7.0.2"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "CommonJS",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "node"
  },
  "include": ["src"]
}

src/index.ts:

console.log("Hello TypeScript!");

Your TypeScript environment is ready. Next up, you will build your first Express server and see it respond in the browser.

Create Your First Express Server

Your TypeScript project is set up and tsx watch is already running in the terminal. Right now it just prints "Hello TypeScript!" and exits.

You need a running server to see your code respond to browser requests. In this substep you will turn src/index.ts into an Express server that listens for requests and sends back JSON.

In this step, get ready to:
  • Replace src/index.ts with Express server code that responds to HTTP requests.
  • Verify the server is running by opening it in your browser.
Write your Express server
  • In VS Code, open src/index.ts (it currently has the console.log line from the last step).
  • Select all the existing code and replace it with the following:
// Import Express and its type definitions
import express, { Request, Response } from "express";

// Create the Express application and define the port
const app = express();
const PORT = 3000;

// Define a route that responds to GET requests at the root URL
app.get("/", (req: Request, res: Response) => {
  res.json({ message: "Task Manager API is running!" });
});

// Start the server and listen for incoming requests
app.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

What does this code do?

  • import express, { Request, Response } brings in the Express library and its TypeScript type definitions so your editor can check your code.
  • const app = express() creates an Express application. This is the object you attach routes and settings to.
  • app.get("/", ...) registers a route. When someone visits the root URL, Express runs the function you pass in and sends back JSON.
  • app.listen(PORT, ...) starts the server on port 3000 so it can receive incoming requests.

Before you check the browser, what do you think you will see when you open http://localhost:3000?

  • Save src/index.ts.
  • In your terminal, you should see tsx watch detect the change and restart. The output now reads Server running at http://localhost:3000.
  • Open your browser and navigate to http://localhost:3000.

You should see {"message":"Task Manager API is running!"} displayed in the browser. That JSON response proves your Express server is running and responding to requests.

Not seeing the JSON in your browser?

  • Check your terminal for errors. If you see a syntax error, compare your code character-for-character against the code block above.
  • Make sure you saved the file. Unsaved changes will not trigger tsx watch to restart.
  • If you see EADDRINUSE, another process is already using port 3000. Stop it with Ctrl+C in that terminal, then re-run npm run dev.

Why isn't my Express server responding in the browser?

✔️ Awesome, I've got everything!

Great. Double check you have saved src/index.ts and your browser is showing the JSON message.

ⓧ I'd like to double check the full code

Here is the complete src/index.ts file at this point:

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

const app = express();
const PORT = 3000;

app.get("/", (req: Request, res: Response) => {
  res.json({ message: "Task Manager API is running!" });
});

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

Your server is alive and responding to requests. Next up, you will split your code into separate TypeScript modules and serve real task data from a dedicated file.

Create a Tasks Module with Imports

Your server is live and responding to browser requests. Right now, all your code lives in a single file. As your project grows, that single file becomes impossible to navigate.

Real projects split code into separate files called modules. Each module has a clear job. In this step, you'll create a dedicated tasks module and connect it to your server using TypeScript imports and exports.

In this step, get ready to:
  • Define a Task interface that describes the shape of your data.
  • Export data from a separate module file.
  • Import the module into your server and serve tasks through a new endpoint.
Create the tasks module

A TypeScript interface defines the exact shape your data must follow. By putting the interface and the data together in their own file, you create a module that other files can import from.

  • In VS Code, right-click the src folder in the Explorer sidebar and select New File.
  • Name the file tasks.ts and press Enter.
  • Add the following code to src/tasks.ts:
export interface Task {
  id: number;
  title: string;
  completed: boolean;
}

export let tasks: Task[] = [
  { id: 1, title: "Learn TypeScript", completed: false },
  { id: 2, title: "Build a REST API", completed: false },
];

What does this code do?

  • export interface Task defines the exact shape every task object must follow: an id number, a title string, and a completed boolean.
  • export let tasks: Task[] creates an array of tasks that matches the interface. The two starter tasks give you data to see immediately.
  • The export keyword makes both the interface and the array available to other files. Without it, they stay private to this file.
  • Save tasks.ts.
  • Confirm the file now appears under the src folder in the Explorer sidebar.

Don't see tasks.ts in the sidebar?

  • Make sure you right-clicked the src folder, not the root task-manager-api folder. The file must live inside src/.
  • If you accidentally created it in the wrong place, drag it into the src folder or delete it and try again.

Help me create a new file in the right folder

Import the module and add a tasks route

Now that tasks.ts exports the interface and data, you can pull them into index.ts using a named import. This is how TypeScript modules connect to each other.

  • In src/index.ts, find this line at the top of the file:
import express, { Request, Response } from "express";
  • Add this import directly below it:
import { tasks, Task } from "./tasks";

What does the import do?

import { tasks, Task } from "./tasks" pulls in the tasks array and the Task interface from your new module. The curly braces are named imports. They match the exact names you exported.

The ./ prefix tells TypeScript to look for a local file, not an npm package.

  • Find your existing GET "/" route. Add this new route below it, but above app.listen:
app.get("/tasks", (req: Request, res: Response) => {
  res.json(tasks);
});

What does this route do?

The new GET /tasks route responds with the entire tasks array as JSON. When someone visits this URL, Express converts the array to a JSON string and sends it back.

  • Save src/index.ts.

Your terminal shows tsx watch restarting the server. Before you check the browser, what do you think you'll see at http://localhost:3000/tasks?

  • Open http://localhost:3000/tasks in your browser.

You see a JSON array with two tasks, each showing an id, title, and completed status. That data is coming from your separate tasks.ts module, imported into your server.

Not seeing the tasks array?

  • Make sure you saved both tasks.ts and index.ts. The tsx watch process only restarts when the imported file is saved.
  • Check that your import path is "./tasks" with the dot-slash prefix. Without the ./, TypeScript looks for an npm package instead of your local file.
  • Check the terminal for any red error messages. A typo in the interface or array will prevent the server from starting.

Help me debug my /tasks endpoint

✔️ Awesome, I've got everything!

Great. Double check you have saved both files.

ⓧ I'd like to double check the full code

Here is the complete src/tasks.ts:

export interface Task {
  id: number;
  title: string;
  completed: boolean;
}

export let tasks: Task[] = [
  { id: 1, title: "Learn TypeScript", completed: false },
  { id: 2, title: "Build a REST API", completed: false },
];

And here is the complete src/index.ts:

import express, { Request, Response } from "express";
import { tasks, Task } from "./tasks";

const app = express();
const PORT = 3000;

app.get("/", (req: Request, res: Response) => {
  res.json({ message: "Task Manager API is running!" });
});

app.get("/tasks", (req: Request, res: Response) => {
  res.json(tasks);
});

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

Your API now serves real data from a separate module. Next up, you'll let users add their own tasks by handling POST requests.

Add a POST Endpoint

Your API can return data, but a read-only API is not very useful. Real applications need to accept new information from users too.

In this step, you will add a POST endpoint that lets users create new tasks. You will also discover a gap in your server's setup that prevents it from reading incoming data.

In this step, get ready to:
  • Add a POST route that creates new tasks.
  • Test the endpoint and observe a missing piece.
Add a POST /tasks route

A POST request sends data TO your server. Your new route will read the task title from the request body, build a new task object, and send it back to confirm it was added.

  • In src/index.ts, find the GET /tasks route. Add the following POST route directly below it:
app.post("/tasks", (req: Request, res: Response) => {
  const { title } = req.body;
  const newTask: Task = {
    id: tasks.length + 1,
    title: title,
    completed: false,
  };
  tasks.push(newTask);
  res.status(201).json(newTask);
});

What does this code do?

  • app.post("/tasks", ...) listens for POST requests at the /tasks path.
  • const { title } = req.body pulls the title property out of the incoming request body using destructuring.
  • The new task gets an auto-incremented id based on the array length, and completed defaults to false.
  • res.status(201).json(newTask) sends back the new task with a 201 status code, which means "created successfully."
  • Save src/index.ts.
  • Check your terminal where tsx watch is running. You should see Server running at http://localhost:3000 printed again as it restarts.

Don't see the server restart?

  • Make sure you saved the file. Unsaved changes will not trigger a restart.
  • Check for red squiggly lines in VS Code. A missing comma, bracket, or typo in the route will prevent the server from compiling.

Help me figure out why tsx watch isn't restarting my server.

Test the POST endpoint

Your POST route is live. Time to send it some data and see what comes back.

Before you run the next command, what do you think the response will look like? You are sending a title of "Buy groceries". Do you expect it to appear in the response?

  • Open a new terminal in VS Code. Press Ctrl+Shift+` (macOS and Windows) to open a new terminal panel. Your existing terminal needs to keep running tsx watch.
  • Send a POST request to create a new task by running this command:
Invoke-RestMethod -Uri http://localhost:3000/tasks -Method POST -Body '{"title":"Buy groceries"}' -ContentType "application/json"

The response shows a new task, but the title is missing from the output. The title shows as nothing because Express cannot read the JSON body yet.

Why is the title missing?

Express does not parse incoming JSON automatically. Without a body parser, req.body is empty. Your route tries to pull title from it, but there is nothing to pull.

Express needs a piece of middleware to understand JSON. That is exactly what you will add in the next step.

This gap is expected and intentional. You just discovered a real problem that every Express developer encounters on their first API.

✔️ Awesome, I've got everything!

Great. Double check you have saved src/index.ts and your terminal shows the server restarted.

ⓧ I'd like to double check the full code

Here is the full src/index.ts at this point:

import express, { Request, Response } from "express";
import { tasks, Task } from "./tasks";

const app = express();
const PORT = 3000;

app.get("/", (req: Request, res: Response) => {
  res.json({ message: "Task Manager API is running!" });
});

app.get("/tasks", (req: Request, res: Response) => {
  res.json(tasks);
});

app.post("/tasks", (req: Request, res: Response) => {
  const { title } = req.body;
  const newTask: Task = {
    id: tasks.length + 1,
    title: title,
    completed: false,
  };
  tasks.push(newTask);
  res.status(201).json(newTask);
});

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

Your POST route is written correctly, but Express cannot read the data you are sending it. In the next step, you will add a single line of middleware that unlocks body parsing and completes your API with PUT and DELETE endpoints.

Fix the Body Parser and Complete Your API

In the previous step, you sent a POST request and the response came back with the title missing. The server received the request but could not read the JSON data inside it.

Express does not parse request bodies by default. You need to explicitly tell it to handle incoming JSON using middleware. In this step, you will add that one-line fix and then build out the PUT and DELETE endpoints to complete your API.

In this step, get ready to:
  • Add JSON parsing middleware to fix the POST endpoint.
  • Add a PUT endpoint to update existing tasks.
  • Add a DELETE endpoint to remove tasks.
Add the JSON body parser middleware

Express needs middleware to understand incoming request bodies. Without it, req.body is undefined and any data the user sends gets silently ignored.

  • In src/index.ts, find this line:
const PORT = 3000;
  • Add this line directly below it:
app.use(express.json());
  • Your file should now look like this around that section:
const app = express();
const PORT = 3000;

// Middleware to parse incoming JSON request bodies
app.use(express.json());

What does this line do?

Middleware is code that runs between receiving a request and sending a response. express.json() intercepts every incoming request, checks if it has a JSON body, and parses it into a JavaScript object.

After this middleware runs, req.body contains the parsed data. Without it, Express ignores the body entirely.

Before you run the POST command again, what do you expect the response to show this time?

  • Save src/index.ts. The tsx watch process will automatically restart your server.
  • Test the POST endpoint again by running this command in a new PowerShell terminal:
Invoke-RestMethod -Uri http://localhost:3000/tasks -Method POST -Body '{"title":"Buy groceries"}' -ContentType "application/json"

This time, the response shows title : Buy groceries. The middleware parsed the JSON body and your POST endpoint can now read the title.

Still seeing an empty title?

  • Make sure app.use(express.json()) is placed BEFORE your route definitions. Middleware only applies to routes declared after it.
  • Check that you saved the file. Look at your terminal for the tsx restart message.
  • Confirm the -ContentType "application/json" flag is included in your PowerShell command.

Why is my POST endpoint still not reading the request body?

Add a PUT endpoint to update tasks

A PUT request lets users update an existing resource. Your endpoint needs to find the right task by its ID, then update the fields the user sends.

  • In src/index.ts, add this route after the POST /tasks route and before app.listen():
app.put("/tasks/:id", (req: Request, res: Response) => {
  // Extract the task ID from the URL parameter
  const id = parseInt(req.params.id);
  const task = tasks.find((t) => t.id === id);

  // Return 404 if no task matches the ID
  if (!task) {
    res.status(404).json({ message: "Task not found" });
    return;
  }

  // Update only the fields that were sent in the request
  const { title, completed } = req.body;
  if (title !== undefined) task.title = title;
  if (completed !== undefined) task.completed = completed;

  res.json(task);
});

What does this code do?

  • :id in the route path is a URL parameter. When someone hits /tasks/1, Express makes "1" available as req.params.id.
  • parseInt() converts the string "1" into the number 1 so it can match the task's numeric ID.
  • The if (title !== undefined) check means the user can update just the title, just the completed status, or both at once.
  • Save src/index.ts and test the PUT endpoint by marking the first task as completed:
Invoke-RestMethod -Uri http://localhost:3000/tasks/1 -Method PUT -Body '{"completed":true}' -ContentType "application/json"

You should see the first task returned with completed : True while the title stays unchanged.

Seeing a 404 response?

  • Make sure you are using /tasks/1 (not /tasks/ without an ID). The :id parameter is required.
  • Check that the route path is "/tasks/:id" with the colon before id. The colon tells Express this is a dynamic parameter.

Why is my PUT request returning 404 even though the task exists?

Add a DELETE endpoint to remove tasks

The DELETE endpoint removes a task from the array permanently. It uses findIndex to locate the task and splice to remove it.

  • In src/index.ts, add this route after the PUT route and before app.listen():
app.delete("/tasks/:id", (req: Request, res: Response) => {
  // Extract the task ID from the URL parameter
  const id = parseInt(req.params.id);
  const index = tasks.findIndex((t) => t.id === id);

  // Return 404 if no task matches the ID
  if (index === -1) {
    res.status(404).json({ message: "Task not found" });
    return;
  }

  // Remove the task from the array and return it
  const deleted = tasks.splice(index, 1);
  res.json(deleted[0]);
});

What does this code do?

  • findIndex() returns the position of the task in the array, or -1 if it does not exist.
  • splice(index, 1) removes exactly one item at that position and returns it in an array. deleted[0] grabs the removed task so you can send it back to the user as confirmation.
  • Save src/index.ts.

Before you run the DELETE command, what do you think the response will contain?

  • Test the DELETE endpoint by removing the second task:
Invoke-RestMethod -Uri http://localhost:3000/tasks/2 -Method DELETE

You should see the deleted task returned: id : 2, title : Build a REST API.

  • Confirm it is gone by opening your browser to http://localhost:3000/tasks. You should see only one task remaining in the array.

DELETE returning an error?

  • If you already deleted task 2 in a previous attempt, it will not exist anymore. Try /tasks/1 instead, or restart your server with Ctrl+C then npm run dev to reset the in-memory data.
  • Make sure the route uses tasks.findIndex (not tasks.find). You need the index position for splice to work.

Why is my DELETE endpoint not removing the task from the array?

✔️ Awesome, I've got everything!

Great. Double check you have saved src/index.ts and your server is still running.

ⓧ I'd like to double check the full code

Your src/index.ts should contain these sections in order. Scroll through your file and confirm each one is present:

  • Import statements at the top (express, Request, Response, tasks, Task).
  • App and PORT declarations.
  • app.use(express.json()) middleware line.
  • GET "/" route.
  • GET "/tasks" route.
  • POST "/tasks" route.
  • PUT "/tasks/:id" route.
  • DELETE "/tasks/:id" route.
  • app.listen() at the very bottom.

Your API now handles all four core HTTP methods. You can create, read, update, and delete tasks. Next up, you will take on a Secret Mission to add query parameter filtering to your GET endpoint.

Secret mission

Add Query Parameter Filtering

Your API returns every task every time. Real APIs let users ask for exactly what they need. Can you add filtering so users can request only completed or only incomplete tasks through the URL?

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally, so there are no ongoing costs. Your server only runs while npm run dev is active in your terminal.

Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • The task-manager-api project folder on your Desktop (includes all source files and node_modules).
  • The running Express server (tsx watch process in your terminal).

Keep everything running

No action needed. Choose this if you are still actively building or experimenting with your API.

  • Leave your terminal open with tsx watch running.
  • Your API stays available at http://localhost:3000 as long as the process is active.

Pause - I'll come back to this later

Shut down the running server to free up your terminal and port 3000. Your project files stay on disk so you can resume anytime.

  • Switch to the terminal where tsx watch is running.
  • Press Ctrl+C to stop the server.
  • To resume later, open the task-manager-api folder in VS Code and run npm run dev in the terminal.

Delete - I don't want to use this again

Remove all project files from your machine. Nothing is deployed externally, so deleting the folder removes everything.

  • Switch to the terminal where tsx watch is running and press Ctrl+C to stop the server.
  • Close the task-manager-api folder in VS Code.
  • Delete the project folder by running this command in your terminal:

macOS

cd ~/Desktop
rm -rf task-manager-api

Windows

cd ~/Desktop
Remove-Item -Recurse -Force task-manager-api
  • Confirm the folder is gone by running ls (macOS) or dir (Windows) on your Desktop. You should no longer see task-manager-api in the output.

That's a Wrap!

That's a Wrap!

Nice work! You just built a fully functional REST API from scratch using TypeScript and Express.

You've learned how to:

  • Build a running Express server that handles all four core HTTP methods: GET, POST, PUT, and DELETE.
  • Structure a TypeScript project into separate modules connected through imports and exports, with typed interfaces defining the shape of your data.
  • Diagnose and fix a missing body parser to understand how Express middleware works and why order matters.
  • Secret Mission: Added query parameter filtering to return subsets of data based on URL parameters.

Ready to quiz yourself?