Concepts
Design spaces
A canvas where the agent builds mockups as live React frames you can look at, click through, and iterate on before any of it becomes real code.
A design tab is a canvas for visual work. Ask for a mockup and the agent builds it as live frames — real, running React you can look at and interact with, not a picture of an interface.
It’s for the stage before implementation: exploring what a screen should look like, putting variants side by side, and agreeing on a direction. Building a design changes no application code, so you can throw away five explorations without touching the app.
Canvases and frames
Two levels, and both are just files:
- A canvas is a folder under
.astra/designs/in the repo. - A frame is a
.tsxfile directly inside that folder.
Adding a file adds a frame; deleting one removes it; renaming the folder renames the canvas. There’s no hidden state — the canvas is the directory, and it’s committed with everything else, so a branch carries its own designs.
Every frame is a self-contained React component that default-exports itself and declares its own size:
export const frame = { width: 1440, height: 900 };
export default function Home() {
return <div style={{ /* ... */ }}>…</div>;
}
Frames are deliberately fenced. They style inline, and they may only import react and relative paths inside .astra/designs/ — so a frame can share a helper with its neighbors, but it can’t reach into your application code. A mockup that quietly depended on your real component library wouldn’t be a mockup any more.
Size is the frame’s own business, declared in its file. Position is the canvas’s: Astra writes a canvas.json beside the frames when you drag things around, and a new frame with no entry places itself next to the last one.
Working on a canvas
Open a design tab from the new-tab menu (⌘T). The tab carries its own conversation, and its acting mode is Design — Build’s equivalent for frames.
The canvas picks up file changes at the end of each turn, so you watch the design land as the agent finishes rather than flickering through half-written states. Frames the agent wrote or edited also show up as cards in the chat, which makes the transcript readable after the fact.
You can @-mention a design from an ordinary chat too, so an agent working on code knows which mockup you’re talking about.
Clicking through a prototype
The canvas itself never goes live — a board of running apps is hard to think on. Instead, each frame’s label has a ▶ on hover that opens it in a dedicated interact overlay.
In there the frame fills the pane and you can actually use it: click, type, navigate. Media queries and text still evaluate at the frame’s declared viewport, so a 390px frame behaves like a phone regardless of how big the overlay is. A reload button resets the prototype’s state, and the agent editing the frame reloads it too.
The loop this is built around is short: click around, find what’s wrong, tell the agent, watch it change.
When a frame breaks
Each frame is compiled on its own. A frame with a syntax error, a missing size export, or a disallowed import renders that error in place — the other frames on the canvas keep working. You never lose the whole board to one bad file, and you never get a silent blank where a frame should be.
The designs hub
The hub browses every canvas in a project without spending a space on it, reading the project’s main checkout. Read one, then use Open in a new space when you want to actually work on it — that mints a fresh space each time, because a design isn’t a conversation and shouldn’t be stuck to one.
Designs on a branch surface inside the space that owns that branch, not in the hub.
Turning a design into code
That’s a separate job, and an explicit one. A design is a mockup; asking for the real implementation is a different request, usually in a different space. Keeping the two apart is what makes it cheap to explore.