
Svelte
Render JSON UI specs into Svelte 5 component trees with @json-render/svelte catalogs and a typed component registry.
Install
npx skills add https://github.com/vercel-labs/json-render --skill svelteWhat is this skill?
- Svelte 5 renderer converts json-render Spec objects into live component trees via Renderer and JsonUIProvider
- defineCatalog with @json-render/core plus zod-validated component props
- Components accept BaseComponentProps<TProps> for typed props wiring
- Supports AI-generated or programmatic JSON specs mapped through a local registry
Adoption & trust: 672 installs on skills.sh; 15k GitHub stars; 3/3 security scanners passed (skills.sh audits).
Recommended Skills
Frontend Designanthropics/skills
Vercel React Best Practicesvercel-labs/agent-skills
Remotion Best Practicesremotion-dev/skills
Vercel Composition Patternsvercel-labs/agent-skills
Develop Userscriptsxixu-me/skills
Next Best Practicesvercel-labs/next-skills
Journey fit
Common Questions / FAQ
Is Svelte safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Svelte
# @json-render/svelte Svelte 5 renderer that converts json-render specs into Svelte component trees. ## Quick Start ```svelte <script lang="ts"> import { Renderer, JsonUIProvider } from "@json-render/svelte"; import type { Spec } from "@json-render/svelte"; import Card from "./components/Card.svelte"; import Button from "./components/Button.svelte"; interface Props { spec: Spec | null; } let { spec }: Props = $props(); const registry = { Card, Button }; </script> <JsonUIProvider> <Renderer {spec} {registry} /> </JsonUIProvider> ``` ## Creating a Catalog ```typescript import { defineCatalog } from "@json-render/core"; import { schema } from "@json-render/svelte"; import { z } from "zod"; export const catalog = defineCatalog(schema, { components: { Button: { props: z.object({ label: z.string(), variant: z.enum(["primary", "secondary"]).nullable(), }), description: "Clickable button", }, Card: { props: z.object({ title: z.string() }), description: "Card container with title", }, }, }); ``` ## Defining Components Components should accept `BaseComponentProps<TProps>`: ```typescript interface BaseComponentProps<TProps> { props: TProps; // Resolved props for this component children?: Snippet; // Child elements (use {@render children()}) emit: (event: string) => void; // Fire a named event bindings?: Record<string, string>; // Map of prop names to state paths (for $bindState) loading?: boolean; // True while spec is streaming } ``` ```svelte <!-- Button.svelte --> <script lang="ts"> import type { BaseComponentProps } from "@json-render/svelte"; interface Props extends BaseComponentProps<{ label: string; variant?: string }> {} let { props, emit }: Props = $props(); </script> <button class={props.variant} onclick={() => emit("press")}> {props.label} </button> ``` ```svelte <!-- Card.svelte --> <script lang="ts"> import type { Snippet } from "svelte"; import type { BaseComponentProps } from "@json-render/svelte"; interface Props extends BaseComponentProps<{ title: string }> { children?: Snippet; } let { props, children }: Props = $props(); </script> <div class="card"> <h2>{props.title}</h2> {#if children} {@render children()} {/if} </div> ``` ## Creating a Registry ```typescript import { defineRegistry } from "@json-render/svelte"; import { catalog } from "./catalog"; import Card from "./components/Card.svelte"; import Button from "./components/Button.svelte"; const { registry, handlers, executeAction } = defineRegistry(catalog, { components: { Card, Button, }, actions: { submit: async (params, setState, state) => { // handle action }, }, }); ``` ## Spec Structure (Element Tree) The Svelte schema uses the element tree format: ```json { "root": "card1", "elements": { "card1": { "type": "Card", "props": { "title": "Hello" }, "children": ["btn1"] }, "btn1": { "type": "Button", "props": { "label": "Click me" } } } } ``` ## Visibility Conditions Use `visible` on elements to show/hide based on state: - `{ "$state": "/path" }` - truthy check - `{ "$state": "/path", "eq": value }` - equality check - `{ "$state": "/path", "not": true }` - falsy check - `{ "$and": [cond1, cond2] }` - AND conditions - `{ "$or": [cond1, cond2] }` - OR conditions ## Providers (via JsonUIProvider) `JsonUIProvider` composes all contexts. Individual contexts: | Context | Purpose | | ------------------- | -------------------------------------------------- | | `StateContext` | Share state across components (JSON Pointer pat