LeCodes Design
A canvas for designing an app before it exists. Every screen is a file — design/screens/<id>.ts — live and executable; meta.json ties the screens into a flow map. lecodes design opens the board in the browser: screens render for real, and the selected one is interactive.
It's built for a human + AI pair: the assistant writes screens as code and looks at the result itself; you watch the board, move things, connect them and edit. This is the intent-capture stage — screens run on inline mock data, before any backend exists.
Setup & first board
The canvas is an optional package next to the CLI. It works inside a cloned project or standalone in any folder — no login needed:
npm i -D lecodes-design lecodes-renderer
lecodes design init # scaffold: screens/, shared/, meta.json, spec.md, CLAUDE.md
lecodes design # dev server + the board in your browser (port 4477)init also writes the SDK types and a tsconfig.json (IntelliSense in screen files) and registers the board's MCP server in .mcp.json, so Claude Code sees its tools right away. lecodes-renderer powers headless rendering — the snapshot command and the render_screen MCP tool.
The board
Screens hot-reload as you save files, and everything you do on the board is written back to the files:
- Drag an unselected screen — the position lands in
meta.json. Click to select a screen and it becomes interactive: taps, scrolling and typing work. - Pull the connect handle onto another screen to draw a flow edge; click an edge to edit its label and activator (the element that triggers the transition) or delete it.
- Double-click any text to edit it in place — the string literal is rewritten right in the screen's source. Double-click an image (or drop a file from your OS) to replace it: the file is stored in
design/assets/and theasset()path is rewritten. - H — hint mode: outlines interactive elements, editable texts and replaceable images.
Screens in meta.json can be gathered into groups (rendered as labeled regions) and tagged with a role (list, form, auth, …) — on a big board that's the only way to stay oriented.
Screens are code
The rules are simple, and they're exactly what makes the design AI-friendly:
- One file = one screen.
screens/<id>.tsdefault-exports aUIScreen; the filename is the screen's identity. - Screens are islands. They import only from
shared/(tokens, shared components) — screens don't know about each other; every relationship lives inmeta.json. - Mock data is the domain. Realistic data at the top of the file is the first draft of the future schema; entities that stabilize graduate to
spec.md— the narrative half of the design (data model, actors, rules). - Screen states aren't separate files but a function of a string-literal union; the union IS the state list:
export default (state: "default" | "empty" = "default") => UIScreen([
Header(),
state === "empty" ? EmptyState("Nothing here yet") : UIScrollable(items.map(Card)),
])- Icons go through the compile-time macro
assetIcon("lucide:bell"): the SVG is vendored at build time, so screens render offline and deterministically.
Working with an AI assistant
init drops a CLAUDE.md into the folder — the conventions spec, written for the assistant — and registers the board's MCP server. While the server runs, Claude Code has the tools: render_screen (what a screen actually looks like — JSON or PNG), check_screens (a fast compile check), design_state (the live screens and edges), check_concept (coherence between spec.md and the screens) and board_activity (what you just did on the board). The assistant builds a screen, renders it, spots problems and fixes them — before showing you.
When the server is down, the same is available from the CLI:
lecodes design snapshot home --png # headless-render a screen → JSON/PNG
lecodes design check # coherence: edges, states, spec.md links
lecodes design arrange --new # place new screens next to their flow neighboursSharing the design
Inside a cloned project the design pushes with the rest of the files (lecodes push), and lecodes design share turns on a public link: anyone with it sees the working mockups — your app code stays private. Turn it off with lecodes design share --off.