Skip to content
Back to skills

Backend Scaffold

ASecurity

Generate production-ready backend code with routes, data models, service layers, and validation. Use when scaffolding backend from specs.

  • 57 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 17, 2026
developmenttypescriptpythongophpbashsqlnodeexpressdockertesting

Works with

  • claude code
  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 17, 2026

npx -y skills add diegosouzapw/awesome-omni-skill --skill backend-scaffold --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Backend Scaffold?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Backend Scaffold
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/diegosouzapw-backend-scaffold/badge)](https://www.skillsdirectory.com/skills/diegosouzapw-backend-scaffold)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: backend-scaffold
description: Generate production-ready backend code with routes, data models, service layers, and validation. Use when scaffolding backend from specs.
allowed-tools: Read, Glob, Grep, Write($JAAN_OUTPUTS_DIR/backend/scaffold/**), Task, WebSearch, AskUserQuestion, Edit(jaan-to/config/settings.yaml)
argument-hint: [backend-api-contract, backend-task-breakdown, backend-data-model]
license: MIT
compatibility: Designed for Claude Code with jaan-to plugin. Requires jaan-init setup.
---

# backend-scaffold

> Generate production-ready backend code scaffolds from upstream specs — multi-stack, tech.md-adaptive.

## Context Files

- `$JAAN_CONTEXT_DIR/tech.md` - Tech stack context (CRITICAL — determines framework, DB, patterns)
  - Uses sections: `#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 protocol

## Input

**Upstream Artifacts**: $ARGUMENTS

Accepts 1-3 file paths or descriptions:
- **backend-api-contract** — Path to OpenAPI YAML (from `/jaan-to:backend-api-contract` output: `api.yaml`)
- **backend-task-breakdown** — Path to BE task breakdown markdown (from `/jaan-to:backend-task-breakdown` output)
- **backend-data-model** — Path to data model markdown (from `/jaan-to:backend-data-model` output)
- **Empty** — Interactive wizard prompting for each

---

## Pre-Execution Protocol
**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 configuration

### Language Settings
Read 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.

---

# PHASE 1: Analysis (Read-Only)

## Thinking Mode

ultrathink

Use extended reasoning for:
- Analyzing upstream artifacts to derive code structure
- Mapping API contract schemas to framework-native patterns
- Planning multi-stack generation strategy
- Identifying edge cases in input parsing

## Step 1: Validate & Parse Inputs

For each provided path:
- **backend-api-contract**: Read api.yaml, extract paths, schemas, error responses, security schemes
- **backend-task-breakdown**: Read markdown, extract task list, entity names, reliability patterns
- **backend-data-model**: Read markdown, extract table definitions, constraints, indexes, relations
- Report which inputs found vs missing; suggest fallback for missing (e.g., CRUD from backend-data-model if no API contract)

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}
```

## Step 2: Detect Tech Stack

Read `$JAAN_CONTEXT_DIR/tech.md`:
- Extract framework from `#current-stack` (default: Fastify v5+)
- Extract DB from `#current-stack` (default: PostgreSQL)
- Extract patterns from `#patterns` (auth, error handling, logging)
- If tech.md missing: ask framework/DB via AskUserQuestion

## Step 3: Clarify Architecture

AskUserQuestion for items not in tech.md:
- Project structure (monolith / modular monolith / microservice)
- Auth middleware pattern (JWT / API key / session / none)
- Error handling depth (basic / full RFC 9457 with error taxonomy)
- Logging (structured JSON pino / winston / none)

## Step 4: Plan Scaffold Structure

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}
```

---

# HARD STOP — Review Scaffold Plan

Use AskUserQuestion:
- Question: "Proceed with generating the scaffold?"
- Header: "Generate"
- Options:
  - "Yes" — Generate the scaffold code
  - "No" — Cancel
  - "Edit" — Let me revise the scope or architecture first

**Do NOT proceed to Phase 2 without explicit approval.**

---

# PHASE 2: Generation (Write Phase)

## Phase 2 Output — Flat folder (no nested subfolder)

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).

## Step 6: Generate Content

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: `#current-stack`
- Frameworks: `#frameworks`
- Constraints: `#constraints`
- Patterns: `#patterns`

## Step 7: Quality Check

Validate generated output against checklist:
- [ ] All API endpoints from contract have route handlers
- [ ] All entities from data model have ORM models
- [ ] Validation schemas generated for all request bodies
- [ ] Error handler covers validation, ORM, and generic errors
- [ ] Service layer stubs exist for all business logic
- [ ] DB singleton + graceful disconnect configured
- [ ] No anti-patterns present in generated code

If any check fails, fix before preview.

## Step 8: Preview & Approval

Present generated output summary. Use AskUserQuestion:
- Question: "Write scaffold files to output?"
- Header: "Write Files"
- Options:
  - "Yes" — Write the files
  - "No" — Cancel
  - "Refine" — Make adjustments first

## Step 9: Generate ID and Folder Structure

```bash
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`

## Step 10: Write Output

1. Create output folder: `mkdir -p "$OUTPUT_FOLDER"`
2. Write all scaffold files to `$OUTPUT_FOLDER`
3. Update subdomain index:
```bash
source "${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}"
```

4. Confirm completion:
> Scaffold written to: `$JAAN_OUTPUTS_DIR/backend/scaffold/{NEXT_ID}-{slug}/`
> Index updated: `$JAAN_OUTPUTS_DIR/backend/scaffold/README.md`

## Step 11: Suggest Next Actions

> **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-plan` to plan integration with existing code
> - Run `/jaan-to:dev-test-plan` to generate test plan

## Step 12: Capture Feedback

Use AskUserQuestion:
- Question: "How did the scaffold turn out?"
- Header: "Feedback"
- Options:
  - "Perfect!" — Done
  - "Needs fixes" — What should I improve?
  - "Learn from this" — Capture a lesson for future runs

If "Learn from this": Run `/jaan-to:learn-add backend-scaffold "{feedback}"`

---

## Key Generation Rules — Node.js/TypeScript (Research-Informed)

- **Routing**: Use `@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 routes
- **Type Provider**: Use `fastify-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)
- **Prisma Singleton**: Use `globalThis` pattern to prevent connection pool exhaustion during hot-reload; conditional assignment based on `NODE_ENV`
- **Zod Schemas**: Define schemas in `.schema.ts` files, export `z.infer<>` types; derive from OpenAPI contract component schemas
- **Error Handler**: Use Fastify's `setErrorHandler` (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+json`
- **RFC 9457 Fields**: `type` (URI), `title`, `status`, `detail`, `instance`; extension `errors[]` for validation details
- **Service Layer**: Plain exported functions importing the Prisma singleton — module caching acts as built-in singleton, making DI containers (tsyringe, inversify) unnecessary; testable via `vi.mock()`; callable from CRON jobs or queue consumers outside HTTP context; use Prisma `$transaction` for cross-service operations
- **Route Structure**: Collocated `index.ts` (routes) + `{resource}.schema.ts` (Zod) + `{resource}.service.ts` (logic) per resource
- **TypeScript**: Extend `fastify-tsconfig` v2 with `target: "ES2023"`, `module: "NodeNext"`, `strict: true`
- **Import Extensions**: With `"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)
- **Env Vars**: Parameterize `DATABASE_URL`, `PORT`, `HOST`, `NODE_ENV`, `LOG_LEVEL`, `CORS_ORIGIN`
- **Env Validation**: Validate environment variables with Zod at startup — crash immediately on missing/invalid variables; use Node.js 20.6+ `--env-file=.env` flag for loading
- **Scripts**: `dev` (tsx watch), `build` (tsc), `start`, `lint`, `test`, `db:generate`, `db:migrate:dev`, `db:migrate:deploy`, `db:push`, `db:seed`, `db:studio`, `postinstall` (prisma generate)

## Multi-Stack Support (Research-Informed)

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:**
- PSR-4 autoloading, single `public/index.php` entry point
- Route model binding + Form Requests for validation (`$request->validated()`, never `$request->all()`)
- Eloquent Active Record with `utf8mb4`, BIGINT PKs, JSON columns
- **Strictness in `AppServiceProvider::boot()`**: `preventLazyLoading()` (catches N+1), `preventSilentlyDiscardingAttributes()` (catches mass assignment typos), `preventAccessingMissingAttributes()`; in production, lazy loading violations log instead of throwing
- API Resources for response shaping (never expose raw models); use `whenLoaded()`, `whenCounted()`, conditional `when()` helpers
- Sanctum for auth (SPA cookies + API tokens); cookie auth requires `SANCTUM_STATEFUL_DOMAINS` and `supports_credentials: true`
- Pest 3/4 for testing with architecture presets (`arch()->preset()->laravel()`) and mutation testing (`--mutate`)
- RFC 9457 via `crell/api-problem` v3.8.0 (PHP ^8.3)
- Zero-downtime MySQL migrations: expand-contract pattern (add nullable → backfill → deploy → drop old); use `daursu/laravel-zero-downtime-migration` for large tables

**PHP Stack (Symfony) — Key Patterns:**
- API Platform v4.x: `#[ApiResource]` annotations for automatic CRUD REST APIs with OpenAPI documentation
- Doctrine Data Mapper ORM: entities are POPOs, persistence via EntityManager (better separation than Active Record)
- DTOs with `#[MapRequestPayload]` and Symfony Validator constraint attributes (`#[Assert\NotBlank]`, `#[Assert\Positive]`)
- JWT via `lexik/jwt-authentication-bundle` v3.2.0 with RS256 signing + `gesdinet/jwt-refresh-token-bundle` for refresh tokens

**Go Stack — Generation Rules:**
- **Routing**: Go 1.22+ `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)
- **Structure**: Feature-based `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)
- **DI**: Constructor injection with small interfaces (1-3 methods) defined at consumer site; accept interfaces, return structs; wire manually in `main.go`; manual DI preferred over Wire/Dig except for very large projects
- **Database**: sqlc generates type-safe Go code from annotated SQL queries (`-- name: GetUser :one`); golang-migrate for sequential numbered up/down migration files
- **Validation**: go-playground/validator v10 (v10.27.0) with struct tags (`validate:"required,email"`); single instance (caches struct info); `WithRequiredStructEnabled()` for v11 compatibility; `RegisterTagNameFunc()` for JSON field names
- **OpenAPI**: oapi-codegen v2 generates Go types, server interfaces, and request validation middleware; developers implement `ServerInterface`; YAML config with Chi/stdlib backend support
- **Error Handling**: RFC 9457 via custom `ProblemDetail` struct; `Content-Type: application/problem+json`
- **Testing**: Table-driven tests with `httptest.NewRecorder()` + `httptest.NewRequest()`; `t.Run()` subtests; `t.Parallel()` for concurrent execution
- **Docker**: Multi-stage builds → 10-20MB images using `distroless/static-debian12`; `CGO_ENABLED=0` for static binaries; `-ldflags="-s -w"` to strip debug info
- **Graceful Shutdown**: `signal.NotifyContext` with 10-second timeout, closing HTTP server and database connections

**WebSocket Support (Optional — all stacks):**
- **Go**: coder/websocket, Hub pattern for connection management
- **Node.js**: ws / Socket.IO
- **PHP**: Ratchet / Swoole
- Auth: ephemeral single-use token via query parameter (`ws://host/ws?ticket=abc123`); 30-second TTL, consumed on first use to prevent log-exposure attacks
- SSE handles 95% of real-time use cases — suggest SSE first; SSE works over standard HTTP, supports auto-reconnection, multiplexed over HTTP/2

## Test Framework & Mutation Tool Recommendations

When 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."

## Anti-Patterns to NEVER Generate

**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

## Package Dependencies (Research-Validated)

**Node.js/TypeScript:**
- **Production**: `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.24
- **Dev**: `typescript` ^5.6, `@types/node` ^22, `fastify-tsconfig` ^2, `prisma` ^6, `tsx` ^4, `vitest` ^2, `eslint` ^9

**Go:** `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`

---

## Skill Alignment

- Two-phase workflow with HARD STOP for human approval
- Multi-stack support via `tech.md` detection
- Template-driven output structure
- Output to standardized `$JAAN_OUTPUTS_DIR` path

## Definition of Done

- [ ] All API endpoints from contract have route handlers
- [ ] All entities from data model have ORM models (Prisma/Eloquent/Doctrine/sqlc)
- [ ] Validation schemas generated for all request bodies
- [ ] Error handler covers validation errors, ORM errors, and generic errors
- [ ] Service layer stubs exist for all business logic
- [ ] DB singleton + graceful disconnect configured
- [ ] Setup README is complete and actionable
- [ ] Output follows v3.0.0 structure (ID, folder, index)
- [ ] Index updated with executive summary
- [ ] User approved final result

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.