Backend Init
What we’re building
Section titled “What we’re building”A NestJS application at apps/api, wired to read its port from the monorepo’s root .env through @nestjs/config, with every dependency the rest of the course needs already installed.
The Nest CLI (nest new) generates the module/controller/service structure, tsconfig.json, and test setup that every later lesson builds on — writing that boilerplate by hand buys nothing and risks a subtly different config than the one the rest of the course assumes. @nestjs/config centralizes environment access behind a typed ConfigService instead of scattering raw process.env reads through the codebase.
Pros & cons
Section titled “Pros & cons”nest new vs. a manual npm init. The CLI wires up ESLint, Jest, tsconfig.json, and the Nest-specific nest-cli.json in one step, and every scaffold looks the same — which matters when you’re following a course. The cost is that it also assumes a standalone project: by default it initializes its own git repo, which you don’t want inside a monorepo that already has its own git init at the root. --skip-git avoids a nested repository; --package-manager npm avoids an interactive prompt.
Installing dependencies as one group vs. as you need them. Installing everything now (GraphQL, Mongoose, auth, validation) means every later module’s npm install step is already done, and one package-lock.json is generated once. The trade-off is a longer initial install and a package.json that has GraphQL and auth dependencies before any resolver or guard exists yet — acceptable here because the course’s dependency list is fixed and known up front.
Set it up
Section titled “Set it up”Scaffold the API into apps/api, skipping a nested git repo since the monorepo root already has one:
cd devblognest new apps/api --package-manager npm --skip-gitcd apps/apinest new already added @nestjs/core, @nestjs/common, and @nestjs/platform-express to package.json — no need to install those again. Install the rest, grouped by what each group is for:
# env vars from the root .env, via ConfigServicenpm install @nestjs/config
# code-first GraphQL, served at /graphql by Apollo Servernpm install @nestjs/graphql @nestjs/apollo @apollo/server graphql
# MongoDB models and schemas via Mongoosenpm install @nestjs/mongoose mongoose
# JWT auth: Passport strategy, JWT signing/verification, password hashingnpm install @nestjs/passport passport passport-jwt @nestjs/jwt bcrypt
# DTO and GraphQL input validationnpm install class-validator class-transformer
# deterministic, URL-safe post slugsnpm install slugify
# type definitions for the auth packages abovenpm install -D @types/passport-jwt @types/bcryptUpdate src/app.module.ts to load the root .env globally:
import { Module } from '@nestjs/common';import { ConfigModule } from '@nestjs/config';import { AppController } from './app.controller';import { AppService } from './app.service';
@Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath: '../../.env', }), ], controllers: [AppController], providers: [AppService],})export class AppModule {}envFilePath is resolved relative to where the Nest process runs (apps/api), so ../../.env points at devblog/.env — the file Repo layout created. isGlobal: true means any later module can inject ConfigService without re-importing ConfigModule.
Update src/main.ts to listen on API_PORT instead of a hardcoded port:
import { NestFactory } from '@nestjs/core';import { ConfigService } from '@nestjs/config';import { AppModule } from './app.module';
async function bootstrap() { const app = await NestFactory.create(AppModule); const configService = app.get(ConfigService); const port = configService.get<number>('API_PORT') ?? 4000; await app.listen(port); console.log(`API listening on http://localhost:${port}`);}bootstrap();Start it in watch mode:
npm run start:devVerify
Section titled “Verify”The console should print the Nest bootstrap log ending with your custom line:
[Nest] ... LOG [NestApplication] Nest application successfully startedAPI listening on http://localhost:4000In another terminal:
curl http://localhost:4000# Hello World!Hello World! is the default response from the scaffolded AppController/AppService pair — seeing it confirms the app boots, ConfigService read API_PORT correctly (4000, from .env), and the HTTP server is reachable.
apps/api is a Nest CLI–scaffolded application with every course dependency installed up front, grouped by purpose: @nestjs/config for environment access, GraphQL/Apollo for the API layer, Mongoose for MongoDB, Passport/JWT/bcrypt for auth, class-validator/class-transformer for validation, and slugify for post slugs. main.ts now reads its port from the root .env via a typed ConfigService instead of a hardcoded number, and npm run start:dev confirms it boots on port 4000.
Next: Frontend init →