# Blueprint Structure A blueprint is a directory that contains template files and optional configuration. Blueprints are stored either globally (`~/.blueprints/`) or locally in a project (`.blueprints/`). ## Directory Layout ``` myBlueprint/ ├── blueprint.json # Configuration (optional) ├── files/ # Template files — required │ ├── __blueprintInstance__.ts │ └── src/ │ └── __blueprintInstance__/ │ └── index.ts ├── scripts/ # Lifecycle hooks (optional) │ ├── preGenerate.mjs │ └── postGenerate.mjs └── prompts/ # AI generation prompts (optional) └── default.md ``` ## blueprint.json All fields are optional. A `blueprint.json` does not need to exist for scaffold generation to work. ```json { "description": "Human-readable description shown in bp list --long", "data": { "styleType": "css", "framework": "react" }, "preGenerate": ["scripts/preGenerate.mjs"], "postGenerate": ["scripts/postGenerate.mjs"], "prompts": ["prompts/default.md"], "model": "claude-haiku" } ``` | Field | Type | Description | | ----- | ---- | ----------- | | `description` | string | Shown in `bp list --long`. | | `data` | object | Default values for template variables. Overridden by values passed on the command line. | | `preGenerate` | string[] | Paths to hook scripts that run before file generation. | | `postGenerate` | string[] | Paths to hook scripts that run after file generation. | | `prompts` | string[] | Paths to prompt files used by `bp ask` (AI mode only). | | `model` | string | Default model id used by `bp ask`. See [AI Generation](ai-generation.md). | ## Template Syntax ### File and Directory Names Wrap a variable name in double underscores to substitute it in file or directory names: ``` files/ __blueprintInstance__/ __blueprintInstance__.tsx __blueprintInstance__.test.tsx ``` Running `bp generate component Button` renames those paths to `Button/Button.tsx`, `Button/Button.test.tsx`. ### File Contents Wrap a variable name in double curly braces to substitute it in file contents: ```tsx // files/__blueprintInstance__/__blueprintInstance__.tsx export function {{blueprintInstance_PascalCaseFormat}}() { return
...
} ``` Whitespace inside the braces is allowed: `{{ blueprintInstance }}` and `{{blueprintInstance}}` are equivalent. See [Template Variables](template-variables.md) for the full list of built-in variables. ## Lifecycle Hooks Hook scripts run before or after file generation. They receive the resolved template data and a set of utility libraries. ### Signature ```js // scripts/postGenerate.mjs export default async function(data, libraries) { const { _, fs, date, File, log } = libraries // ... perform any file operations return Promise.resolve() } ``` ### Available Libraries | Name | Package | Docs | | ---- | ------- | ---- | | `fs` | fs-extra | https://github.com/jprichardson/node-fs-extra | | `_` | lodash | https://lodash.com/docs | | `date` | date-fns | https://date-fns.org | | `File` | built-in | Chain-based file manipulation (read, append, prepend, replace, save) | | `log` | built-in | `log.text()`, `log.success()`, `log.warning()`, `log.error()` | ### Hook Path Tokens The paths in `preGenerate` and `postGenerate` support these substitution tokens: | Token | Replaced with | | ----- | ------------- | | `` | The blueprint's name | | `` | Absolute path to the blueprint directory | | `` | The blueprint instance name | | `` | Absolute path to the generated instance destination | ### Error Handling If any hook rejects its Promise, generation stops and a `LIFECYCLE_SCRIPT_ERROR` is thrown. With `--json`, the error appears as: ```json { "error": { "code": "LIFECYCLE_SCRIPT_ERROR", "message": "postGenerate hook failed: ..." } } ``` ## Creating Blueprints **From scratch (empty template directory):** ```bash bp new myBlueprint # creates in .blueprints/myBlueprint bp new -g myBlueprint # creates in ~/.blueprints/myBlueprint ``` **With specific template files:** ```bash # File paths are relative to files/ inside the blueprint bp new myBlueprint -f "__blueprintInstance__/index.ts" -f "__blueprintInstance__/index.test.ts" # Optionally provide inline content after a colon bp new myBlueprint \ -f "__blueprintInstance__/index.ts:export default function {{ blueprintInstance_ClassFormat }}() {}" \ -f "__blueprintInstance__/index.test.ts" ``` The `-f, --file` flag is repeatable. Each value has the format `path[:content]` where the path is relative to `files/` and content is optional. When at least one `--file` flag is given, the default empty `files/__blueprintInstance__/` directory is not created. **From an existing directory:** ```bash bp new myBlueprint -s ./src/components/Button ``` This copies the directory into `files/__blueprintInstance__/` and generates the script scaffolding. ## Blueprint Resolution When running `bp generate myBlueprint ...`, the CLI checks: 1. `.blueprints/myBlueprint` in the current project (or nearest ancestor with a `.blueprints` folder) 2. `~/.blueprints/myBlueprint` globally The project-local blueprint takes precedence if both exist.