kikita-create-nestjs-app 是做什麼的?
Bootstraps a new NestJS project and generates its AGENTS.md / .agents/ documentation tree so
any AI agent (Claude Code, Codex, etc.) working in the project afterwards has a complete,
self-maintaining source of truth.
0. Mode detection (always do this first)
Check for .agents/.kikita-scaffold.json in the target directory.
- Missing → fresh init. Continue with section 1 below, then
plan.md. - Present → this project was already scaffolded by this skill. Follow
update.mdinstead — do not re-run the questionnaire or re-scaffold.update.mdhandles pulling the latest template, diffing since the recorded commit, and merging changes into the project's (possibly customized).agents/files.
0.5 Preconditions (fresh init only)
- Confirm the working directory is empty or the user explicitly wants to init here.
- Never run this against a directory that already has an unrelated project without asking first.
1. Questionnaire (always ask before touching the filesystem)
Follow plan.md step by step from here. Do not skip the questionnaire. When done, run through
checklist.md before telling the user it's finished.
Ask in two stages, not as 12 questions dumped in one shot — the first answer decides which of the later questions are even relevant, so asking them all upfront means presenting a bot-only user with an "auth for your REST API" question that doesn't apply to them.
Stage 1 — the branching question, alone:
- Application type: REST API, bot, or both in the same app?
- If bot (or both): which platform? Telegram (
nestjs-telegraf) or Discord — and for Discord specifically,necordis the recommended default (least glue code to satisfy the generic event→handler→service pattern via native Nest DI/guards/pipes) but not mandatory: if the user wants rawdiscord.jsinstead (existing team expertise, adiscord.jsfeaturenecorddoesn't wrap yet), that's a legitimate choice — treat it the same as "another platform" below, adapting the generic pattern by hand instead of getting it for free. - Any other platform/library (name it — the generic bot transport pattern in
architecture/transport-adapter.mdadapts to it, but the concrete adapter code needs to be written by hand for anything outsidenestjs-telegraf/necord).
- If bot (or both): which platform? Telegram (
Stage 2 — everything else, batched (question 3 only asked if stage 1 answered REST or "both"; every other question below applies regardless of application type):
- Tests: none, or unit / e2e (Supertest) / both? "Both" also wires Testcontainers for integration tests that hit a real Postgres instance instead of mocks.
- Auth (skip entirely if stage 1 was bot-only): needed or not? A "yes" scaffolds one fixed
battle-tested pattern, not a menu — see
core/auth.md's scaffold block: short-lived access token (5–15 min, never in a cookie) + refresh token in an httpOnly cookie scoped to/auth/refresh+ rotation (single-use, hashed in DB) +csrf-csrfon the refresh endpoint +argon2idpassword hashing + aRolesGuard. Do not offer alternatives (sessions, bare JWT without rotation) — this is the one default. - Background jobs: BullMQ (Redis-backed queues) or not?
- Caching:
@nestjs/cache-manager+@keyv/redis(cache-aside) or not? Default recommendation is no — add it when there's a real performance need, not speculatively on every CRUD endpoint. - File uploads: needed or not? If yes, no further sub-question — the storage vendor (local disk in dev, any S3-compatible bucket in prod: AWS S3, MinIO, R2, Spaces) is an env variable, not a scaffold-time choice.
- Async messaging / inter-service events: needed or not? If yes, no broker sub-question
either — RabbitMQ is the fixed default (task queues, routing, DLQ cover the overwhelming
majority of cases).
architecture/messaging.mddocuments Kafka as a later migration path for event-streaming/replay/extreme-throughput needs, not a scaffold-time option. - i18n: does this project need multiple locales — translated REST error/validation
messages and/or bot replies in more than one language? If yes, no further sub-question —
nestjs-i18nis the fixed library; locale resolution differs by transport (REST:Accept-Languageheader; bot: the platform's own per-user locale field, neverAccept-Language) and both are covered incore/i18n.md. If no, skip — a project that will only ever run in one language doesn't need this. - JSDoc/TSDoc on public API: enforce mandatory doc comments on every exported symbol, or
skip it? Drives whether
.agents/agent-surface.mdis generated (recommended default: yes). - Git policy: may the agent commit and push without asking each time, or must every commit/push be confirmed?
- Package manager: npm, pnpm, or yarn? Default recommendation: pnpm.
- Git remote: does the user already have a repo URL to push to? If yes, record it —
git remote add origin <url>runs right aftergit init(seeplan.md). If no URL is given, skip this; the user wires the remote later themselves.
Record every answer — they drive both scaffolding and which doc files get generated. Never
silently assume a default beyond what's explicitly fixed above; if the user skips a question,
ask again for that one. This skill targets a single NestJS project, not a monorepo/Nx workspace
and not a distributed microservices topology (multiple deployable services/repos) — if the user
wants either, say this skill doesn't cover that and stop rather than improvising. A message
broker (see question 7) only wires a hybrid app (app.connectMicroservice() inside the same
single app) — it never spins up a second service.
Fixed defaults — never ask about these, they're locked by design:
- ORM/DB: Prisma + Postgres. No TypeORM (not recommended for new projects), no Drizzle (niche perf/edge pick), no NoSQL/MongoDB branch in v1 of this skill.
- Validation:
class-validator+class-transformeron the HTTP layer, globalValidationPipewired inmain.tsunconditionally withwhitelist,forbidNonWhitelisted,forbidUnknownValues, andtransformalltrue. Zod for env/config validation (@nestjs/config+validate), enforced by an ESLint rule blocking directprocess.envreads outside the schema file — seetesting-and-quality.md's "Mechanically Enforced Rules". Nested DTO fields require both@ValidateNested()and@Type(() => NestedDto)— seecode-style/dto-and-validation.md. DTO reuse viaPartialType/OmitType/PickTypeimported from@nestjs/swagger, never@nestjs/mapped-types— ESLint-blocked, not just documented (same section). - Response shape: a global
ClassSerializerInterceptor+@Exclude()on DTO fields is the one fixed serialization mechanism — never a raw Prisma entity returned, never a second serialization approach introduced without an ADR. - Swagger/OpenAPI: always wired for the REST branch.
- CORS: always configured in
main.tsvia an env-driven origin allowlist, never*. - API versioning: Nest URI Versioning (
/v1/...), fixed inarchitecture/transport-adapter.md. - Rate limiting:
@nestjs/throttleralways installed for REST and/or bot, IP-keyed for REST routes, user/chat-id-keyed for bot handlers — never skipped as "not needed yet". - Logging:
nestjs-pino, always — structured JSON logs, no plainLoggeroption offered. - Health checks:
@nestjs/terminus, always wired, not questionnaire-gated — two separate routes,GET /health/live(process-only, no external checks) andGET /health/ready(Prisma + any chosen Redis/RabbitMQ dependency), never merged into one. Seecore/health.md. - Graceful shutdown:
app.enableShutdownHooks()always called inmain.ts— without it, Prisma'sOnModuleDestroyconnection-close hook never fires on container restart. - Prisma error mapping: a global
PrismaExceptionFilter(APP_FILTER) mapsPrismaClientKnownRequestErrorcodes to the matching Nest HTTP exception — a Prisma error never surfaces as a bare unhandled 500. - Prisma client generation:
package.jsonalways gets"postinstall": "prisma generate"— the generated client is gitignored, so a fresh clone/CI needs this to compile at all. - docker-compose.yml: always generated (dev/test only, never referenced by prod deploy) — Postgres always present; Redis added only if BullMQ and/or caching was chosen (one shared instance for both); RabbitMQ added only if messaging was chosen.
2. Generate
Follow plan.md. Copy files from templates/ into the target project, including the dotfiles
(.gitignore, .gitattributes, .editorconfig, .prettierrc, .prettierignore, .nvmrc,
.vscode/extensions.json, .env.example, docker-compose.yml).
Two different things happen with questionnaire answers, don't conflate them:
- Text placeholders — find-and-replace every
{{TOKEN}}with the real value, leave none behind:{{PROJECT_NAME}},{{APP_TYPE}},{{BOT_PLATFORM}},{{TESTS}},{{GIT_POLICY}},{{PACKAGE_MANAGER}},{{NODE_VERSION}},{{DATE}}. - Inclusion gates — application type, bot platform, tests, auth, queue, cache, storage,
messaging, i18n, and mandatory-TSDoc answers don't fill a placeholder; they decide whether a
whole file (or a
<!-- SCAFFOLD -->-marked block inside one) is copied at all. A "no" answer means the file/block is deleted, not filled with an empty string. Gated files must still be linked fromAGENTS.md/ the relevant README when kept, and their links removed when skipped.
3. Verify
Run checklist.md in full before reporting success.
Notes on documentation structure (read once, then follow templates/ literally)
CLAUDE.mdis always a one-line stub pointing toAGENTS.md.AGENTS.mdis the mandatory entry point: a short "Must Read" list plus non-negotiable rules, at the project root..agents/README.mdis a flat index of everything under.agents/— keep it in sync whenever a conditional file (auth, queue, cache, storage, messaging, i18n, agent-surface) is added or skipped.- Topics that are genuinely one short doc stay flat in
.agents/*.md(workflow, git-policy, documentation, testing-and-quality, agent-surface, refactoring, progress). - Topics that fan out into several docs, or per-feature registries, get a subfolder with its own
README.mdhub:.agents/code-style/,.agents/architecture/,.agents/shared/,.agents/core/,.agents/decisions/. .agents/shared/README.mdregisterssrc/common/(framework-agnostic utilities — zero@nestjs/*imports — plus generic pipes/filters/interceptors/decorators)..agents/core/README.mdregisterssrc/core/app-wide singletons (auth, Prisma client provider, logger, queue, cache, storage, i18n — each with its own conditional doc file when that feature was chosen)..agents/decisions/README.mdexplains when a short ADR is required (layer direction, message broker migration, versioning strategy change) — always generated, starts with no ADR files.- All tracked file content — including TSDoc — is English only. No Cyrillic, no mojibake.
- All docs in
.agents/must read likekikita-create-angular-app's templates: imperative, short, example-backed, ending in a review/verification checklist.