agentleFS
LongJohnSilver1504LongJohnSilver1504/claude-skills/skills/create-feature/SKILL.md

create-feature

Skill1 starsChanged 58 days agoMITView on GitHub

Scaffold a NEW domain feature module following vertical slicing and hexagonal architecture (DTO+mapper API boundary, query keys, hooks, pure-renderer components). Use when the user wants to create, add, implement, or scaffold a new feature with entities, API endpoints, and CRUD operations ("create a feature", "new module", "scaffold X"). NOT for extending or refactoring a feature that already exists (modify-feature), shared plumbing like providers/layouts/i18n (create-infrastructure), or dev-only debug panels (create-devtool).

7 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

5 rules. 0 are common, 5 are distinctive, and 0 are very specific to this project.

  • 0

    Common

    Most of the 5 edited versions we read keep these.

  • 5

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Related: create-infrastructure (shared infra), plan-implementation (upstream planning), react-clean-architecture (architecture rationale), …

    line 13
  2. Distinctive:

    When a feature serves multiple routes that share the same types, API, and query keys, use nested sub-features.

    line 88
  3. Distinctive:

    Sub-features never import from each other: If A needs something from B, it belongs in the shared parent level.

    line 116
  4. Distinctive:

    Ask: "Does this feature serve multiple routes/pages that share the same data model and API?" If yes, use sub-features.

    line 121
  5. Distinctive:

    Only when all three are met: (1) it has its own API endpoints and response types, (2) its own query keys and data lifecycle, (3) it can be …

    line 125

“Common” is measured: kept by at least 6 in 10 of the 5 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Project config: {app} is the project's new-code root from .claude/rules/project-structure.md; project values (package manager, commands, base branch, error surface) come from docs/agents/project-conventions.md. Resolve both before writing any file — never assume. If a needed file is missing, stop: "Run /setup-daher-skills first — missing <file>."

Create Feature

Scaffold a complete domain feature module following vertical slicing with hexagonal architecture. This skill handles features with entities, API endpoints, and CRUD operations that live under the features root defined in .claude/rules/project-structure.md.

For shared infrastructure (providers, hooks, layouts, i18n, config), use create-infrastructure instead.

Related: create-infrastructure (shared infra), plan-implementation (upstream planning), react-clean-architecture (architecture rationale), frontend-testing (post-scaffold tests), generate-feature-doc (post-implementation docs).

Conventions live in the project's .claude/rules/ — this skill carries only the scaffold order, file map, and templates. Read the relevant rule before writing each layer:

LayerRule file
Where code lives, import directionproject-structure.md
Wire DTOs, mappers, domain-type ownershipapi-boundary.md
API adapters, AppError, handleApiError, parseResponseerror-handling.md
Query keys, useQuery/useMutation, invalidationtanstack-query.md
Forms (zodResolver + Controller + Field)form-patterns.md
Component/hook separation, translate-in-hookscomponent-hook-separation.md
Routes and endpoint constantscentralized-links.md
Colors (semantic tokens only)color-usage.md
Page layout / AppContainerlayout-ownership.md
Zustand storeszustand-patterns.md
Teststesting.md

Small deltas not covered by the rules are listed in references/shared-conventions.md.

Living example: the most complete feature already merged in the project — read its api/, domain/, queries/, hooks/, and sub-feature directories when a template leaves you unsure. Exception: if it predates the API-boundary rule (it re-exports schema types as domain), follow api-boundary.md and this skill's templates for dto/mapper structure; it stays the reference for adapter/error/query mechanics.

Why the DTO + Mapper Boundary

The api/ layer is an Anti-Corruption Layer (DDD), implemented as DTO + Mapper following "parse, don't validate": the wire format is validated once (parseResponse(dtoSchema, ...)), mapped once (toX(dto) / buildXBody(input)), and the rest of the app only ever sees hand-authored domain types. Full rule: .claude/rules/api-boundary.md — this skill carries only the scaffold order and templates.

Before You Begin

Gather from the user:

  1. Feature name (singular, lowercase): e.g., payment, invoice, reservation
  2. Main entity fields: Properties of the domain model
  3. API endpoints: Endpoints this feature will consume — validate response shapes against the real API, never trust legacy types
  4. Operations needed: List (paginated?), detail, create, update, delete?

Feature Directory Structure

Simple Feature (single page/concern)

Create in {features-root}/{feature-name}/:

