NestJS Template
The NestJS template provides a modern Node.js backend framework with TypeScript, perfect for building scalable server-side applications with excellent developer experience.
Technical Stack
- NestJS - Node.js framework
- TypeScript - Type-safe development
- Express - Web framework
- Docker - Containerization
- MariaDB - Database
- Redis - Caching
- Jest - Testing framework
Quick Start
1. Create Project
bash
# Initialize project
vup init my-api-project
cd my-api-project
# Add NestJS template
vup add my-api2. Install Dependencies
bash
# Install dependencies
pnpm install3. Start Development
bash
# Start development server
cd apps/my-api
pnpm devThe API server will be available at http://localhost:9310.
Project Structure
apps/my-api/
├── src/
│ ├── app.controller.spec.ts # Controller unit test
│ ├── app.controller.ts # App controller
│ ├── app.module.ts # App module
│ ├── app.service.ts # App service
│ └── main.ts # Application entry point
├── test/
│ ├── app.e2e-spec.ts # E2E tests
│ └── jest-e2e.json # Jest E2E configuration
├── .env.example # Environment variables example
├── docker-compose.yml # Docker configuration
├── nest-cli.json # NestJS CLI configuration
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
└── README.md # Project documentationCore Features
Controller
typescript
// app.controller.ts
import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
@Get(':id')
findOne(@Param('id') id: string): string {
return this.appService.findOne(id);
}
@Post()
create(@Body() createDto: any): string {
return this.appService.create(createDto);
}
}Service
typescript
// app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
findOne(id: string): string {
return `Found item with id: ${id}`;
}
create(createDto: any): string {
return `Created item: ${JSON.stringify(createDto)}`;
}
}Module
typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}Main Application
typescript
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Enable CORS
app.enableCors();
// Set global prefix
app.setGlobalPrefix('api');
await app.listen(9310);
console.log('Application is running on: http://localhost:9310');
}
bootstrap();Development Tools
NestJS Configuration
json
// nest-cli.json
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"deleteOutDir": true
}
}TypeScript Configuration
json
// tsconfig.json
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"resolvePackageJsonExports": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "esnext",
"outDir": "./.output",
"incremental": true,
"strictNullChecks": true,
"noImplicitAny": false,
"strictBindCallApply": false,
"noFallthroughCasesInSwitch": false
}
}Docker Configuration
yaml
# docker-compose.yml
version: '3.8'
services:
api:
build: .
ports:
- '3000:3000'
environment:
- NODE_ENV=development
depends_on:
- mariadb
- redis
mariadb:
image: mariadb:10.9
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myapp
MYSQL_USER: user
MYSQL_PASSWORD: password
ports:
- '3306:3306'
volumes:
- mariadb_data:/var/lib/mysql
redis:
image: redis:7-alpine
ports:
- '6379:6379'
volumes:
- redis_data:/data
volumes:
mariadb_data:
redis_data:Available Scripts
json
{
"scripts": {
"dev": "nest start",
"dev:watch": "nest start --watch",
"build": "nest build",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\""
}
}Testing
Unit Tests
typescript
// app.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { AppService } from './app.service';
describe('AppService', () => {
let service: AppService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [AppService],
}).compile();
service = module.get<AppService>(AppService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should return "Hello World!"', () => {
expect(service.getHello()).toBe('Hello World!');
});
});E2E Tests
typescript
// test/app.e2e-spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!');
});
});Deployment
Build for Production
bash
cd apps/my-api
# Build the application
pnpm build
# The built files will be in the .output directoryDocker Deployment
bash
# Build Docker image
docker build -t my-api .
# Run with Docker Compose
docker-compose up -d