Blueprint spec

A blueprint is a structure that describes code to be built, in the abstract: the files, folders, classes, functions, variables, and relations, rather than the source itself. An LLM uses that structure to write working code. A person uses it to instruct the LLM at that same level, and to see what the LLM intends to build.

How it is used

On top of existing code. The project is already there. The blueprint adds files and folders, and points at the existing files, folders, functions, or variables it reaches into. Imports and notes can name those existing paths.

Without existing code. The project is empty. The blueprint describes only what it adds: files, folders, functions, variables, and the imports between them. pointers and deleted are empty.

In between. Some paths are new and some already exist. The todo app below is this case. src/todo and the files under it are added, and src/App.tsx is a pointer to a file already in the project, with TodoApp imported into it.

Example

Entries taken from todo-app.blueprint.json. deleted and steps are empty in that file. The sections below explain each list.

todo-app.blueprint.json
{12 keys}
"version": 1,
"kind": "blueprint",
"name": "todo-app",
"files": [1 item],
{4 keys}
"id": "src/todo/TodoApp.tsx",
"name": "TodoApp.tsx",
"path": "src/todo/TodoApp.tsx",
"folder": "src/todo"
}
],
"folders": [2 items],
{4 keys},
"id": "src/todo",
"name": "todo",
"path": "src/todo",
"parent": "src"
},
{4 keys}
"id": "src/todo/components",
"name": "components",
"path": "src/todo/components",
"parent": "src/todo"
}
],
"functions": [2 items],
{2 keys},
"name": "addTodo",
"file": "src/todo/store/todos.ts"
},
{2 keys}
"name": "TodoItem",
"file": "src/todo/components/TodoItem.tsx"
}
],
"variables": [2 items],
{2 keys},
"name": "FILTERS",
"file": "src/todo/constants.ts"
},
{2 keys}
"name": "todos",
"file": "src/todo/store/todos.ts"
}
],
"imports": [3 items],
{3 keys},
"name": "Todo",
"from": "src/todo/types.ts",
"file": "src/todo/utils/filters.ts"
},
{3 keys},
"name": "FilterId",
"from": "src/todo/types.ts",
"file": "src/todo/utils/filters.ts"
},
{3 keys}
"name": "TodoApp",
"from": "src/todo/TodoApp.tsx",
"file": "src/App.tsx"
}
],
"notes": [2 items],
{3 keys},
"file": "src/todo",
"kind": "folder",
"note": "Plain React todo app. No extra packages. Keep each file small."
},
{3 keys}
"file": "src/todo/components/TodoItem.tsx",
"kind": "file",
"note": "One row: checkbox, title, delete. Props only, no store."
}
],
"pointers": [1 item],
{2 keys}
"kind": "file",
"path": "src/App.tsx"
}
],
"deleted": [],
"steps": []
}

Overview

One blueprint is one file with the extension .blueprint.json, for example todo-app.blueprint.json.

All paths are relative to the project root and use forward slashes. src/todo/TodoApp.tsx names its folder src/todo. The function TodoApp names that same path as its file.

todo-app.blueprint.json
{2 keys}
"files": [1 item],
{4 keys}
"id": "src/todo/TodoApp.tsx",
"name": "TodoApp.tsx",
"path": "src/todo/TodoApp.tsx",
"folder": "src/todo"
}
],
"functions": [1 item]
{2 keys}
"name": "TodoApp",
"file": "src/todo/TodoApp.tsx"
}
]
}

Blueprint file

todo-app.blueprint.json
{3 keys}
"version": 1,
"kind": "blueprint",
"name": "todo-app"
}

These three fields identify the file. version is 1, kind is "blueprint", and name is todo-app, the file name without .blueprint.json. The lists in the sections below sit on this same object.

FieldTypeDescription
version number Format version. Always 1.
kind string Always "blueprint".
name string Name of the blueprint. Usually the file name without the extension.
files … steps arrays The entities described in the sections below. Every list is optional and defaults to empty.

files

todo-app.blueprint.json → files
{1 key}
"files": [1 item]
{4 keys}
"id": "src/todo/TodoApp.tsx",
"name": "TodoApp.tsx",
"path": "src/todo/TodoApp.tsx",
"folder": "src/todo"
}
]
}

