Welcome to your first lesson in NestJS Fundamentals. In this lesson, you’ll create the foundation for a full-stack project using NestJS as the backend. The goal is to set up:
- A functional NestJS server
- Static file serving (for a minimal frontend)
- A working API endpoint (
/api/hello) - Proper CORS configuration so the frontend can talk to the backend
- SPA (Single Page Application) fallback routing support
The eventual goal is to create a full stack app with integrated React frontend, but for now we’ll focus entirely on the backend and a simple preview using a raw index.html file.
Here’s how the project is structured:
Breakdown:
src/holds the NestJS application code.public/contains a static HTML file to preview the API. In the browser preview, you can:- Visit
/to load the staticindex.html. - Visit
/api/helloto see a greeting returned from the backend.
This will give you a full round-trip experience between the frontend and backend.
To start a NestJS project (on your own machine), you’d typically run:
This uses the Nest CLI (Command Line Interface) – a tool that helps scaffold your project with best practices and TypeScript support. It automatically creates:
- a controller to handle routes. In our code, we have
app.controller.tswhich handles incomingHTTPrequests like/api/hello. - a service for logic. In the
app.service.ts, we have a logic or data used by the controller. You’ll see more examples as we proceed with the course. - a module to glue everything together. Our
app.module.tsregisters all controllers/services and serves as the app's root
💡 We will experiment with CLI commands like
nest generate service usersto scaffold new parts in our practice sessions.
The main.ts file is the entry point of every NestJS application. It’s where the app is created and configured before being run.
Here’s a breakdown of what happens in main.ts, line by line:
1. Creating the App Instance:
This line bootstraps the app by loading the AppModule and initializing NestJS with the Express framework under the hood. The type <NestExpressApplication> gives us access to Express-specific features, like serving static files.
2. Enabling CORS (Cross-Origin Resource Sharing):
CORS is a browser security feature that blocks requests from one domain to another unless explicitly allowed.
In development, your frontend (React) and backend (NestJS) may run on different ports (e.g., React on localhost:5173, NestJS on localhost:3000). CORS needs to be enabled so the frontend can make requests to the backend.
origin: '*'allows all origins to access the backend. This is safe for local development, but you should restrict it in production.credentials: trueallows cookies or authorization headers to be sent along with requests.
3. Serving Static Files:
Every NestJS app starts with a root module, and that’s AppModule.
controllerstells Nest which controller to use.providersare services or any logic providers.importswill later include other feature modules.
This is where we register the building blocks of our app. In NestJS, a module serves as a logical container that groups related components — such as controllers, services, and other modules — allowing your app to stay organized and scalable as it grows.
The controller defines our API routes and how they respond to HTTP requests.
The controller is bound to /api.
The method getHello() handles GET requests to /api/hello.
It calls this.appService.getHello() to get the actual data.
Controllers should stay lightweight and delegate business logic to services. A controller in NestJS is responsible for handling incoming HTTP requests, extracting parameters, and returning responses. It acts as the interface between the client (frontend) and the internal logic of the app.
The service contains reusable logic. Right now it just returns a string:
But as your app grows, this file may:
- Fetch data from a database
- Perform calculations
- Call external APIs
Services keep your logic modular and testable. A service in NestJS encapsulates reusable, application-specific logic and is typically injected into controllers or other services using Nest's built-in dependency injection system.
Now, let’s add a basic HTML file to the public folder so you can see your API in action from a browser.
Here is an example public/index.html:
Explanation:
- The
<button>has an ID of btn, which lets us target it with JavaScript. - The
<pre>tag is where we’ll display the API response. - Inside the
<script>tag, we define a JavaScript function which:- Adds a click listener to the button.
- Makes a GET request to
/api/hello. - Waits for the text response.
- Displays the result inside the
<pre>block.
Output:
When you open localhost:3000 and click the button, you should see the greeting from your backend appear below the button.
In this lesson, you learned how to scaffold a NestJS project to serve both an API and a static user interface. You set up static file serving, enabled CORS for frontend-backend communication, added a simple HTML preview, and configured a fallback for single-page applications. These are the essential building blocks for any modern web API project.
Next, you will get hands-on practice with these concepts. You will try serving static files, enabling CORS, and connecting your frontend to your backend. This will help you become comfortable with the basic setup before moving on to more advanced features.