{feature-name}/
├── api/
│   ├── {feature}.dto.ts          # Zod wire schemas (strict by default) — ONLY file that knows the backend shape
│   ├── {feature}.mapper.ts       # toX(dto) / buildXBody(input) — pure mapping functions
│   └── {feature}.api.ts          # HTTP adapter (endpoints const + .catch(handleApiError) + parseResponse → mapper)
├── domain/
│   ├── {feature}.types.ts        # Hand-authored domain types (frontend-owned — never re-export DTO infers)
│   ├── {feature}.service.ts      # Pure business logic functions
│   └── {feature}.errors.ts       # Domain error classes (optional)
├── queries/
│   └── {feature}.keys.ts         # Query key factory
├── store/                         # Only if feature needs UI state
│   └── {feature}.store.ts        # Zustand store (filters, selection, dialogs)
├── hooks/                        # ALL logic lives here
│   ├── use-{feature}s-query.ts   # Thin useQuery wrappers
│   ├── use-{feature}-list.ts     # Component hook (data + translated strings)
│   ├── use-{feature}-mutations.ts # CRUD mutation hooks
│   └── use-{feature}-form.ts     # Form hook (useForm + submit + navigation)
├── components/                   # Pure renderers ONLY
│   ├── {feature}-list.tsx
│   ├── {feature}-card.tsx
│   └── {feature}-form.tsx
├── pages/                        # Page compositors (wrap content in AppContainer)
│   └── {feature}s-page.tsx
├── testing/                      # Test factories + MSW handlers
│   └── factories.ts
└── index.ts                       # Public exports

Translations do NOT live inside the feature — they go in public/locales/{locale}/{namespace}.json (one file per locale per namespace).

Feature with Sub-Features (multiple sub-pages sharing same data model)

When a feature serves multiple routes that share the same types, API, and query keys, use nested sub-features. Each sub-feature is self-contained with its own components and hooks.

{feature-name}/
├── api/                          # Shared across all sub-features
├── domain/                       # Shared types + business logic
├── queries/                      # Shared query key factories
├── hooks/                        # Shared hooks (data fetching, common logic)
├── testing/                      # Shared test factories
├── pages/                        # Page compositors (one per route)
│
├── {sub-feature-a}/              # Self-contained sub-feature
│   ├── components/
│   ├── hooks/
│   └── domain/                   # Only if sub-feature has local-only logic
│
├── {sub-feature-b}/
│   ├── components/
│   └── hooks/
│
└── index.ts                      # Public barrel exports

Sub-Feature Rules

  1. Shared things stay shared. Types, API adapters, and query keys used by multiple sub-features live at the parent feature root (api/, domain/, queries/, hooks/).
  2. Local logic stays local. Logic used only by one sub-feature goes in {sub-feature}/domain/.
  3. Pages are thin compositors. Each page in pages/ imports and assembles components from sub-features. Pages never own business logic.
  4. Sub-features never import from each other. If A needs something from B, it belongs in the shared parent level.
  5. Pages can import from any sibling sub-feature. They are the only cross-cutting layer.

When to Use Sub-Features

Ask: "Does this feature serve multiple routes/pages that share the same data model and API?" If yes, use sub-features. If no, use the simple structure.

When a Sub-Feature Graduates to Top-Level

Only when all three are met: (1) it has its own API endpoints and response types, (2) its own query keys and data lifecycle, (3) it can be deleted without touching shared domain code.

Implementation Checklist

Feature: {name}
[ ] 1. Wire DTOs          — api/{feature}.dto.ts (strict Zod wire schemas, validated against real API)
[ ] 2. Mappers            — api/{feature}.mapper.ts (toX(dto) / buildXBody(input) pure functions)
[ ] 3. API Adapter        — api/{feature}.api.ts (parseResponse(dto) → mapper)
[ ] 4. Domain Layer       — hand-authored types (written alongside mappers — mappers return them), service, errors
[ ] 5. Queries Layer      — query key factory
[ ] 6. Store Layer        — Zustand (skip if no UI state needed)
[ ] 7. Hooks Layer        — queries, component hooks, mutations, form
[ ] 8. Components Layer   — card, list, form, page compositor
[ ] 9. Public Exports     — index.ts
[ ] 10. Translations      — public/locales/{en,es}/{namespace}.json
[ ] 11. Tests             — MSW handlers + per-layer tests (see frontend-testing)

Layer Dependencies

LayerImports FromNever Imports
domain/Nothing (pure TS)React, axios, anything external
api/domain/, @/{app}/shared/React, hooks
queries/api/, domain/React, components
store/domain/ onlyReact hooks, API, components
hooks/queries/, api/, domain/, store/Components
components/hooks/, domain/, store/, @/{app}/ui/api/ directly

Files outside api/ must never import from api/*.dto or api/*.mapper — hooks and components get their types from domain/ only. (Projects may enforce this with their own PreToolUse hook; this plugin does not ship one.)

Feature-Specific Anti-Patterns

  • Don't make API calls in components — go through hooks which wrap queries/mutations
  • Don't put business logic in components — use domain/{feature}.service.ts for pure functions, hooks for React logic
  • Don't import other features' internals — use their index.ts exports
  • Don't put UI state in TanStack Query — use Zustand
  • Don't put a queryOptions layer between keys and hooks — hooks call useQuery directly with keys from the factory
  • Don't re-export wire types as domain types — domain/{feature}.types.ts is hand-authored (api-boundary.md)
  • Don't let a form submit the wire body directly — forms produce domain input; buildXBody in the mapper owns the wire shape

Everything else (logic in components, hardcoded routes/colors, raw try/catch in adapters, toast.error(), legacy imports) is covered by the rule files listed above.

Code Templates

For complete code templates of each file, read references/templates.md.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.