/blocks/[blockId]/edit and in the canvas block editor overlay (?expanded=<id>&edit=1 or block ⋯ → Edit). The overlay is the primary authoring surface on canvas; the standalone route remains for direct links and embed blocks.
If you’d rather have your coding agent drive the same workflow over MCP, see Authoring via an agent. Both paths produce the same artifact.
Layout
The editor is a three-pane layout:- File tree on the left — virtual filesystem rooted at the block.
chatblocks.jsonis the manifest;src/App.tsxis the conventional entry for code blocks. Add, rename, and delete files inline. - Monaco in the center — full TypeScript + JSX language services with Tailwind class IntelliSense, multi-file open tabs, find-in-file, and the usual Monaco affordances.
- Live preview on the right — sandboxed iframe that re-renders as you edit. Two engines depending on
manifest.format(see below).
Save vs Publish
Two distinct operations, two distinct buttons.Save
Persists the current file set as the block’s working draft. Cheap — no build, no quota. Save freely while you iterate.
Publish
Triggers the Vercel Sandbox build of your current files, uploads the resulting HTML bundle to Convex storage, and cuts a new
blockPublishedVersions row. Counts against your monthly build quota.publishedVersionId stay on that version until you re-pin them.
Preview engines
The live preview branches onmanifest.format:
- format: code
- format: embed
Sandpack compiles your source in-browser. The conventional entry is
src/App.tsx, declared via the manifest’s entry field. Sandpack supports TSX, hooks, and the dependency set you declare in package.json.The Sandpack preview reflects your unsaved edits live — you don’t need to Save first to see them.code blocks use Sandpack, which compiles your file as TSX. If you try to drop a full <!DOCTYPE html> HTML document into a code block’s entry, Sandpack rejects it. Set format to embed with an external URL, or build the page in JSX.
Hide-header toggle
The preview frame ships with a small block header (block name, owner). The toolbar has a toggle to hide it while you’re working on visuals that own the full canvas. This is client-only state — it’s not persisted to the block manifest. Each time you reload the editor the header is back.File constraints
Each block carries a virtual filesystem with hard caps, enforced server-side byconvex/lib/blockFiles.ts:
Hit the cap and Save returns an error listing every offending file. The same cap applies whether you’re editing in-app or pushing via MCP
blocks.setFiles — agents see the same error.
Dependencies and lockfiles
Forformat: code blocks, your package.json declares the runtime dependencies. Two valid shapes:
- Exact-version deps
- Lockfile
^, ~, *) are rejected."network" in manifest.permissions and list the allowed origins in manifest.network.allowedOrigins — see Manifest.
What’s next
Manifest
The full
chatblocks.json schema — formats, sizes, widget, binding, permissions.Runtime
What’s available inside the iframe — render paths, sandbox model, data injection.