From nja
Use when creating, scaffolding, or generating a new feature module or entity in a nestjs-neo4jsonapi + nextjs-jsonapi monorepo — backend (NestJS), frontend (Next.js), or both. Triggers include "create a new module", "scaffold an entity", "generate the backend/frontend for X", "add a feature module", or building a new feature that needs CRUD code.
How this skill is triggered — by the user, by Claude, or both
Slash command
/nja:nja-generateThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
nestjs-neo4jsonapi and nextjs-jsonapi ship two purpose-built code generators that scaffold a complete module from a single JSON "module shape". **Always use the generators — never hand-write the entity / DTO / repository / service / controller / model / component files.** Hand-written modules drift from the live templates and violate the architecture.
nestjs-neo4jsonapi and nextjs-jsonapi ship two purpose-built code generators that scaffold a complete module from a single JSON "module shape". Always use the generators — never hand-write the entity / DTO / repository / service / controller / model / component files. Hand-written modules drift from the live templates and violate the architecture.
pnpm generate-module <json>pnpm generate-web-module <json>Both read the same JSON schema (an array of module definitions). Your job is to turn a module description into a correct JSON schema, run the generators, and complete the handful of manual steps the generators can't do (chiefly the ModuleId enum).
Placeholders: this skill uses
<api-app>/<web-app>for the workspace package names of your NestJS API and Next.js web apps (the values you pass topnpm --filter), and@<scope>/sharedfor your shared-types package. Substitute your repo's actual names before running any command.
When NOT to use: editing an existing module's bespoke logic (custom editors, business methods) — the generators only scaffold standard CRUD; refine by hand afterward.
Run from the monorepo root. REQUIRED REFERENCE: read references/schema-reference.md before authoring the JSON, and references/post-generation.md before/after generating.
Decide scope — backend, frontend, or both (default both).
Check for name/endpoint collisions FIRST. A clash silently overwrites or duplicates existing code. Grep for the proposed moduleName, endpointName, and page route:
grep -rn "<Module>Module\|\"<plural>\"\|/<plural>\b" apps/web/src/config/Bootstrapper.ts apps/web/src/app packages/shared/src/const/module.id.ts apps/api/src/features/*/*.modules.ts
If taken (e.g. "Supplier" is already an Account role-view), pick a different name/endpoint or resolve the collision with the user before proceeding.
Gather the module shape. From the user's description; if invoked autonomously and details are missing, ask targeted questions. You need: domain (targetDir), fields (name, type, nullable, optional description/kind), relationships (target entity, its directory, cardinality, Neo4j edge name, direction, optional edge fields / alias / dtoKey). See references/schema-reference.md for every field and how to infer it.
Author the structure JSON in a single-module file structure/<module-kebab>.json (a one-element array). Two reasons it must be its own file in structure/:
*.json in that directory to resolve cross-module relationship selectors, so it MUST live in structure/.Files already exist. Use --force) on the first already-generated module in a multi-module array — so do NOT generate from the shared structure/<domain>.json (it would abort on existing siblings, and --force would overwrite/regenerate them, discarding hand edits). A single-module file processes only the new module.Mint a fresh UUID for moduleId. Verify each relationship's target name/directory against the live entity (its *.meta.ts and ModuleId key), not a possibly-stale structure file.
Build the generators if stale (they run from dist/):
pnpm --filter @carlonicora/nestjs-neo4jsonapi build
pnpm --filter @carlonicora/nextjs-jsonapi build
Dry-run to preview the file list (writes nothing):
pnpm generate-module structure/<module-kebab>.json --dry-run
pnpm generate-web-module structure/<module-kebab>.json --dry-run
Confirm with the user — show the authored shape and the dry-run file list before any real write.
Generate (real write + auto-registration). Add --force only when intentionally re-scaffolding (it overwrites and discards hand edits); add --no-register to skip editing the parent modules file / Bootstrapper.ts / i18n.
pnpm generate-module structure/<module-kebab>.json
pnpm generate-web-module structure/<module-kebab>.json
Complete the manual steps in references/post-generation.md — most importantly add <Module>: "<same-uuid>" to packages/shared/src/const/module.id.ts (the build fails without it), then the Neo4j module-node seed, RBAC paths, and it.json i18n.
Verify. Run pnpm lint and pnpm build (full monorepo). Then invoke the nja-architecture skill to audit the generated code, and flag the bespoke parts the generator only scaffolds (custom business logic, custom editor pickers).
| What | Command / location |
|---|---|
| Backend generator | pnpm generate-module structure/<module-kebab>.json [--dry-run] [--force] [--no-register] |
| Frontend generator | pnpm generate-web-module structure/<module-kebab>.json [--dry-run] [--force] [--no-register] |
| Input JSON | structure/<module-kebab>.json — single-module array, lives in structure/ |
| ModuleId enum (manual) | packages/shared/src/const/module.id.ts — moduleId UUID must match |
| Module-node seed (manual) | apps/api/src/neo4j.migrations/20250901_005.ts |
| RBAC paths | pnpm --filter <api-app> generate:rbac-paths |
ModuleId entry → ModuleId.<Module> is undefined → backend build fails. Always do step 9 first.structure/<domain>.json → backend errors Files already exist on existing siblings. Use a single-module structure/<module-kebab>.json.structure/ → frontend relationship selectors resolve wrong (the generator can't see sibling modules).required: true → the key is ignored; use nullable: false/true instead.Item vs the live CatalogItem; verify against the entity's *.meta.ts and ModuleId.kind: { "type": "money" } expecting frontend money UI → it's a backend hint only; money formatting is manual.languages: ["en"] only → Italian (it.json) is left empty; add "it" or translate manually.npx claudepluginhub carlonicora/nja --plugin njaCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.