Full-Stack Nest + Next.js Example
Great question! Hereβs how your NestJS backend would look compared to the FastAPI structure. NestJS follows a more Angular-inspired, decorator-based architecture:
π’ NestJS Backend Structure
backend/βββ src/β βββ main.ts # NestJS app entry pointβ βββ app.module.ts # Root moduleβ βββ app.controller.ts # Root controllerβ βββ app.service.ts # Root serviceβ βββ config/ # Configurationβ β βββ database.config.tsβ β βββ jwt.config.tsβ β βββ app.config.tsβ βββ modules/ # Feature modulesβ β βββ users/β β β βββ users.module.tsβ β β βββ users.controller.tsβ β β βββ users.service.tsβ β β βββ users.repository.tsβ β β βββ dto/β β β β βββ create-user.dto.tsβ β β β βββ update-user.dto.tsβ β β β βββ user-response.dto.tsβ β β βββ entities/β β β β βββ user.entity.tsβ β β βββ users.controller.spec.tsβ β βββ projects/β β β βββ projects.module.tsβ β β βββ projects.controller.tsβ β β βββ projects.service.tsβ β β βββ projects.repository.tsβ β β βββ dto/β β β β βββ create-project.dto.tsβ β β β βββ update-project.dto.tsβ β β β βββ project-response.dto.tsβ β β βββ entities/β β β β βββ project.entity.tsβ β β βββ projects.controller.spec.tsβ β βββ soq/β β β βββ soq.module.tsβ β β βββ soq.controller.tsβ β β βββ soq.service.tsβ β β βββ soq.repository.tsβ β β βββ dto/β β β β βββ create-soq.dto.tsβ β β β βββ update-soq.dto.tsβ β β β βββ soq-response.dto.tsβ β β βββ entities/β β β β βββ soq.entity.tsβ β β βββ soq.controller.spec.tsβ β βββ tenders/β β β βββ tenders.module.tsβ β β βββ tenders.controller.tsβ β β βββ tenders.service.tsβ β β βββ tenders.repository.tsβ β β βββ dto/β β β β βββ create-tender.dto.tsβ β β β βββ update-tender.dto.tsβ β β β βββ tender-response.dto.tsβ β β βββ entities/β β β β βββ tender.entity.tsβ β β βββ tenders.controller.spec.tsβ β βββ escrow/β β β βββ escrow.module.tsβ β β βββ escrow.controller.tsβ β β βββ escrow.service.tsβ β β βββ escrow.repository.tsβ β β βββ dto/β β β β βββ create-escrow.dto.tsβ β β β βββ update-escrow.dto.tsβ β β β βββ escrow-response.dto.tsβ β β βββ entities/β β β β βββ escrow.entity.tsβ β β βββ escrow.controller.spec.tsβ β βββ audit/β β βββ audit.module.tsβ β βββ audit.controller.tsβ β βββ audit.service.tsβ β βββ audit.repository.tsβ β βββ dto/β β β βββ create-audit.dto.tsβ β β βββ update-audit.dto.tsβ β β βββ audit-response.dto.tsβ β βββ entities/β β β βββ audit.entity.tsβ β βββ audit.controller.spec.tsβ βββ common/ # Shared utilitiesβ β βββ decorators/β β β βββ roles.decorator.tsβ β β βββ current-user.decorator.tsβ β βββ guards/β β β βββ jwt-auth.guard.tsβ β β βββ roles.guard.tsβ β βββ interceptors/β β β βββ transform.interceptor.tsβ β β βββ logging.interceptor.tsβ β βββ filters/β β β βββ http-exception.filter.tsβ β βββ pipes/β β β βββ validation.pipe.tsβ β βββ utils/β β βββ email.util.tsβ β βββ file-upload.util.tsβ β βββ validators.util.tsβ βββ database/ # Database configurationβ β βββ database.module.tsβ β βββ entities/β β β βββ user.entity.tsβ β β βββ project.entity.tsβ β β βββ soq.entity.tsβ β β βββ tender.entity.tsβ β β βββ escrow.entity.tsβ β β βββ audit.entity.tsβ β βββ migrations/β β βββ 001-create-users.tsβ β βββ 002-create-projects.tsβ β βββ 003-create-soq.tsβ β βββ 004-create-tenders.tsβ β βββ 005-create-escrow.tsβ β βββ 006-create-audit.tsβ βββ auth/ # Authentication moduleβ βββ auth.module.tsβ βββ auth.controller.tsβ βββ auth.service.tsβ βββ jwt.strategy.tsβ βββ local.strategy.tsβ βββ dto/β βββ login.dto.tsβ βββ register.dto.tsβββ test/ # E2E testsβ βββ app.e2e-spec.tsβ βββ users.e2e-spec.tsβ βββ projects.e2e-spec.tsβ βββ soq.e2e-spec.tsβ βββ tenders.e2e-spec.tsβ βββ escrow.e2e-spec.tsβ βββ audit.e2e-spec.tsβββ dist/ # Compiled outputβββ node_modules/βββ package.jsonβββ package-lock.jsonβββ tsconfig.jsonβββ tsconfig.build.jsonβββ nest-cli.jsonβββ .env.exampleβββ .gitignoreβββ Dockerfileβββ docker-compose.ymlβββ README.mdοΏ½οΏ½ Key Differences: FastAPI vs NestJS
| Aspect | FastAPI | NestJS |
|---|---|---|
| Language | Python | TypeScript/JavaScript |
| Architecture | Function-based | Class-based, decorators |
| Structure | Flat modules | Feature modules |
| Validation | Pydantic models | DTOs with class-validator |
| Database | SQLAlchemy | TypeORM/Prisma |
| Testing | pytest | Jest |
| Dependency Injection | Manual | Built-in DI container |
| Guards/Interceptors | Dependencies | Built-in decorators |
π Example: User Module in NestJS
src/modules/users/users.controller.ts
import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common';import { UsersService } from './users.service';import { CreateUserDto } from './dto/create-user.dto';import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';import { RolesGuard } from '../../common/guards/roles.guard';import { Roles } from '../../common/decorators/roles.decorator';
@Controller('users')@UseGuards(JwtAuthGuard, RolesGuard)export class UsersController { constructor(private readonly usersService: UsersService) {}
@Post() @Roles('admin') create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); }
@Get() @Roles('admin', 'manager') findAll() { return this.usersService.findAll(); }
@Get(':id') @Roles('admin', 'manager') findOne(@Param('id') id: string) { return this.usersService.findOne(id); }}src/modules/users/dto/create-user.dto.ts
import { IsEmail, IsString, IsEnum, IsOptional } from 'class-validator';
export class CreateUserDto { @IsString() name: string;
@IsEmail() email: string;
@IsString() phone: string;
@IsEnum(['Project Owner', 'In-House User', 'Bidder']) role: string;
@IsOptional() @IsString() entity?: string;
@IsOptional() @IsString() category?: string;}src/modules/users/entities/user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
@Entity('users')export class User { @PrimaryGeneratedColumn('uuid') id: string;
@Column() name: string;
@Column({ unique: true }) email: string;
@Column() phone: string;
@Column({ type: 'enum', enum: ['Project Owner', 'In-House User', 'Bidder'], default: 'Bidder' }) role: string;
@Column({ nullable: true }) entity: string;
@Column({ nullable: true }) category: string;
@CreateDateColumn() createdAt: Date;
@UpdateDateColumn() updatedAt: Date;}π NestJS Benefits for Your Project
- TypeScript First: Better type safety and IDE support
- Modular Architecture: Clean separation of concerns
- Built-in DI: Automatic dependency injection
- Decorators: Clean, readable API definitions
- Guards & Interceptors: Built-in middleware system
- Validation: Class-validator integration
- Testing: Jest integration out of the box
Would you like me to show you how to set up the NestJS equivalent of your current FastAPI structure?
1. File and Path Check
- File:
src/content/docs/instruction/nestjs+nextjs.md - Sidebar Slug:
instruction/nestjs+nextjs - Expected Path:
- The slug is always relative to the docs root (
src/content/docs/) - So,
instruction/nestjs+nextjsβsrc/content/docs/instruction/nestjs+nextjs.md
- The slug is always relative to the docs root (
You have this correct.
2. Case Sensitivity & Typos
- Make sure the filename is exactly
nestjs+nextjs.md(all lowercase, no spaces, no hidden characters). - Make sure the folder is exactly
instruction(all lowercase).
3. Sidebar Config
- Your config should be:
{ label: 'Full-Stack Nest + Next.js Example', slug: 'instruction/nestjs+nextjs' }
- No
.mdin the slug.
4. Astro/Content Caching
- Restart your Astro dev server after any file or config changes.
- If you use
pnpm,yarn, ornpm, try:(or the equivalent for your package manager)rm -rf .astrorm -rf node_modules/.vitenpm run dev
5. Check for Duplicate or Conflicting Files
- Make sure there is only one file named
nestjs+nextjs.mdin your entiresrc/content/docs/tree. - No uppercase variants, no
.mdxwith the same name.
6. Astro Version / Starlight Version
- If you recently upgraded Astro or Starlight, sometimes a full clean and reinstall helps:
rm -rf node_modulesrm package-lock.json # or yarn.lock or pnpm-lock.yamlnpm installnpm run dev
7. Check for Hidden Characters
- Sometimes, especially if the file was renamed in Finder or via copy-paste, there can be hidden characters.
- Run this in your project root to check:
Make sure the filename is exactlyls -l src/content/docs/instruction/
nestjs+nextjs.md.
8. Try Renaming the File
- Rename
nestjs+nextjs.mdtonestjs-nextjs.md - Update the sidebar slug to
instruction/nestjs-nextjs - Restart the dev server
Sometimes the + character can cause issues in some static site generators or their routing logic.
9. Check for .mdx Extension
- If you accidentally created
nestjs+nextjs.mdx, the slug would be different. Make sure the extension is.md.
10. Final: Minimal Sidebar Test
Try a minimal sidebar config with only this entry to isolate the problem:
sidebar: [ { label: 'Instruction', items: [ { label: 'Full-Stack Nest + Next.js Example', slug: 'instruction/nestjs+nextjs' } ] }]If this still fails, the issue is with file recognition, not config.
Summary of What to Try Next
- Rename
nestjs+nextjs.mdβnestjs-nextjs.md - Update sidebar slug to
instruction/nestjs-nextjs - Restart Astro dev server
- If it works, the
+was the problem.
Would you like me to automatically rename the file and update your config for you? This is the most likely fix!