#4 — Bootstrapping: main.ts & AppModule
As a former 3D Animator with more than 12 years of experience, I have always been fascinated by the intersection of technology and creativity. That's why I recently shifted my career towards MERN stack development and software engineering, where I have been serving since 2021.
With my background in 3D animation, I bring a unique perspective to software development, combining creativity and technical expertise to build innovative and visually engaging applications. I have a passion for learning and staying up-to-date with the latest technologies and best practices, and I enjoy collaborating with cross-functional teams to solve complex problems and create seamless user experiences.
In my current role as a MERN stack developer, I have been responsible for developing and implementing web applications using MongoDB, Express, React, and Node.js. I have also gained experience in Agile development methodologies, version control with Git, and cloud-based deployment using platforms like Heroku and AWS.
I am committed to delivering high-quality work that meets the needs of both clients and end-users, and I am always seeking new challenges and opportunities to grow both personally and professionally.
1) Big Picture: How Nest boots
(main.ts) → (AppModule) → (Your Feature Modules)
main.tsbootstraps the application.It creates a Nest instance from
AppModule.AppModuleis the root module that imports your feature modules (Users, Posts, Auth, …).
2) Start the dev server
Use the built-in script (watch mode):
npm run start:dev
You’ll see logs like:
[Nest] xxxx - ... [InstanceLoader] AppModule dependencies initialized
[Nest] xxxx - ... Nest application successfully started
Open http://localhost:3000 to confirm.
Tip: If you see EADDRINUSE 3000, another process is using port 3000. Stop it or change the port (see §4).
3) main.ts: the bootstrap file
A default main.ts looks like this:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
What’s happening
NestFactory.create(AppModule)builds the application graph from the root module.app.listen(3000)starts the HTTP server (Express by default; Fastify if you configured it).
Changing the port
await app.listen(3300); // now it serves on :3300
Hot-reload will restart the server; open http://localhost:3300.
Peeking at the app object (for learning)
console.log(app); // a large object describing your app graph
⚠️ It’s huge; use sparingly. Later we’ll explore
app.get(...)to resolve providers.
4) AppModule: the root wiring hub
Open src/app.module.ts (or src/app/app.module.ts if you nest it). A minimal version:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [], // other modules go here
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Key idea: The @Module() decorator makes a class a Nest module — the filename is just a convention.
imports: other modules this module depends oncontrollers: HTTP route handlersproviders: injectable classes (services, guards, pipes, interceptors, repositories)exports: which providers to expose to other modules
Every feature module you create must eventually be added to some module’s
imports(oftenAppModuleinitially), or it won’t exist in the app graph.
5) Organizing files under src/app/
By default, the CLI puts app files directly under src/. Many teams prefer:
src/
app/
app.module.ts
app.controller.ts
app.service.ts
main.ts
If you move files into src/app/, fix the import in main.ts:
// from
import { AppModule } from './app.module';
// to
import { AppModule } from './app/app.module';
If the path is wrong, Nest will fail to start with an import error.
6) What do the generated files do?
app.controller.ts
Declares routes (e.g.,
GET /) using decorators like@Controller()and@Get().Delegates the actual work to a service.
app.service.ts
Holds business logic used by controllers.
Example returns
"Hello World!"(or your custom message).
app.controller.spec.ts
- Unit tests for the controller.
*.spec.tsis purely a naming convention; test frameworks pick them up by glob.
Separation of concerns: controller = I/O + routing; service = business logic. This pays off as the app grows.
7) v11 note: Express 5 by default
Nest v11 upgrades the default HTTP platform to Express 5 (performance & type improvements). Most apps will “just work”, but if you have custom middleware/types, re-check them after upgrading. Staying on v10 for learning is also fine.
8) Common hiccups & fixes
Port won’t open: another service is running → change port or stop the other process.
Module not found: incorrect path after moving files → fix the import in
main.ts.Feature not reachable: forgot to add your feature module to some module’s
imports.TS errors after upgrades: delete
node_modules+ lockfile and reinstall.
9) Hands‑on tasks (do these now)
Change the port to 3300, verify in the browser, then change back to 3000.
Create
src/app/and move app files there; fix theAppModuleimport inmain.ts.Edit
AppServiceto return"Hello from NestJS"and confirm it appears at/.(Stretch) Log
process.env.NODE_ENVinbootstrap()and pass it to your app viacross-env NODE_ENV=dev npm run start:dev.
10) Quick check (1‑minute quiz)
What two steps does
main.tsusually perform?Which part of a module lists other modules it depends on?
True/False: Naming a file
*.controller.tsautomatically makes it a controller.
Answers: create app from AppModule and listen(port); imports; False — the @Controller() decorator does.