Velloo documentation
Markdown for LLMs ↗MCP: codegen
emit_code and emit_snippet return agent-consumed IR in the screen framework's native idiom; emit_theme writes the framework's theme artifacts and a DTCG tokens file.
Velloo is the design source; the agent is the bridge to code. emit_code and emit_snippet return a structured, JSX-shaped intermediate representation meant for the agent to read and transform into the user’s app code, using the app’s conventions, routing, and providers. It is not paste-ready output: no import statements, no function wrapper, no prettier pass. emit_theme is the exception: direct, user-facing artifacts that need no agent translation. Workflow: Emit to code.
Emit is per screen or per snippet. Board layout (frames, positions, groups) is canvas metadata and is never part of the emitted code.
emit_code
Return agent-consumed IR for a screen, plus a full diagnostic pass over it.
| Arg | Type | Required | Description |
|---|---|---|---|
screenId | string | yes | |
componentsAlias | string | no | Overrides the components import prefix the IR is built against. Defaults to config.codegen.componentsAlias, else @/components/ui |
Returns:
| Field | Description |
|---|---|
screen | { id, name } |
jsx | The JSX body: no imports, no wrapper |
componentsUsed | Library component identifiers referenced in the tree |
iconsUsed | Icon names rendered as JSX tags (<ArrowRight />), imported from lucide-react |
snippetsUsed | Each referenced snippet’s own IR (the emit_snippet shape), to materialize as a component or inline |
classesUsed | Unique Tailwind classes in the emitted JSX |
componentsToInstall | shadcn primitives the app needs, as kebab names ready for npx shadcn@latest add. Empty for native-framework and inline-style targets |
helpersToMaterialize | Velloo composition helpers with runtime logic (such as Gradient, SVG, Image, Layer, Divider) that the agent must author in the app. Empty for native-framework and inline-style targets |
warnings | Non-fatal caveats: things JSX couldn’t express faithfully, such as an unresolved icon name |
tailwindV3Compat | Only when the host app is on Tailwind v3: [{ class, v3?, note }], the v4 classes to rename (or rework) while writing the file, covering the screen and its snippets |
diagnostics | Only when there is something to fix: the full-screen diagnostics pass |
The JSX uses the screen framework’s native idiom:
- shadcn: library component identifiers with Tailwind classes
- MUI (and other native-framework libraries): components imported from the framework’s own module, styled with
sxobjects - no-framework, Tailwind channel: plain-HTML primitives with Tailwind classes
- no-framework, inline-style channel (a
none/nonefolder): Tailwind-free plain HTML with inlinestyleobjects
Snippet instances emit as component references with the snippet’s PascalCase name, matching emit_snippet; an instance’s extra classes pass as a className prop. An instance carrying $overrides can’t be expressed by the shared component, so its body is inlined instead: args substituted, overrides and extra classes applied. Extension nodes emit under their own id with the extension’s declared importPath. A node carrying $emitAs emits as a bare <Name /> of the named host component instead of its design subtree.
Errors: ScreenNotFound, UnknownComponent, SnippetNotFound.
emit_snippet
Same idea, scoped to a single snippet.
| Arg | Type | Required | Description |
|---|---|---|---|
snippetId | string | yes | |
componentsAlias | string | no | Same default chain as emit_code |
Returns { id, componentName, params, jsx, componentsToInstall, helpersToMaterialize, warnings }: the PascalCase component name, the typed params (name, type, and default / optional where declared), and the JSX body with $param references emitted as {name}, plus tailwindV3Compat and diagnostics under the same conditions as emit_code.
emit_theme
Generate theme artifacts for the folder’s default library from a theme. Dry-run by default; the output is direct: write it as returned.
| Arg | Type | Required | Description |
|---|---|---|---|
outputDir | string | yes | Target app directory (relative paths resolve from the design folder root) |
cssPath | string | no | Tailwind targets: globals.css location relative to outputDir; default app/globals.css (pass globals.css or src/index.css for Vite/Astro layouts) |
themePath | string | no | Native-framework targets: theme module location relative to outputDir; default depends on the framework (theme.ts for MUI) |
apply | boolean | no | Write the files. Default false; dry-run returns per-file diffs |
cssOnly | boolean | no | Tailwind targets: skip the Tailwind config (v4) or preset (v3) file |
theme | string | no | Named theme to emit; default "default" |
tailwind | 3 or 4 | no | Force the Tailwind major of the emitted artifacts. Default: detected from outputDir’s package.json, falling back to v4 |
cssPath and themePath must stay inside outputDir; an absolute path or one that escapes with .. is rejected.
Per target:
- Tailwind v4 (shadcn and Tailwind-channel folders):
globals.cssatcssPath, with the token tree as CSS custom properties and an@themeblock, and the folder’s custom CSS appended; atypeset.cssstylesheet next to it, whichglobals.cssimports; andtailwind.config.tsinoutputDirunlesscssOnly. - Tailwind v3: never overwrites the app’s globals file. It writes
velloo-theme.cssin the same directory ascssPath(custom CSS appended), avelloo-typeset.cssbeside it, and, unlesscssOnly, a Tailwind preset inoutputDir:velloo.preset.tswhen the app has a TypeScript Tailwind config, otherwisevelloo.preset.cjs.notesspell out the@importlines and thepresetsregistration to add by hand. - Native frameworks: a theme module at
themePathexportingtheme, built with the framework’s factory (createTheme(...)for MUI,extendTheme(...)for Chakra UI), plus adarkThemeexport when the theme defines dark colors.
Every target also writes a framework-neutral DTCG tokens.json in outputDir.
Returns { files, warnings?, notes? }. Each file entry carries path, contents, a diff against what’s on disk, and whether it was applied. On Tailwind targets, warnings flag palette tokens skipped because they would shadow a semantic slot, and what tokens.json leaves out; native-framework targets return files only.