From jaan-to
Generates production-ready backend code scaffolds with routes, data models, service layers, and validation from OpenAPI specs, task breakdowns, and data models. Adapts to tech stack in tech.md.
npx claudepluginhub parhumm/jaan-to --plugin jaan-toThis skill is limited to using the following tools:
> Generate production-ready backend code scaffolds from upstream specs — multi-stack, tech.md-adaptive.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Generate production-ready backend code scaffolds from upstream specs — multi-stack, tech.md-adaptive.
$JAAN_CONTEXT_DIR/tech.md - Tech stack context (CRITICAL — determines framework, DB, patterns)
#current-stack, #frameworks, #constraints, #patterns$JAAN_CONTEXT_DIR/config.md - Project configuration$JAAN_TEMPLATES_DIR/jaan-to-backend-scaffold.template.md - Output template$JAAN_LEARN_DIR/jaan-to-backend-scaffold.learn.md - Past lessons (loaded in Pre-Execution)${CLAUDE_PLUGIN_ROOT}/docs/extending/language-protocol.md - Language resolution protocolUpstream Artifacts: $ARGUMENTS
Accepts 1-3 file paths or descriptions:
/jaan-to:backend-api-contract output: api.yaml)/jaan-to:backend-task-breakdown output)/jaan-to:backend-data-model output)MANDATORY — Read and execute ALL steps in: ${CLAUDE_PLUGIN_ROOT}/docs/extending/pre-execution-protocol.md
Skill name: backend-scaffold
Execute: Step 0 (Init Guard) → A (Load Lessons) → B (Resolve Template) → C (Offer Template Seeding)
Also read context files if available:
$JAAN_CONTEXT_DIR/tech.md — Know the tech stack for framework-specific code generation$JAAN_CONTEXT_DIR/config.md — Project configurationRead and apply language protocol: ${CLAUDE_PLUGIN_ROOT}/docs/extending/language-protocol.md
Override field for this skill: language_backend-scaffold
Language exception: Generated code output (variable names, code blocks, schemas, SQL, API specs) is NOT affected by this setting and remains in the project's programming language.
ultrathink
Use extended reasoning for:
For each provided path:
Present input summary:
INPUT SUMMARY
─────────────
Sources Found: {list}
Sources Missing: {list with fallback suggestions}
Entities: {extracted entity names}
Endpoints: {count from API contract}
Tables: {count from data model}
Tasks: {count from task breakdown}
Read $JAAN_CONTEXT_DIR/tech.md:
#current-stack (default: Fastify v5+)#current-stack (default: PostgreSQL)#patterns (auth, error handling, logging)AskUserQuestion for items not in tech.md:
Present directory tree, file list, resource count:
SCAFFOLD PLAN
═════════════
STACK: {framework} + {database} + {orm}
PROJECT STRUCTURE
─────────────────
{directory tree showing all files to generate}
FILES ({count} total)
─────────────────────
{numbered list with file purpose}
RESOURCES ({count})
───────────────────
{resource list with operations}
Use AskUserQuestion:
Do NOT proceed to Phase 2 without explicit approval.
All files in $JAAN_OUTPUTS_DIR/backend/scaffold/{id}-{slug}/:
{id}-{slug}/
├── {id}-{slug}.md # Main doc (setup guide + architecture)
├── {id}-{slug}-routes.ts # Route handlers (all resources)
├── {id}-{slug}-services.ts # Service layer (business logic)
├── {id}-{slug}-schemas.ts # Validation schemas
├── {id}-{slug}-middleware.ts # Auth + error handling middleware
├── {id}-{slug}-prisma.prisma # ORM data model
├── {id}-{slug}-config.ts # Package.json + tsconfig content
└── {id}-{slug}-readme.md # Setup + run instructions
File extensions adapt to detected stack (.ts for Node.js, .php for PHP, .go for Go).
Read $JAAN_TEMPLATES_DIR/jaan-to-backend-scaffold.template.md and populate all sections based on Phase 1 analysis.
If tech stack needed, extract sections from tech.md:
#current-stack#frameworks#constraints#patternsValidate generated output against checklist:
If any check fails, fix before preview.
Present generated output summary. Use AskUserQuestion:
source "${CLAUDE_PLUGIN_ROOT}/scripts/lib/id-generator.sh"
SUBDOMAIN_DIR="$JAAN_OUTPUTS_DIR/backend/scaffold"
mkdir -p "$SUBDOMAIN_DIR"
NEXT_ID=$(generate_next_id "$SUBDOMAIN_DIR")
slug="{project-name-slug}"
OUTPUT_FOLDER="${SUBDOMAIN_DIR}/${NEXT_ID}-${slug}"
Preview output configuration:
Output Configuration
- ID: {NEXT_ID}
- Folder:
$JAAN_OUTPUTS_DIR/backend/scaffold/{NEXT_ID}-{slug}/- Main file:
{NEXT_ID}-{slug}.md
mkdir -p "$OUTPUT_FOLDER"$OUTPUT_FOLDERsource "${CLAUDE_PLUGIN_ROOT}/scripts/lib/index-updater.sh"
add_to_index \
"$SUBDOMAIN_DIR/README.md" \
"$NEXT_ID" \
"${NEXT_ID}-${slug}" \
"{Project Title}" \
"{Executive summary — 1-2 sentences}"
Scaffold written to:
$JAAN_OUTPUTS_DIR/backend/scaffold/{NEXT_ID}-{slug}/Index updated:$JAAN_OUTPUTS_DIR/backend/scaffold/README.md
Scaffold generated successfully!
Next Steps:
- Copy scaffold files to your project directory
- Run
npm install(or equivalent) to install dependencies- Run
/jaan-to:dev-integration-planto plan integration with existing code- Run
/jaan-to:dev-test-planto generate test plan
Use AskUserQuestion:
If "Learn from this": Run /jaan-to:learn-add backend-scaffold "{feedback}"
@fastify/autoload v6 for file-based route loading — register twice (plugins with encapsulate: false, routes encapsulated per resource); add ignorePattern: /.*\.(?:schema|service)\.ts/ to prevent non-plugin files from being auto-loaded as routesfastify-type-provider-zod v6.1+ with validatorCompiler/serializerCompiler set once at app level; must call withTypeProvider<ZodTypeProvider>() on each encapsulated context (type providers don't propagate across encapsulation boundaries)globalThis pattern to prevent connection pool exhaustion during hot-reload; conditional assignment based on NODE_ENV.schema.ts files, export z.infer<> types; derive from OpenAPI contract component schemassetErrorHandler (NOT Express-style middleware) — use hasZodFastifySchemaValidationErrors(error) for 400 (NOT instanceof ZodError which fails across module boundaries), use isResponseSerializationError(error) for 500 serialization errors; map PrismaClientKnownRequestError P2002 → 409 (unique constraint), P2003 → 409 (foreign key), P2025 → 404 (not found), all others → 500; always set Content-Type: application/problem+jsontype (URI), title, status, detail, instance; extension errors[] for validation detailsvi.mock(); callable from CRON jobs or queue consumers outside HTTP context; use Prisma $transaction for cross-service operationsindex.ts (routes) + {resource}.schema.ts (Zod) + {resource}.service.ts (logic) per resourcefastify-tsconfig v2 with target: "ES2023", module: "NodeNext", strict: true"type": "module" and moduleResolution: "NodeNext", all imports MUST include .js extensions — NodeNext mirrors Node.js runtime behavior; never use moduleResolution: "bundler" for backends (allows vague imports that fail at runtime)DATABASE_URL, PORT, HOST, NODE_ENV, LOG_LEVEL, CORS_ORIGIN--env-file=.env flag for loadingdev (tsx watch), build (tsc), start, lint, test, db:generate, db:migrate:dev, db:migrate:deploy, db:push, db:seed, db:studio, postinstall (prisma generate)The skill reads tech.md #current-stack to determine which stack to generate:
| tech.md value | Framework | ORM/DB | Validation | Output |
|---|---|---|---|---|
| Node.js / TypeScript | Fastify v5+ | Prisma | Zod + type-provider v6.1 | .ts files |
| PHP | Laravel 12 / Symfony 7 | Eloquent / Doctrine | Form Requests / Symfony Validator | .php files |
| Go | Chi / stdlib (Go 1.22+) | sqlc / GORM | go-playground/validator | .go files |
PHP Stack (Laravel) — Key Patterns:
public/index.php entry point$request->validated(), never $request->all())utf8mb4, BIGINT PKs, JSON columnsAppServiceProvider::boot(): preventLazyLoading() (catches N+1), preventSilentlyDiscardingAttributes() (catches mass assignment typos), preventAccessingMissingAttributes(); in production, lazy loading violations log instead of throwingwhenLoaded(), whenCounted(), conditional when() helpersSANCTUM_STATEFUL_DOMAINS and supports_credentials: truearch()->preset()->laravel()) and mutation testing (--mutate)crell/api-problem v3.8.0 (PHP ^8.3)daursu/laravel-zero-downtime-migration for large tablesPHP Stack (Symfony) — Key Patterns:
#[ApiResource] annotations for automatic CRUD REST APIs with OpenAPI documentation#[MapRequestPayload] and Symfony Validator constraint attributes (#[Assert\NotBlank], #[Assert\Positive])lexik/jwt-authentication-bundle v3.2.0 with RS256 signing + gesdinet/jwt-refresh-token-bundle for refresh tokensGo Stack — Generation Rules:
net/http.ServeMux with method+wildcard patterns (GET /users/{id}, r.PathValue("id")); use Chi v5.2.x only for middleware grouping/subrouters; avoid gorilla/mux (archived 2023), Gin/Fiber (diverge from net/http idioms)internal/ packages (internal/user/handler.go, service.go, repository.go); avoid layer-based internal/handlers/ anti-pattern (excessive cross-package imports); shallow hierarchies (1-2 levels)main.go; manual DI preferred over Wire/Dig except for very large projects-- name: GetUser :one); golang-migrate for sequential numbered up/down migration filesvalidate:"required,email"); single instance (caches struct info); WithRequiredStructEnabled() for v11 compatibility; RegisterTagNameFunc() for JSON field namesServerInterface; YAML config with Chi/stdlib backend supportProblemDetail struct; Content-Type: application/problem+jsonhttptest.NewRecorder() + httptest.NewRequest(); t.Run() subtests; t.Parallel() for concurrent executiondistroless/static-debian12; CGO_ENABLED=0 for static binaries; -ldflags="-s -w" to strip debug infosignal.NotifyContext with 10-second timeout, closing HTTP server and database connectionsWebSocket Support (Optional — all stacks):
ws://host/ws?ticket=abc123); 30-second TTL, consumed on first use to prevent log-exposure attacksWhen generating scaffold, include test framework and mutation tool recommendations based on detected stack:
| Stack | Test Framework | Mutation Tool | Config File |
|---|---|---|---|
| Node.js/TS | Vitest | StrykerJS | stryker.config.mjs |
| PHP/Laravel | Pest | Infection | infection.json5 |
| Go | testing + testify | go-mutesting | CLI flags |
| Python | pytest | mutmut | setup.cfg |
Add to generated README: "Run /jaan-to:qa-test-mutate to validate test suite effectiveness."
All Stacks: Business logic in route handlers, hardcoded secrets, missing .gitignore, no error handling
Node.js: Direct Prisma calls in handlers, multiple PrismaClient instances, any types, Express-style error middleware, missing response serialization schemas, instanceof ZodError (use v6 helpers), missing .js extensions in ESM imports, moduleResolution: "bundler" for backends
PHP: Fat controllers, N+1 queries, exposing raw Eloquent models, env() outside config files, utf8 instead of utf8mb4, missing Eloquent strictness modes
Go: Generic package names (utils/), global database connections, ignoring errors, unlimited connection pool, goroutine leaks, layer-based internal/handlers/ structure
Node.js/TypeScript:
fastify ^5.7, @fastify/autoload ^6, @fastify/cors ^10, @fastify/sensible ^6, @fastify/swagger ^9, @fastify/swagger-ui ^5, @prisma/client ^6, fastify-plugin ^5, fastify-type-provider-zod ^6.1, zod ^3.24typescript ^5.6, @types/node ^22, fastify-tsconfig ^2, prisma ^6, tsx ^4, vitest ^2, eslint ^9Go: chi v5.2.x (optional), go-playground/validator v10, golang-migrate, sqlc, oapi-codegen v2
PHP (Laravel): laravel/sanctum, crell/api-problem ^3.8, pestphp/pest ^3
PHP (Symfony): api-platform/core ^4, lexik/jwt-authentication-bundle ^3.2, gesdinet/jwt-refresh-token-bundle
tech.md detection$JAAN_OUTPUTS_DIR path