Use this skill when working in apps/api to follow NestJS, GraphQL, Prisma, auth, and testing conventions.
Read the root SKILL.md first for repository-wide Git, PR, and language rules. This file covers conventions specific to apps/api.
| Layer | Technology |
|---|---|
| Framework | NestJS 11 |
| Language | TypeScript strict |
| GraphQL | Apollo Server 5, @nestjs/graphql (code-first) |
| ORM | Prisma 5 |
| Database | PostgreSQL 16 |
| Auth | Passport.js, @nestjs/jwt, bcryptjs |
| Testing | Jest, Supertest |
apps/api/src/
├── app.module.ts # Root module — imports all feature modules
├── main.ts # Bootstrap — sets up Apollo, Express, CORS
├── schema.gql # Auto-generated GraphQL schema (NEVER edit by hand)
├── auth/
│ ├── auth.module.ts
│ ├── auth.resolver.ts
│ ├── auth.service.ts
│ ├── jwt.strategy.ts
│ ├── jwt-auth.guard.ts
│ └── dto/
├── tasks/
│ ├── tasks.module.ts
│ ├── tasks.resolver.ts
│ ├── tasks.service.ts
│ └── dto/
├── users/
│ ├── users.module.ts
│ └── users.resolver.ts
├── prisma/
│ └── prisma.module.ts # PrismaService provider
└── common/
└── decorators/ # @CurrentUser and other shared decorators
Each feature follows the same pattern:
*.module.ts — imports and exports, declares providers.*.resolver.ts — GraphQL queries and mutations; delegates to service.*.service.ts — business logic, database access via PrismaService.dto/ — input types decorated with @InputType() and class-validator decorators.Rules:
PrismaClient directly in resolvers; always go through PrismaService.@ObjectType(), @Field(), @InputType(), @Args(), @Query(), @Mutation() decorators.schema.gql is auto-generated by NestJS on startup — never edit it by hand.@UseGuards(JwtAuthGuard) on any query or mutation requiring authentication.@CurrentUser() decorator to access the authenticated user in resolver methods.@ObjectType() response types; avoid returning raw Prisma models.yarn workspace @taskhub/api db:migrate.prisma/schema.prisma and create a migration.yarn workspace @taskhub/api db:generate after schema changes to regenerate the Prisma client.prisma/seed.ts for development seed data; keep seeds idempotent.PrismaService (injected via NestJS DI), not the raw PrismaClient import.directUrl for direct database connections (bypasses connection pooling for migrations).Database models:
User — id, name, email (unique), password (bcrypt), role (USER|ADMIN), timestamps
Task — id, title, description, status (TODO|IN_PROGRESS|DONE), priority (LOW|MEDIUM|HIGH),
deadline, userId (FK → User), timestamps
jwt.strategy.ts) extracts the token from the Authorization: Bearer header.JwtAuthGuard wraps Passport JWT; apply it at resolver or method level.JWT_SECRET environment variable; never hard-code it.{ sub: userId, email }.Run before every commit:
yarn workspace @taskhub/api lint
yarn workspace @taskhub/api test
Run when changing Prisma schema:
yarn workspace @taskhub/api db:generate
yarn workspace @taskhub/api db:migrate
Full build check:
yarn workspace @taskhub/api build
test/ at the app root for e2e tests.@nestjs/testing to create isolated module contexts.PrismaService in unit tests; do not hit a real database in unit tests.test/ use Supertest against a real NestJS app; run against a test database when available.*.spec.ts for unit tests, *.e2e-spec.ts for e2e tests.| Variable | Purpose |
|---|---|
DATABASE_URL | Prisma connection string (via pooler) |
DIRECT_URL | Direct database connection (migrations, introspection) |
JWT_SECRET | HS256 signing secret; must match the web app |
.env locally (git-ignored)..env or secrets..env.example to document required variables without values.common/ utilities.HttpException / NestJS built-in exceptions; never throw raw Error from resolvers.If a task reveals a better convention, recurring mistake, or useful reminder specific to this API, update this SKILL.md in the same PR. Keep updates concise and actionable.