Files the blueprint adds. This one is src/todo/TodoApp.tsx: its id and path are that path, its name is TodoApp.tsx, and its folder is src/todo. A file that already exists belongs in pointers instead.

FieldTypeDescription
id string Unique id. The same value as path.
name string File name with extension, such as TodoApp.tsx.
path string Full path from the project root.
folder string Path of the folder the file sits in.

All four fields are required strings.

LLM instruction example

A file is a new file the plan creates. A file that already exists is a pointer, not a file.

folders

todo-app.blueprint.json → folders
{1 key}
"folders": [2 items]
{4 keys},
"id": "src/todo",
"name": "todo",
"path": "src/todo",
"parent": "src"
},
{4 keys}
"id": "src/todo/components",
"name": "components",
"path": "src/todo/components",
"parent": "src/todo"
}
]
}

Folders the blueprint adds. Each level is its own entry: src/todo/components sits next to src/todo, and its parent is src/todo.

FieldTypeDescription
id string Unique id. The same value as path.
name string Last segment of the path, such as todo.
path string Full path from the project root.
parent string Path of the parent folder. "." means the project root.

All four fields are required strings.

LLM instruction example

A folder is part of the folder skeleton the plan creates. Each level is its own entry.

classes

class shape
{3 keys}
"classes": [1 item],
{4 keys}
"name": "TodoStore",
"file": "src/todo/store/todos.ts",
"extends": "Store",
"implements": [1 item]
"Persistable"
]
}
],
"functions": [1 item],
{4 keys}
"name": "addTodo",
"file": "src/todo/store/todos.ts",
"class": "TodoStore",
"overrides": true
}
],
"variables": [1 item]
{3 keys}
"name": "todos",
"file": "src/todo/store/todos.ts",
"class": "TodoStore"
}
]
}

A class the blueprint adds, in a file. TodoStore is defined in src/todo/store/todos.ts. A method is a function with class set to that name: addTodo. A field is a variable with class set to that name: todos. The constructor is one of those functions, using the name that language uses. extends names its one parent class, Store. implements names the interfaces it fulfills, Persistable. addTodo sets overrides because it replaces a method on that parent. The todo blueprint has no classes; this snippet is only the shape.

FieldTypeDescription
name string Identifier of the class. Required.
file string Path of the file that defines it. Required. Several classes may share one file.
extends string Name of the one parent class. Omit it when the class has no parent.
implements string[] Names of the interfaces or protocols it fulfills. Omit it when there are none. One name per entry.

Static members and visibility stay in a note. The structure does not give them their own fields.

LLM instruction example

A class is a class the plan adds, in a file. extends is its one parent class. implements names the interfaces or protocols it fulfills. Its methods are functions with class set to its name. Its fields are variables with class set to its name. The constructor is one of those functions.

functions

todo-app.blueprint.json → functions
{1 key}
"functions": [2 items]
{2 keys},
"name": "addTodo",
"file": "src/todo/store/todos.ts"
},
{2 keys}
"name": "TodoItem",
"file": "src/todo/components/TodoItem.tsx"
}
]
}

Functions, methods, components, and hooks the blueprint adds. addTodo is defined in src/todo/store/todos.ts. TodoItem is defined in src/todo/components/TodoItem.tsx. file is that path. These two omit class because they are not methods. A method includes class, as addTodo does on TodoStore in classes.

FieldTypeDescription
name string Identifier of the function.
file string Path of the file that defines it. Required.
class string Name of the class the function belongs to. Omit it when the function is not a method.
overrides boolean True when this method replaces a method on the parent class. Omit it otherwise.

LLM instruction example

A function is a function, method, component, or hook the plan adds. A method includes class, the class it belongs to. A method that replaces a parent method sets overrides.

variables

todo-app.blueprint.json → variables
{1 key}
"variables": [2 items]
{2 keys},
"name": "FILTERS",
"file": "src/todo/constants.ts"
},
{2 keys}
"name": "todos",
"file": "src/todo/store/todos.ts"
}
]
}

