codegen
Code generation utilities for json-render. Use when generating code from UI specs, building custom code exporters, traversing specs, or serializing props for…
Build JSON-defined TanStack Start applications with @json-render/tanstack-start. Use for Start route specs, splat routing, SSR loaders, head metadata, layouts, and client navigation. Do not use for generic TanStack Router apps that do not use json-render.
$ npx -y skills add vercel-labs/json-render --skill tanstack-start --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/tanstack-startContext preview
The summary Claude sees to decide when to auto-load this skill.
Build JSON-defined TanStack Start applications with @json-render/tanstack-start. Use for Start route specs, splat routing, SSR loaders, head metadata, layouts, and client navigation. Do not use for generic TanStack Router apps that do not use json-render.
name: tanstack-start description: Build JSON-defined TanStack Start applications with @json-render/tanstack-start. Use for Start route specs, splat routing, SSR loaders, head metadata, layouts, and client navigation. Do not use for generic TanStack Router apps that do not use json-render.
Use this integration when a TanStack Start app needs complete pages or routes described by json-render specs.
npm install @json-render/core @json-render/react @json-render/tanstack-start
Include the server-safe built-in definitions in the generation catalog. The renderer supplies their component implementations.
import { defineCatalog } from "@json-render/core";
import {
schema,
startComponentDefinitions,
} from "@json-render/tanstack-start/server";
const catalog = defineCatalog(schema, {
components: {
...startComponentDefinitions,
Card: cardDefinition,
Shell: shellDefinition,
Navigation: navigationDefinition,
Home: homeDefinition,
Post: postDefinition,
},
actions: {},
});Then use `StartAppSpec` and TanStack Router route patterns:
import type { StartAppSpec } from "@json-render/tanstack-start";
export const spec: StartAppSpec = {
metadata: {
title: { default: "Site", template: "%s | Site" },
},
layouts: {
main: {
root: "shell",
elements: {
shell: { type: "Shell", props: {}, children: ["nav", "slot"] },
nav: { type: "Navigation", props: {}, children: [] },
slot: { type: "Slot", props: {}, children: [] },
},
},
},
routes: {
"/": {
layout: "main",
metadata: { title: "Home" },
page: {
root: "home",
elements: {
home: { type: "Home", props: {}, children: [] },
},
},
},
"/posts/$slug": {
layout: "main",
loader: "post",
staticParams: [{ slug: "hello" }],
page: {
root: "post",
elements: {
post: {
type: "Post",
props: { value: { $state: "/post" } },
children: [],
},
},
},
},
},
};Routes use `/posts/$slug` for named parameters and `/docs/$` for a splat. Splat loader parameters are slash-delimited strings under `_splat`. Escape route-key slashes as `~1` when generating RFC 6902 patches.
Every layout needs a `Slot` element. Declare `Slot` and `Link` through `startComponentDefinitions`; do not require consumers to register React implementations for them.
import { createStartApp } from "@json-render/tanstack-start/server";
export const { getPageData, getHead, getStaticPaths } = createStartApp({
spec,
loaders: {
post: async ({ slug }) => ({ post: await getPost(slug as string) }),
},
});State merge precedence is application state, layout state, page state, then loader data. `getHead` merges app and route metadata into TanStack `meta` and `links` descriptors. `getStaticPaths` includes static routes plus dynamic routes with `staticParams`. Convert its strings to `{ path }` objects for TanStack Start's top-level `pages` plugin option. Loader params are URL-decoded, while values from `staticParams` are URL-encoded in generated paths. Route matching treats trailing slashes as optional and accepts encoded or decoded pathname representations so loader data and metadata resolve the same static route.
import { createFileRoute, notFound } from "@tanstack/react-router";
import {
PageRenderer,
StartErrorBoundary,
StartLoading,
StartNotFound,
} from "@json-render/tanstack-start";
import { getHead, getPageData } from "@/lib/json-app";
export const Route = createFileRoute("/$")({
loader: async ({ location }) => {
const data = await getPageData({ pathname: location.pathname });
if (!data) throw notFound();
return data;
},
head: ({ match }) => getHead({ pathname: match.pathname }),
component: () => <PageRenderer {...Route.useLoaderData()} />,
pendingComponent: StartLoading,
errorComponent: StartErrorBoundary,
notFoundComponent: StartNotFound,
});TanStack Router loaders run on both the server and client. If a spec factory or named loader uses credentials, database clients, or server-only imports, wrap `getPageData` and `getHead` in a TanStack Start `createServerFn`; do not import that server code directly into an isomorphic route loader.
Wrap the root route's `Outlet` with `StartAppProvider`. Render `HeadContent` so metadata from `getHead` reaches the document.
import {
createRootRoute,
HeadContent,
Outlet,
Scripts,
} from "@tanstack/react-router";
import { StartAppProvider } from "@json-render/tanstack-start";
import { spec } from "@/lib/spec";
export const Route = createRootRoute({
component: () => (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<StartAppProvider
registry={registry}
handlers={handlers}
spec={spec}
>
<Outlet />
</StartAppProvider>
<Scripts />
</body>
</html>
),
});Use `StartLoading`, `StartErrorBoundary`, and `StartNotFound` for TanStack Router's `pendingComponent`, `errorComponent`, and `notFoundComponent` options. When `StartAppProvider` receives `spec`, each component selects the matched route's corresponding fallback. Explicit fallback props override that lookup. Pass named `$computed` implementations through `StartAppProvider.functions`. The default error boundary invalidates the router and reruns a failed loader when the user selects **Try again**.
Import React components from `@json-render/tanstack-start`. Import `schema`, `createStartApp`, `matchRoute`, `resolveMetadata`, and static path helpers from `@json-render/tanstack-start/server`.
The Generative UI framework. Generate dynamic, personalized UIs from prompts without sacrificing reliability. Predefined components and actions for safe, predictable output.
Repo: vercel-labs/json-render
Code generation utilities for json-render. Use when generating code from UI specs, building custom code exporters, traversing specs, or serializing props for…
Core package for defining schemas, catalogs, and AI prompt generation for json-render. Use when working with @json-render/core, defining schemas, creating…
Drop-in inspector panel for any json-render app. Use when the user wants to debug a generative UI, inspect the spec tree, edit state at runtime, see dispatched…
Pre-built custom directives for json-render — formatting, math, string manipulation, and i18n. Use when working with @json-render/directives, defining custom…
Image renderer for json-render that turns JSON specs into SVG and PNG images via Satori. Use when working with @json-render/image, generating OG images from…
Ink terminal renderer for json-render that turns JSON specs into interactive terminal UIs. Use when working with @json-render/ink, building terminal UIs from…