Every block has aDocumentation Index
Fetch the complete documentation index at: https://docs.chatblocks.ai/llms.txt
Use this file to discover all available pages before exploring further.
chatblocks.json manifest at the root of its file set. The manifest is the contract between your code and the platform: it declares the format, the canvas footprint, what data flows in, and what the iframe is allowed to do.
The full Zod schema lives in packages/shared/src/manifest.ts. This page covers the shape; the schema there is the source of truth and what the server validates against.
Minimal manifest
A barebonescode block with no widget or data binding:
Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
schemaVersion | 1 | yes | Currently always 1. Schema bumps go through a coordinated migration. |
format | "code" | "embed" | no (defaults to "code") | See Formats. |
entry | string | yes for code, must be absent for embed | Relative path ending in .js, .jsx, .ts, .tsx, or .html. No URLs, absolute paths, parent traversal, or backslashes. |
defaultSize | { width, height } | yes | Canvas footprint in pixels. Each dimension is an integer in [50, 2000]. |
constraints | object | no | Min/max resize bounds. Defaults to 0.6×/2.5× of defaultSize, clamped to [50, 2000]. |
resizable | boolean | no (defaults true) | Set false for fixed-shape blocks like a stamp or a specific-aspect-ratio widget. |
permissions | array | no (defaults []) | See Permissions. |
network | object | no | { allowedOrigins: [] }. Required when "network" permission is declared. |
embed | object | yes for embed, must be absent for code | See Formats. |
widget | object | no | iOS widget projection. See Widget. |
binding | object | no | Live-data binding. See Binding. |
Formats
ChatBlocks has two first-class formats. The bar for adding a new one is a platform invariant the AI generator can’t be trusted to uphold on its own — everything else stayscode.
- code
- embed
Vibe-coded block. Your file set is built into an iframe-loaded artifact via Vercel Sandbox. Strict CSP, no cross-origin framing, sandboxed iframe.Required:
entry must be a relative path to a file in your set. Conventional: src/App.tsx.Permissions
Declare the capabilities yourcode block needs. Each is opt-in.
| Permission | Grants |
|---|---|
viewer.profile | Read the viewer’s display name and avatar (when permitted by visibility). |
storage.kv | Per-block key/value storage scoped to the viewer. |
assets | Upload and serve static assets via Convex storage. |
events | Emit custom events into the audit log. |
forms | Render <form> elements with submission posting back to the platform. |
network | Make outbound HTTP requests. Requires network.allowedOrigins to be set. |
network permission and network.allowedOrigins are coupled — declaring one without the other is a validation error. Origins must be HTTPS, origin-only (no path/query/hash/credentials, no wildcards).
Binding
Optional. Connects the block to a configured data source so the platform refreshes its widget data on a cron (or push) cadence.queryConfig.type is one of KNOWN_QUERY_TYPES (see packages/shared/src/binding.ts):
stripe.mrr,stripe.balance,stripe.recentChargespostgres.sqlwebhook.latest,webhook.aggregate,webhook.listmcp.tool
projection maps raw query output into the widget’s data shape. Each field is either { source, format?, formatOptions? } (pluck from the query result with optional formatting) or { literal } (constant value). Formats: currency, number, percent, percent-with-sign, datetime.
Cross-reference: the Connecting data section walks through each connector and the queries it supports.
Constraints reference
constraints.min* and constraints.max* set the block’s resize bounds on a canvas. Defaults are derived from defaultSize:
min*=defaultSize.* × 0.6, clamped to ≥ 50.max*=defaultSize.* × 2.5, clamped to ≤ 2000.
min ≤ max for each axis, and defaultSize must lie within [min, max].
Validation errors
When validation fails, the API returns a list of issues, each with a stable code:| Code | Meaning |
|---|---|
missing_entry | code format requires entry. |
invalid_entry | entry path failed the relative-path / extension check. |
unexpected_entry | embed format must not declare entry. |
missing_embed | embed format requires embed.url. |
invalid_embed_url | URL is not HTTPS, has credentials, or has a non-public hostname. |
unexpected_embed | code format must not declare embed. |
invalid_constraint | min > max on width or height. |
default_size_out_of_bounds | defaultSize falls outside constraints. |
duplicate_permission | Same permission listed twice. |
missing_network_permission | network.allowedOrigins declared without the "network" permission. |
missing_network_origins | "network" permission declared without any origins. |
invalid_origin | An origin failed the HTTPS-origin-only check. |
unsupported_permissions | embed format must not declare permissions. |
unsupported_network | embed format must not declare network.allowedOrigins. |
unrecognized_field | Unknown top-level field. |
What’s next
Widget
The iOS widget projection — six templates, five themes, sample-data schema.
Runtime
What happens at render time — render paths, sandbox, data injection.