Constants, shared module state, and config values the blueprint adds. FILTERS is declared in src/todo/constants.ts. todos is declared in src/todo/store/todos.ts. Same fields as functions: name, file, and an optional class. These two omit class. A field includes it, as todos does on TodoStore in classes.

LLM instruction example

A variable is a constant, a piece of shared state, a config value, or a field the plan adds. A field includes class, the class it belongs to.

imports (relations)

todo-app.blueprint.json → imports
{1 key}
"imports": [3 items]
{3 keys},
"name": "Todo",
"from": "src/todo/types.ts",
"file": "src/todo/utils/filters.ts"
},
{3 keys},
"name": "FilterId",
"from": "src/todo/types.ts",
"file": "src/todo/utils/filters.ts"
},
{3 keys}
"name": "TodoApp",
"from": "src/todo/TodoApp.tsx",
"file": "src/App.tsx"
}
]
}

Relations between files. Each entry says that file imports name from from. src/todo/utils/filters.ts imports Todo and FilterId from src/todo/types.ts, one entry each. src/App.tsx imports TodoApp from src/todo/TodoApp.tsx.

FieldTypeDescription
name string The imported symbol.
from string Path of the file that exports the symbol.
file string Path of the file that imports the symbol.

All three fields are required. Import one symbol per entry. Todo and FilterId come from the same file, so they are two entries.

LLM instruction example

An import is a relation between two files: file imports name from from. One symbol is one entry.

notes

todo-app.blueprint.json → notes
{1 key}
"notes": [3 items]
{3 keys},
"file": "src/todo",
"kind": "folder",
"note": "Plain React todo app. No extra packages. Keep each file small."
},
{3 keys},
"file": "src/todo/components/TodoItem.tsx",
"kind": "file",
"note": "One row: checkbox, title, delete. Props only, no store."
},
{3 keys}
"file": "src/App.tsx",
"kind": "file",
"note": "Import TodoApp and render it under ColorGenerator. Keep the existing hello world."
}
]
}

Text attached to a folder, file, class, function, or variable. The folder src/todo has a note. The file src/todo/components/TodoItem.tsx has a note. The existing file src/App.tsx has a note too.

FieldTypeDescription
file string Path of the file or folder the note belongs to. For class, function, and variable notes, the file that defines the symbol.
kind string "file", "folder", "class", "function", or "variable". "file" when missing.
name string Symbol name. Required for class, function, and variable notes.
class string Class name. Set it when the note is on a method or field, so the symbol is not confused with another of the same name.
note string The text.

One note per folder, file, or symbol.

LLM instruction example

A note is an instruction on a file, folder, class, function, or variable. It states the contract or a non-obvious invariant the plan must keep. A note on a method or field includes class.

pointers

todo-app.blueprint.json → pointers
{1 key}
"pointers": [1 item]
{2 keys}
"kind": "file",
"path": "src/App.tsx"
}
]
}

References to a file, folder, class, function, or variable that already exists. This blueprint has one: the file src/App.tsx. Its note is in notes, and the TodoApp import into it is in imports.

FieldTypeDescription
kind string "file", "folder", "class", "function", or "variable". Required.
path string Path of the file or folder. For a class, function, or variable, the file that defines the symbol.
name string Symbol name. Required for class, function, and variable pointers.
class string Class name. Set it when the pointer is a method or field.

Pointers use path. Notes use file for the same role.

LLM instruction example

A pointer is a reference to a file, folder, class, function, or variable that already exists. Pay attention to it when setting up the plan, and usually edit it. It does not also go in files, folders, or classes. A method or field pointer includes class.

deleted

todo-app.blueprint.json → deleted
{1 key}
"deleted": []
}

Paths of files to remove. This blueprint removes none, so the list is empty. An entry is a path string, the same shape as src/todo/TodoApp.tsx.

LLM instruction example

A deleted entry is an existing file path the plan removes, including its imports, references, and usages.

steps

todo-app.blueprint.json → steps
{1 key}
"steps": []
}

Ordered steps for building the blueprint. This blueprint has none, so the list is empty. An entry is a string.

LLM instruction example

