--- name: scaffold license: MIT description: >- Project-aware file generation. Reads existing codebase conventions (naming, structure, imports, exports, test patterns) then generates new files that match exactly. Wires generated files into the project's registration points. user-invocable: true auto-trigger: false trigger_keywords: - scaffold - generate component - generate module - generate service - new component - new module - new route - new service - create component - stub out - bootstrap --- # /scaffold — Project-Aware File Generator ## Orientation **Use when:** Creating a new component, module, service, route, hook, domain, or utility with existing examples in the project. **Do NOT use when:** The file has no precedent (use `/marshal` for unconstrained generation), you're modifying existing files (use `/refactor`), or the project has no conventions yet. **Needs:** target type, name, and optional description. ## Protocol ### Step 1: IDENTIFY THE TARGET Parse the user's request into: - **type**: component | module | service | route | hook | domain | utility | custom - **name**: the name the user gave (e.g., "UserProfile", "auth-service", "settings route") - **description**: what it does, if provided (otherwise leave blank for now) If the type is ambiguous, ask ONE clarifying question. Do not ask more than one. ### Step 2: FIND EXEMPLARS Search the codebase for 2-3 existing files of the same type. **Search strategy by type:** | Type | Search Pattern | What to Look For | |---|---|---| | component | `**/*.tsx` in the same directory or sibling directories | Functional components with similar complexity | | module | Same directory as where new module will live | Registration pattern, exports, config shape | | service | `**/services/**`, `**/lib/**` | Class vs function, singleton vs factory, error handling | | route | Router config files, `**/routes.*`, `**/pages/**` | Route definition format, lazy loading, guards | | hook | `**/hooks/**`, `**/use*.ts` | Naming, parameter patterns, return types, cleanup | | domain | Top-level domain/feature directories | Manifest structure, entry point, internal layout | | utility | `**/utils/**`, `**/helpers/**` | Pure function style, type signatures, JSDoc | **For each exemplar, extract:** 1. File naming convention (PascalCase, kebab-case, camelCase, snake_case) 2. Directory placement (co-located with component? separate `hooks/` dir?) 3. Import style (path aliases? relative? named imports? default exports?) 4. Export style (named exports? default? re-exported from barrel/index file?) 5. Internal patterns (how state is managed, how errors are handled, JSDoc or no) 6. Test co-location (`.test.ts` next to file? `__tests__/` directory? separate `tests/` tree?) 7. Types pattern (inline? separate `.types.ts`? shared types file?) **Output a brief analysis** (3-5 lines) summarizing the conventions you found. ### Step 3: DETERMINE THE FILE SET Based on the exemplars, determine which files to generate. Not every project needs every file. Only generate what the project's conventions call for. **Decision matrix:** | File | Generate IF... | |---|---| | Main file | Always | | Types file (`.types.ts`) | Project separates types into their own files (check exemplars) | | Test file (`.test.ts`) | Project has co-located tests for this type of file | | Barrel/index file | Project uses barrel exports AND this file's directory doesn't already have one | | Barrel update | Project uses barrel exports AND the directory already has an index file | | Style file (`.module.css`, `.styled.ts`) | Project uses co-located styles for this type | | Storybook file (`.stories.tsx`) | Project has stories for this type of file | **Do NOT generate:** - Empty placeholder files with only a TODO comment - Test files that only contain `describe('...', () => { it.todo('...') })` - Types files that only re-export from elsewhere - Any file type the project doesn't already use ### Step 4: GENERATE THE FILES For each file in the set, generate content by adapting the closest exemplar. **Rules:** 1. Match the exemplar's structure exactly — same section order, same patterns 2. Replace names and specific logic, keep structural patterns 3. Every generated file must be syntactically valid and importable 4. No placeholder comments (`// TODO: implement`, `// Add logic here`) 5. No empty function bodies unless the exemplar has them 6. Minimal but functional — renders something, has at least one real method, returns a typed value 7. Match the project's TypeScript strictness Match the exemplar's props pattern, state management, utility imports, async patterns, and error handling exactly. ### Step 5: WIRE IT IN Find every registration point the exemplars use and add the new file there. **Common wiring points (check which ones the project uses):** | Wiring Point | How to Find It | What to Add | |---|---|---| | Barrel exports | `index.ts` in the same or parent directory | `export { NewThing } from './NewThing'` | | Route registration | Router config file (search for exemplar's route) | New route entry matching the pattern | | Module registry | Bootstrap/registration file | New registration call | | Navigation/sidebar | Nav config array | New nav entry if appropriate | | Lazy loading map | Dynamic import map | New lazy import entry | | Type unions | Discriminated unions that list all variants | New variant if this is a new "type" of thing | **Rules:** 1. Only wire into registration points that the exemplars actually use 2. Match the exact format — same spacing, same trailing commas, same comments 3. If a registration point uses alphabetical ordering, maintain it 4. Never create new registration points — only add to existing ones ### Step 6: VERIFY Run typecheck — every generated file must pass. Fix failures before exiting. If typecheck is unavailable, do a manual read-through for syntax and import correctness. ## Fringe Cases - **Target directory or file already exists**: Do not silently overwrite. Confirm with the user before proceeding. Output: "A file at `{path}` already exists. Overwrite it?" and wait for confirmation. - **Template or exemplar not found**: List the available file types in the codebase and ask which one to use as the exemplar. Never scaffold from memory if no exemplar exists. - **Language or framework not detected**: Ask the user directly rather than guessing. One question: "What type of file should this be? (e.g., React component, Express route, utility function)" - **Typecheck fails after generation**: Fix the issue before exiting — do not leave the user with broken generated files. - **No wiring point found**: Note the missing registration explicitly in the exit summary rather than silently leaving the file unwired. ## Contextual Gates **Reversibility:** Amber — creates new files and modifies registration points; `git checkout` to undo. **Cost:** No cost actions — file generation only; no agents spawned, no confirmation needed. **Trust:** No gates — safe at all trust levels; overwrite confirmation is in Fringe Cases. ## Quality Gates All of these must be true before the skill exits: - [ ] Found 2+ exemplar files of the same type in the project - [ ] Generated files match the project's naming convention exactly - [ ] Generated files match the project's import/export style exactly - [ ] No placeholder comments, TODO stubs, or empty function bodies - [ ] Every generated file is syntactically valid TypeScript/JavaScript - [ ] Main file is wired into the project (barrel export, route, registry, etc.) - [ ] Test file exists IF AND ONLY IF the project co-locates tests for this type - [ ] Types file exists IF AND ONLY IF the project separates types for this type - [ ] Typecheck passes (or manual verification if typecheck unavailable) ## Exit Protocol Output a summary in this format: ``` SCAFFOLD COMPLETE Created: - path/to/MainFile.tsx (component) - path/to/MainFile.test.tsx (test) - path/to/MainFile.types.ts (types) Wired into: - path/to/index.ts (barrel export) - path/to/routes.ts (route registration) Conventions matched from: - path/to/ExemplarA.tsx - path/to/ExemplarB.tsx Typecheck: PASS ``` ``` ---HANDOFF--- - Scaffolded: {name} ({type}) - Created: {N} files, wired into {N} registration points - Conventions matched from: {exemplar names} - Reversibility: green -- new files only, delete to undo --- ```