Intent-First Design
Every block starts with what it should do. Arrows show data flow at a glance -- inputs, steps, outputs.
Describe what your service does. Blueprint compiles it to production-ready TypeScript.
Write this:
@ "Create a new todo"
POST /api/todos {
<- title string required
|> todo = save todo { title: title }
-> 201 { id: todo.id, title: todo.title }
}Get this (production-ready TypeScript with Hono + Drizzle + Zod):
todosRoutes.post('/api/todos',
zValidator('json', postTodosSchema),
async (c) => {
try {
const { title } = c.req.valid('json');
const todo = (await db.insert(schema.todos).values({ title }).returning())[0];
return c.json({ id: todo.id, title: todo.title }, 201);
} catch (err) {
throw new BpError(500, 'Internal error');
}
}
);Arrows on the left margin show data flow at a glance:
| Arrow | Meaning | Example |
|---|---|---|
<- | Input | <- name string required |
|> | Step | |> user = fetch user(id) |
-> | Output | -> 200 { id: user.id } |
@ | Intent | @ "Create a user" |
@> | LLM slot | @> implement this logic |
Flat by design: Maximum one level of nesting. try/recover is the only exception.
No if/else, no loops: Use guard for validation and when for conditions. Use map for iteration.
blueprint "my-api" {
version "1.0.0"
port 3000
runtime node
database postgres
}
secret DATABASE_URL required
model user {
id uuid primary
name string required
email string unique required
}
GET /api/users/:id {
<- id uuid required
|> user = fetch user(id)
|> guard user -> 404 "Not found"
-> 200 { id: user.id, name: user.name, email: user.email }
}
POST /api/users {
<- name string required
<- email string required format(email)
|> user = save user { name: name, email: email }
-> 201 { id: user.id }
}bp build my-api.bp
cd generated && npm install && npm start@> slots make the codebase navigable by AI