A step is a suggested sentence for the plan. Decide which are useful and in what order. Keep, merge, split, reword, reorder, or drop them, and add missing ones. They are suggestions, not the plan itself.

Full example

apps/example-target/blueprints/todo-app/todo-app.blueprint.json
{12 keys}
"version": 1,
"kind": "blueprint",
"name": "todo-app",
"files": [13 items],
{4 keys},
"id": "src/todo/types.ts",
"name": "types.ts",
"path": "src/todo/types.ts",
"folder": "src/todo"
},
{4 keys},
"id": "src/todo/constants.ts",
"name": "constants.ts",
"path": "src/todo/constants.ts",
"folder": "src/todo"
},
{4 keys},
"id": "src/todo/utils/ids.ts",
"name": "ids.ts",
"path": "src/todo/utils/ids.ts",
"folder": "src/todo/utils"
},
{4 keys},
"id": "src/todo/utils/storage.ts",
"name": "storage.ts",
"path": "src/todo/utils/storage.ts",
"folder": "src/todo/utils"
},
{4 keys},
"id": "src/todo/utils/filters.ts",
"name": "filters.ts",
"path": "src/todo/utils/filters.ts",
"folder": "src/todo/utils"
},
{4 keys},
"id": "src/todo/store/todos.ts",
"name": "todos.ts",
"path": "src/todo/store/todos.ts",
"folder": "src/todo/store"
},
{4 keys},
"id": "src/todo/components/EmptyState.tsx",
"name": "EmptyState.tsx",
"path": "src/todo/components/EmptyState.tsx",
"folder": "src/todo/components"
},
{4 keys},
"id": "src/todo/components/TodoItem.tsx",
"name": "TodoItem.tsx",
"path": "src/todo/components/TodoItem.tsx",
"folder": "src/todo/components"
},
{4 keys},
"id": "src/todo/components/TodoList.tsx",
"name": "TodoList.tsx",
"path": "src/todo/components/TodoList.tsx",
"folder": "src/todo/components"
},
{4 keys},
"id": "src/todo/components/TodoForm.tsx",
"name": "TodoForm.tsx",
"path": "src/todo/components/TodoForm.tsx",
"folder": "src/todo/components"
},
{4 keys},
"id": "src/todo/components/TodoFilters.tsx",
"name": "TodoFilters.tsx",
"path": "src/todo/components/TodoFilters.tsx",
"folder": "src/todo/components"
},
{4 keys},
"id": "src/todo/components/TodoStats.tsx",
"name": "TodoStats.tsx",
"path": "src/todo/components/TodoStats.tsx",
"folder": "src/todo/components"
},
{4 keys}
"id": "src/todo/TodoApp.tsx",
"name": "TodoApp.tsx",
"path": "src/todo/TodoApp.tsx",
"folder": "src/todo"
}
],
"folders": [4 items],
{4 keys},
"id": "src/todo",
"name": "todo",
"path": "src/todo",
"parent": "src"
},
{4 keys},
"id": "src/todo/utils",
"name": "utils",
"path": "src/todo/utils",
"parent": "src/todo"
},
{4 keys},
"id": "src/todo/store",
"name": "store",
"path": "src/todo/store",
"parent": "src/todo"
},
{4 keys}
"id": "src/todo/components",
"name": "components",
"path": "src/todo/components",
"parent": "src/todo"
}
],
"functions": [16 items],
{2 keys},
"name": "createTodo",
"file": "src/todo/types.ts"
},
{2 keys},
"name": "nextId",
"file": "src/todo/utils/ids.ts"
},
{2 keys},
"name": "loadTodos",
"file": "src/todo/utils/storage.ts"
},
{2 keys},
"name": "saveTodos",
"file": "src/todo/utils/storage.ts"
},
{2 keys},
"name": "filterTodos",
"file": "src/todo/utils/filters.ts"
},
{2 keys},
"name": "addTodo",
"file": "src/todo/store/todos.ts"
},
{2 keys},
"name": "toggleTodo",
"file": "src/todo/store/todos.ts"
},
{2 keys},
"name": "removeTodo",
"file": "src/todo/store/todos.ts"
},
{2 keys},
"name": "setFilter",
"file": "src/todo/store/todos.ts"
},
{2 keys},
"name": "EmptyState",
"file": "src/todo/components/EmptyState.tsx"
},
{2 keys},
"name": "TodoItem",
"file": "src/todo/components/TodoItem.tsx"
},
{2 keys},
"name": "TodoList",
"file": "src/todo/components/TodoList.tsx"
},
{2 keys},
"name": "TodoForm",
"file": "src/todo/components/TodoForm.tsx"
},
{2 keys},
"name": "TodoFilters",
"file": "src/todo/components/TodoFilters.tsx"
},
{2 keys},
"name": "TodoStats",
"file": "src/todo/components/TodoStats.tsx"
},
{2 keys}
"name": "TodoApp",
"file": "src/todo/TodoApp.tsx"
}
],
"variables": [3 items],
{2 keys},
"name": "FILTERS",
"file": "src/todo/constants.ts"
},
{2 keys},
"name": "todos",
"file": "src/todo/store/todos.ts"
},
{2 keys}
"name": "filter",
"file": "src/todo/store/todos.ts"
}
],
"imports": [29 items],
{3 keys},
"name": "Todo",
"from": "src/todo/types.ts",
"file": "src/todo/utils/storage.ts"
},
{3 keys},
"name": "Todo",
"from": "src/todo/types.ts",
"file": "src/todo/utils/filters.ts"
},
{3 keys},
"name": "FilterId",
"from": "src/todo/types.ts",
"file": "src/todo/utils/filters.ts"
},
{3 keys},
"name": "FILTERS",
"from": "src/todo/constants.ts",
"file": "src/todo/utils/filters.ts"
},
{3 keys},
"name": "Todo",
"from": "src/todo/types.ts",
"file": "src/todo/store/todos.ts"
},
{3 keys},
"name": "createTodo",
"from": "src/todo/types.ts",
"file": "src/todo/store/todos.ts"
},
{3 keys},
"name": "nextId",
"from": "src/todo/utils/ids.ts",
"file": "src/todo/store/todos.ts"
},
{3 keys},
"name": "loadTodos",
"from": "src/todo/utils/storage.ts",
"file": "src/todo/store/todos.ts"
},
{3 keys},
"name": "saveTodos",
"from": "src/todo/utils/storage.ts",
"file": "src/todo/store/todos.ts"
},
{3 keys},
"name": "Todo",
"from": "src/todo/types.ts",
"file": "src/todo/components/TodoItem.tsx"
},
{3 keys},
"name": "TodoItem",
"from": "src/todo/components/TodoItem.tsx",
"file": "src/todo/components/TodoList.tsx"
},
{3 keys},
"name": "EmptyState",
"from": "src/todo/components/EmptyState.tsx",
"file": "src/todo/components/TodoList.tsx"
},
{3 keys},
"name": "todos",
"from": "src/todo/store/todos.ts",
"file": "src/todo/components/TodoList.tsx"
},
{3 keys},
"name": "toggleTodo",
"from": "src/todo/store/todos.ts",
"file": "src/todo/components/TodoList.tsx"
},
{3 keys},
"name": "removeTodo",
"from": "src/todo/store/todos.ts",
"file": "src/todo/components/TodoList.tsx"
},
{3 keys},
"name": "filterTodos",
"from": "src/todo/utils/filters.ts",
"file": "src/todo/components/TodoList.tsx"
},
{3 keys},
"name": "addTodo",
"from": "src/todo/store/todos.ts",
"file": "src/todo/components/TodoForm.tsx"
},
{3 keys},
"name": "FILTERS",
"from": "src/todo/constants.ts",
"file": "src/todo/components/TodoFilters.tsx"
},
{3 keys},
"name": "filter",
"from": "src/todo/store/todos.ts",
"file": "src/todo/components/TodoFilters.tsx"
},
{3 keys},
"name": "setFilter",
"from": "src/todo/store/todos.ts",
"file": "src/todo/components/TodoFilters.tsx"
},
{3 keys},
"name": "todos",
"from": "src/todo/store/todos.ts",
"file": "src/todo/components/TodoStats.tsx"
},
{3 keys},
"name": "filterTodos",
"from": "src/todo/utils/filters.ts",
"file": "src/todo/components/TodoStats.tsx"
},
{3 keys},
"name": "loadTodos",
"from": "src/todo/utils/storage.ts",
"file": "src/todo/TodoApp.tsx"
},
{3 keys},
"name": "todos",
"from": "src/todo/store/todos.ts",
"file": "src/todo/TodoApp.tsx"
},
{3 keys},
"name": "TodoForm",
"from": "src/todo/components/TodoForm.tsx",
"file": "src/todo/TodoApp.tsx"
},
{3 keys},
"name": "TodoFilters",
"from": "src/todo/components/TodoFilters.tsx",
"file": "src/todo/TodoApp.tsx"
},
{3 keys},
"name": "TodoStats",
"from": "src/todo/components/TodoStats.tsx",
"file": "src/todo/TodoApp.tsx"
},
{3 keys},
"name": "TodoList",
"from": "src/todo/components/TodoList.tsx",
"file": "src/todo/TodoApp.tsx"
},
{3 keys}
"name": "TodoApp",
"from": "src/todo/TodoApp.tsx",
"file": "src/App.tsx"
}
],
"notes": [15 items],
{3 keys},
"file": "src/todo",
"kind": "folder",
"note": "Plain React todo app. No extra packages. Keep each file small."
},
{3 keys},
"file": "src/todo/types.ts",
"kind": "file",
"note": "Export Todo { id, title, done } and FilterId \"all\" | \"active\" | \"done\". Export createTodo(title, id)."
},
{3 keys},
"file": "src/todo/constants.ts",
"kind": "file",
"note": "Export FILTERS: { id: FilterId, label: string }[] for All, Active, Done."
},
{3 keys},
"file": "src/todo/utils/ids.ts",
"kind": "file",
"note": "Export nextId() returning a unique string. No React."
},
{3 keys},
"file": "src/todo/utils/storage.ts",
"kind": "file",
"note": "loadTodos() / saveTodos(todos) using localStorage key \"example-todos\". No React."
},
{3 keys},
"file": "src/todo/utils/filters.ts",
"kind": "file",
"note": "filterTodos(todos, filterId) using FILTERS ids. No React."
},
{3 keys},
"file": "src/todo/store/todos.ts",
"kind": "file",
"note": "Module state: todos and filter. addTodo, toggleTodo, removeTodo, setFilter. Persist with storage after each change. No React."
},
{3 keys},
"file": "src/todo/components/EmptyState.tsx",
"kind": "file",
"note": "Simple empty-list message. No store imports."
},
{3 keys},
"file": "src/todo/components/TodoItem.tsx",
"kind": "file",
"note": "One row: checkbox, title, delete. Props only, no store."
},
{3 keys},
"file": "src/todo/components/TodoList.tsx",
"kind": "file",
"note": "Read todos and filter from the store. Map TodoItem. Show EmptyState when the filtered list is empty."
},
{3 keys},
"file": "src/todo/components/TodoForm.tsx",
"kind": "file",
"note": "Title input and Add button. Calls addTodo. Independent of the list UI."
},
{3 keys},
"file": "src/todo/components/TodoFilters.tsx",
"kind": "file",
"note": "Buttons for FILTERS. Independent of the list and form."
},
{3 keys},
"file": "src/todo/components/TodoStats.tsx",
"kind": "file",
"note": "Show active and done counts from the store. Independent of the list and form."
},
{3 keys},
"file": "src/todo/TodoApp.tsx",
"kind": "file",
"note": "Shell that loads storage once, then renders form, filters, stats, and list."
},
{3 keys}
"file": "src/App.tsx",
"kind": "file",
"note": "Import TodoApp and render it under ColorGenerator. Keep the existing hello world."
}
],
"pointers": [1 item],
{2 keys}
"kind": "file",
"path": "src/App.tsx"
}
],
"deleted": [],
"steps": []
}

A complete todo app blueprint: the src/todo folder with its store, utils, and components, the functions and constants in them, the imports between them, a note per file, and a pointer at src/App.tsx. The lists start collapsed.