
Vue
Render AI- or agent-generated JSON UI specs into Vue 3 component trees with catalogs, registries, and data-bound actions.
Overview
vue is an agent skill for the Build phase that teaches solo builders to render JSON UI specs in Vue 3 with @json-render/vue catalogs and registries.
Install
npx skills add https://github.com/vercel-labs/json-render --skill vueWhat is this skill?
- defineCatalog + defineRegistry pattern for typed Vue components and actions
- Converts JSON specs to Vue trees with visibility, data binding, and emit handlers
- Requires @json-render/vue, @json-render/core, vue ^3.5, zod ^4
- Documented quick start: catalog props with zod, registry render functions via h()
Adoption & trust: 754 installs on skills.sh; 15k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You have machine-readable UI JSON but no consistent Vue 3 pipeline to validate props and mount component trees safely.
Who is it for?
Indie builders using Vue 3 who receive JSON UI specs from agents or APIs and want typed catalogs instead of one-off dynamic components.
Skip if: Teams on React-only stacks, static marketing sites with no JSON-driven UI, or projects that will not adopt @json-render/core and Zod schemas.
When should I use this skill?
Building Vue UIs from JSON specs, working with @json-render/vue, defining Vue component registries, or rendering AI-generated specs in Vue.
What do I get? / Deliverables
You get a catalog-plus-registry setup that turns JSON specs into bound Vue UIs ready to wire into your app or agent output loop.
- Typed component catalog
- Vue registry with h() mappings
- Renderable JSON spec pipeline
Recommended Skills
Journey fit
Canonical shelf is Build because the skill implements product UI from structured specs using Vue 3, catalogs, and h()-based registries. Frontend subphase matches Vue renderer work: component registries, JSON-to-tree rendering, and peer deps vue ^3.5 and zod.
How it compares
Use as a Vue renderer integration skill, not a full design-system generator or MCP server for arbitrary APIs.
Common Questions / FAQ
Who is vue for?
Solo and indie frontend builders on Vue 3 who integrate @json-render and need agent-friendly JSON-to-UI rendering.
When should I use vue?
During Build frontend work when defining Vue registries, binding AI-generated specs, or evaluating json-render for your stack.
Is vue safe to install?
Review the Security Audits panel on this Prism page and inspect the skill source in your repo before granting agent filesystem or network access.
SKILL.md
READMESKILL.md - Vue
# @json-render/vue Vue 3 renderer that converts JSON specs into Vue component trees with data binding, visibility, and actions. ## Installation ```bash npm install @json-render/vue @json-render/core zod ``` Peer dependencies: `vue ^3.5.0` and `zod ^4.0.0`. ## Quick Start ### Create a Catalog ```typescript import { defineCatalog } from "@json-render/core"; import { schema } from "@json-render/vue/schema"; import { z } from "zod"; export const catalog = defineCatalog(schema, { components: { Card: { props: z.object({ title: z.string(), description: z.string().nullable() }), description: "A card container", }, Button: { props: z.object({ label: z.string(), action: z.string() }), description: "A clickable button", }, }, actions: {}, }); ``` ### Define Registry with h() Render Functions ```typescript import { h } from "vue"; import { defineRegistry } from "@json-render/vue"; import { catalog } from "./catalog"; export const { registry } = defineRegistry(catalog, { components: { Card: ({ props, children }) => h("div", { class: "card" }, [ h("h3", null, props.title), props.description ? h("p", null, props.description) : null, children, ]), Button: ({ props, emit }) => h("button", { onClick: () => emit("press") }, props.label), }, }); ``` ### Render Specs ```vue <script setup lang="ts"> import { StateProvider, ActionProvider, Renderer } from "@json-render/vue"; import { registry } from "./registry"; const spec = { root: "card-1", elements: { /* ... */ } }; </script> <template> <StateProvider :initial-state="{ form: { name: '' } }"> <ActionProvider :handlers="{ submit: handleSubmit }"> <Renderer :spec="spec" :registry="registry" /> </ActionProvider> </StateProvider> </template> ``` ## Providers | Provider | Purpose | |----------|---------| | `StateProvider` | Share state across components (JSON Pointer paths). Accepts `initialState` or `store` for controlled mode. | | `ActionProvider` | Handle actions dispatched via the event system | | `VisibilityProvider` | Enable conditional rendering based on state | | `ValidationProvider` | Form field validation | ## Composables | Composable | Purpose | |------------|---------| | `useStateStore()` | Access state context (`state` as `ShallowRef`, `get`, `set`, `update`) | | `useStateValue(path)` | Get single value from state | | `useIsVisible(condition)` | Check if a visibility condition is met | | `useActions()` | Access action context | | `useAction(binding)` | Get a single action dispatch function | | `useFieldValidation(path, config)` | Field validation state | | `useBoundProp(propValue, bindingPath)` | Two-way binding for `$bindState`/`$bindItem` | Note: `useStateStore().state` returns a `ShallowRef<StateModel>` — use `state.value` to access. ## External Store (StateStore) Pass a `StateStore` to `StateProvider` to wire json-render to Pinia, VueUse, or any state management: ```typescript import { createStateStore, type StateStore } from "@json-render/vue"; const store = createStateStore({ count: 0 }); ``` ```vue <StateProvider :store="store"> <Renderer :spec="spec" :registry="registry" /> </StateProvider> ``` ## Dynamic Prop Expressions Props support `$state`, `$bindState`, `$cond`, `$template`, `$computed`. Use `{ "$bindState": "/path" }` on the natural value prop for two-way binding. ## Visibility Conditions ```typescript { "$state": "/user/isAdmin" } { "$state": "/status", "eq": "active" } { "$state": "/maintenance", "not": true } [ cond1, cond2 ] // implicit AND ``` ## Built-in Actions `setState`, `pushState`, `removeState`, and `validateForm` are built into the Vue schema and handled by `ActionProvider`: ```json { "action": "setS