@thorprovider/create-storefront 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +119 -0
  2. package/bin/install.js +116 -0
  3. package/commands/sf-add-view.md +21 -0
  4. package/commands/sf-init.md +16 -0
  5. package/commands/sf-theme.md +15 -0
  6. package/commands/sf-view.md +20 -0
  7. package/package.json +40 -0
  8. package/recipes/archetype.schema.json +39 -0
  9. package/recipes/archetypes.json +148 -0
  10. package/recipes/recipe.schema.json +59 -0
  11. package/recipes/recipes.json +90 -0
  12. package/recipes/sections.json +46 -0
  13. package/recipes/validate.mjs +190 -0
  14. package/skills/building-storefronts/SKILL.md +178 -0
  15. package/skills/building-storefronts/references/frontend-integration.md +229 -0
  16. package/skills/json-render-core/SKILL.md +291 -0
  17. package/skills/json-render-next/SKILL.md +194 -0
  18. package/skills/json-render-react/SKILL.md +298 -0
  19. package/skills/json-render-remotion/SKILL.md +111 -0
  20. package/skills/json-render-shadcn/SKILL.md +159 -0
  21. package/skills/json-render-solid/SKILL.md +204 -0
  22. package/skills/nextjs-shadcn/SKILL.md +303 -0
  23. package/skills/nextjs-shadcn/references/architecture.md +499 -0
  24. package/skills/nextjs-shadcn/references/project-setup.md +127 -0
  25. package/skills/nextjs-shadcn/references/shadcn-platform.md +258 -0
  26. package/skills/nextjs-shadcn/references/sidebar.md +274 -0
  27. package/skills/nextjs-shadcn/references/styling.md +555 -0
  28. package/skills/sf-scaffold/SKILL.md +118 -0
  29. package/skills/sf-theme-gen/SKILL.md +44 -0
  30. package/skills/sf-view-gen/SKILL.md +94 -0
  31. package/skills/shadcn-component-discovery/SKILL.md +273 -0
  32. package/skills/shadcn-component-discovery/references/registries.md +226 -0
  33. package/skills/shadcn-theming/SKILL.md +104 -0
  34. package/skills/shadcn-theming/references/templates/theme-setup.md +109 -0
  35. package/skills/shadcn-theming/references/theming-guide.md +90 -0
  36. package/skills/storefront-best-practices/SKILL.md +421 -0
  37. package/skills/storefront-best-practices/reference/components/breadcrumbs.md +123 -0
  38. package/skills/storefront-best-practices/reference/components/cart-popup.md +189 -0
  39. package/skills/storefront-best-practices/reference/components/country-selector.md +298 -0
  40. package/skills/storefront-best-practices/reference/components/footer.md +112 -0
  41. package/skills/storefront-best-practices/reference/components/hero.md +241 -0
  42. package/skills/storefront-best-practices/reference/components/megamenu.md +239 -0
  43. package/skills/storefront-best-practices/reference/components/navbar.md +397 -0
  44. package/skills/storefront-best-practices/reference/components/popups.md +221 -0
  45. package/skills/storefront-best-practices/reference/components/product-card.md +125 -0
  46. package/skills/storefront-best-practices/reference/components/product-reviews.md +217 -0
  47. package/skills/storefront-best-practices/reference/components/product-slider.md +174 -0
  48. package/skills/storefront-best-practices/reference/components/search.md +101 -0
  49. package/skills/storefront-best-practices/reference/connecting-to-backend.md +391 -0
  50. package/skills/storefront-best-practices/reference/design.md +388 -0
  51. package/skills/storefront-best-practices/reference/features/promotions.md +307 -0
  52. package/skills/storefront-best-practices/reference/features/wishlist.md +230 -0
  53. package/skills/storefront-best-practices/reference/layouts/account.md +380 -0
  54. package/skills/storefront-best-practices/reference/layouts/cart.md +316 -0
  55. package/skills/storefront-best-practices/reference/layouts/checkout.md +486 -0
  56. package/skills/storefront-best-practices/reference/layouts/home-page.md +264 -0
  57. package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +231 -0
  58. package/skills/storefront-best-practices/reference/layouts/product-details.md +527 -0
  59. package/skills/storefront-best-practices/reference/layouts/product-listing.md +520 -0
  60. package/skills/storefront-best-practices/reference/layouts/static-pages.md +356 -0
  61. package/skills/storefront-best-practices/reference/medusa.md +307 -0
  62. package/skills/storefront-best-practices/reference/mobile-responsiveness.md +183 -0
  63. package/skills/storefront-best-practices/reference/seo.md +195 -0
  64. package/templates/app/app/[[...slug]]/page.tsx +17 -0
  65. package/templates/app/app/[[...slug]]/renderer.tsx +10 -0
  66. package/templates/app/app/globals.css +101 -0
  67. package/templates/app/app/layout.tsx +35 -0
  68. package/templates/app/lib/__STOREFRONT__/catalog.ts +132 -0
  69. package/templates/app/lib/__STOREFRONT__/handlers.ts +33 -0
  70. package/templates/app/lib/__STOREFRONT__/registry.tsx +134 -0
  71. package/templates/app/lib/__STOREFRONT__/runtime.ts +25 -0
  72. package/templates/app/lib/__STOREFRONT__/spec/home.ts +62 -0
  73. package/templates/app/lib/__STOREFRONT__/spec/index.ts +59 -0
  74. package/templates/app/lib/__STOREFRONT__/spec/types.ts +14 -0
  75. package/templates/app/lib/__STOREFRONT__/state.ts +35 -0
@@ -0,0 +1,194 @@
1
+ ---
2
+ name: next
3
+ description: Next.js renderer for json-render that turns JSON specs into full Next.js applications with routes, layouts, SSR, and metadata. Use when working with @json-render/next, building Next.js apps from JSON specs, or creating AI-generated multi-page applications.
4
+ ---
5
+
6
+ # @json-render/next
7
+
8
+ Next.js renderer that converts JSON specs into full Next.js applications with routes, pages, layouts, metadata, and SSR support.
9
+
10
+ ## Quick Start
11
+
12
+ ```bash
13
+ npm install @json-render/core @json-render/react @json-render/next
14
+ ```
15
+
16
+ ### 1. Define Your Spec
17
+
18
+ ```typescript
19
+ // lib/spec.ts
20
+ import type { NextAppSpec } from "@json-render/next";
21
+
22
+ export const spec: NextAppSpec = {
23
+ metadata: {
24
+ title: { default: "My App", template: "%s | My App" },
25
+ description: "A json-render Next.js application",
26
+ },
27
+ layouts: {
28
+ main: {
29
+ root: "shell",
30
+ elements: {
31
+ shell: { type: "Container", props: {}, children: ["nav", "slot"] },
32
+ nav: { type: "NavBar", props: { links: [
33
+ { href: "/", label: "Home" },
34
+ { href: "/about", label: "About" },
35
+ ]}, children: [] },
36
+ slot: { type: "Slot", props: {}, children: [] },
37
+ },
38
+ },
39
+ },
40
+ routes: {
41
+ "/": {
42
+ layout: "main",
43
+ metadata: { title: "Home" },
44
+ page: {
45
+ root: "hero",
46
+ elements: {
47
+ hero: { type: "Card", props: { title: "Welcome" }, children: [] },
48
+ },
49
+ },
50
+ },
51
+ "/about": {
52
+ layout: "main",
53
+ metadata: { title: "About" },
54
+ page: {
55
+ root: "content",
56
+ elements: {
57
+ content: { type: "Card", props: { title: "About Us" }, children: [] },
58
+ },
59
+ },
60
+ },
61
+ },
62
+ };
63
+ ```
64
+
65
+ ### 2. Create the App
66
+
67
+ ```typescript
68
+ // lib/app.ts
69
+ import { createNextApp } from "@json-render/next/server";
70
+ import { spec } from "./spec";
71
+
72
+ export const { Page, generateMetadata, generateStaticParams } = createNextApp({
73
+ spec,
74
+ loaders: {
75
+ // Server-side data loaders (optional)
76
+ loadPost: async ({ slug }) => {
77
+ const post = await getPost(slug as string);
78
+ return { post };
79
+ },
80
+ },
81
+ });
82
+ ```
83
+
84
+ ### 3. Wire Up Route Files
85
+
86
+ ```tsx
87
+ // app/[[...slug]]/page.tsx
88
+ export { Page as default, generateMetadata, generateStaticParams } from "@/lib/app";
89
+ ```
90
+
91
+ ```tsx
92
+ // app/[[...slug]]/layout.tsx
93
+ import { NextAppProvider } from "@json-render/next";
94
+ import { registry, handlers } from "@/lib/registry";
95
+
96
+ export default function Layout({ children }: { children: React.ReactNode }) {
97
+ return (
98
+ <html lang="en">
99
+ <body>
100
+ <NextAppProvider registry={registry} handlers={handlers}>
101
+ {children}
102
+ </NextAppProvider>
103
+ </body>
104
+ </html>
105
+ );
106
+ }
107
+ ```
108
+
109
+ ## Key Concepts
110
+
111
+ ### NextAppSpec
112
+
113
+ The top-level spec defines an entire Next.js application:
114
+
115
+ - **metadata**: Root-level SEO metadata (title template, description, OpenGraph)
116
+ - **layouts**: Reusable layout element trees (each must include a `Slot` component)
117
+ - **routes**: Route definitions keyed by URL pattern
118
+ - **state**: Global initial state shared across all routes
119
+
120
+ ### Route Patterns
121
+
122
+ Routes use Next.js URL conventions:
123
+
124
+ - `"/"` -- home page
125
+ - `"/about"` -- static route
126
+ - `"/blog/[slug]"` -- dynamic segment
127
+ - `"/docs/[...path]"` -- catch-all segment
128
+ - `"/settings/[[...path]]"` -- optional catch-all segment
129
+
130
+ ### Layouts
131
+
132
+ Layouts wrap page content. Every layout MUST include a `Slot` component where page content will be rendered. Layouts are defined once in `spec.layouts` and referenced by routes via the `layout` field.
133
+
134
+ ### Built-in Components
135
+
136
+ - **Slot**: Placeholder in layouts where page content is rendered
137
+ - **Link**: Client-side navigation link (wraps `next/link`)
138
+
139
+ ### Built-in Actions
140
+
141
+ - **setState**: Update state value. Params: `{ statePath, value }`
142
+ - **pushState**: Append to array. Params: `{ statePath, value, clearStatePath? }`
143
+ - **removeState**: Remove from array by index. Params: `{ statePath, index }`
144
+ - **navigate**: Client-side navigation. Params: `{ href }`
145
+
146
+ ### Data Loaders
147
+
148
+ Server-side async functions that run in the Server Component before rendering. Results are merged into the page's initial state.
149
+
150
+ ```typescript
151
+ createNextApp({
152
+ spec,
153
+ loaders: {
154
+ loadPost: async ({ slug }) => {
155
+ const post = await db.post.findUnique({ where: { slug } });
156
+ return { post };
157
+ },
158
+ },
159
+ });
160
+ ```
161
+
162
+ ### SSR
163
+
164
+ Pages are server-rendered automatically. The `createNextApp` `Page` component is an async Server Component that:
165
+
166
+ 1. Matches the route from the spec
167
+ 2. Runs server-side data loaders
168
+ 3. Generates metadata
169
+ 4. Passes the resolved spec to the client renderer for hydration
170
+
171
+ ### Entry Points
172
+
173
+ - `@json-render/next` -- Client components (NextAppProvider, PageRenderer, Link)
174
+ - `@json-render/next/server` -- Server utilities (createNextApp, matchRoute, schema)
175
+
176
+ ## API Reference
177
+
178
+ ### Server Exports (`@json-render/next/server`)
179
+
180
+ - `createNextApp(options)` -- Create Page, generateMetadata, generateStaticParams
181
+ - `schema` -- Custom schema for Next.js apps (for AI catalog generation)
182
+ - `matchRoute(spec, pathname)` -- Match a URL to a route spec
183
+ - `resolveMetadata(spec, route)` -- Resolve metadata for a route
184
+ - `slugToPath(slug)` -- Convert catch-all slug array to pathname
185
+ - `collectStaticParams(spec)` -- Collect static params for all routes
186
+
187
+ ### Client Exports (`@json-render/next`)
188
+
189
+ - `NextAppProvider` -- Context provider for registry and handlers
190
+ - `PageRenderer` -- Renders a page spec with optional layout
191
+ - `NextErrorBoundary` -- Error boundary component
192
+ - `NextLoading` -- Loading state component
193
+ - `NextNotFound` -- Not-found component
194
+ - `Link` -- Built-in navigation component (wraps next/link)
@@ -0,0 +1,298 @@
1
+ ---
2
+ name: react
3
+ description: React renderer for json-render that turns JSON specs into React components. Use when working with @json-render/react, building React UIs from JSON, creating component catalogs, or rendering AI-generated specs.
4
+ ---
5
+
6
+ # @json-render/react
7
+
8
+ React renderer that converts JSON specs into React component trees.
9
+
10
+ ## Quick Start
11
+
12
+ ```typescript
13
+ import { defineRegistry, Renderer } from "@json-render/react";
14
+ import { catalog } from "./catalog";
15
+
16
+ const { registry } = defineRegistry(catalog, {
17
+ components: {
18
+ Card: ({ props, children }) => <div>{props.title}{children}</div>,
19
+ },
20
+ });
21
+
22
+ function App({ spec }) {
23
+ return <Renderer spec={spec} registry={registry} />;
24
+ }
25
+ ```
26
+
27
+ ## Creating a Catalog
28
+
29
+ ```typescript
30
+ import { defineCatalog } from "@json-render/core";
31
+ import { schema } from "@json-render/react/schema";
32
+ import { defineRegistry } from "@json-render/react";
33
+ import { z } from "zod";
34
+
35
+ // Create catalog with props schemas
36
+ export const catalog = defineCatalog(schema, {
37
+ components: {
38
+ Button: {
39
+ props: z.object({
40
+ label: z.string(),
41
+ variant: z.enum(["primary", "secondary"]).nullable(),
42
+ }),
43
+ description: "Clickable button",
44
+ },
45
+ Card: {
46
+ props: z.object({ title: z.string() }),
47
+ slots: ["default"],
48
+ description: "Card container with title",
49
+ },
50
+ Layout: {
51
+ props: z.object({}),
52
+ slots: ["default", "header", "footer"],
53
+ description: "Layout with named content regions",
54
+ },
55
+ },
56
+ });
57
+
58
+ // Define component implementations with type-safe props
59
+ const { registry } = defineRegistry(catalog, {
60
+ components: {
61
+ Button: ({ props }) => (
62
+ <button className={props.variant}>{props.label}</button>
63
+ ),
64
+ Card: ({ props, children }) => (
65
+ <div className="card">
66
+ <h2>{props.title}</h2>
67
+ {children}
68
+ </div>
69
+ ),
70
+ Layout: ({ children, slots }) => (
71
+ <div>
72
+ <header>{slots?.header}</header>
73
+ <main>{children}</main>
74
+ <footer>{slots?.footer}</footer>
75
+ </div>
76
+ ),
77
+ },
78
+ });
79
+ ```
80
+
81
+ ## Spec Structure (Element Tree)
82
+
83
+ The React schema uses an element tree format:
84
+
85
+ ```json
86
+ {
87
+ "root": {
88
+ "type": "Card",
89
+ "props": { "title": "Hello" },
90
+ "children": [{ "type": "Button", "props": { "label": "Click me" } }]
91
+ }
92
+ }
93
+ ```
94
+
95
+ ## Named Slots
96
+
97
+ Use `children` for the `"default"` slot. Use the element's top-level `slots` object for other slot names declared by the catalog:
98
+
99
+ ```json
100
+ {
101
+ "type": "Layout",
102
+ "props": {},
103
+ "children": ["main"],
104
+ "slots": {
105
+ "header": ["heading"],
106
+ "footer": ["actions"]
107
+ }
108
+ }
109
+ ```
110
+
111
+ Registry components receive named content as `slots?.header`, `slots?.footer`, and so on. Do not use `slots.default`.
112
+
113
+ ## Visibility Conditions
114
+
115
+ Use `visible` on elements to show/hide based on state. New syntax: `{ "$state": "/path" }`, `{ "$state": "/path", "eq": value }`, `{ "$state": "/path", "not": true }`, `{ "$and": [cond1, cond2] }` for AND, `{ "$or": [cond1, cond2] }` for OR. Helpers: `visibility.when("/path")`, `visibility.unless("/path")`, `visibility.eq("/path", val)`, `visibility.and(cond1, cond2)`, `visibility.or(cond1, cond2)`.
116
+
117
+ ## Providers
118
+
119
+ | Provider | Purpose |
120
+ | -------------------- | ------------------------------------------------------------------------------------------------------ |
121
+ | `StateProvider` | Share state across components (JSON Pointer paths). Accepts optional `store` prop for controlled mode. |
122
+ | `ActionProvider` | Handle actions dispatched via the event system |
123
+ | `VisibilityProvider` | Enable conditional rendering based on state |
124
+ | `ValidationProvider` | Form field validation |
125
+
126
+ ### External Store (Controlled Mode)
127
+
128
+ Pass a `StateStore` to `StateProvider` (or `JSONUIProvider` / `createRenderer`) to use external state management (Redux, Zustand, XState, etc.):
129
+
130
+ ```tsx
131
+ import { createStateStore, type StateStore } from "@json-render/react";
132
+
133
+ const store = createStateStore({ count: 0 });
134
+
135
+ <StateProvider store={store}>{children}</StateProvider>;
136
+
137
+ // Mutate from anywhere — React re-renders automatically:
138
+ store.set("/count", 1);
139
+ ```
140
+
141
+ When `store` is provided, `initialState` and `onStateChange` are ignored.
142
+
143
+ ## Dynamic Prop Expressions
144
+
145
+ Any prop value can be a data-driven expression resolved by the renderer before components receive props:
146
+
147
+ - **`{ "$state": "/state/key" }`** - reads from state model (one-way read)
148
+ - **`{ "$bindState": "/path" }`** - two-way binding: reads from state and enables write-back. Use on the natural value prop (value, checked, pressed, etc.) of form components.
149
+ - **`{ "$bindItem": "field" }`** - two-way binding to a repeat item field. Use inside repeat scopes.
150
+ - **Filtered lists**: `repeat` plus an `$item` visible condition on the same container renders only matching items: `{ "repeat": { "statePath": "/tasks", "key": "id" }, "visible": { "$item": "status", "eq": "todo" }, "children": ["task-card"] }`. AND-composed `$state` conjuncts gate the container shell; `$item`/`$index` conjuncts filter items.
151
+ - **Nested lists**: inside a repeat, use `{ "repeat": { "statePath": { "$item": "comments" }, "key": "id" } }` to iterate an array on the enclosing item.
152
+ - **`{ "$cond": <condition>, "$then": <value>, "$else": <value> }`** - conditional value
153
+ - **`{ "$template": "Hello, ${/name}!" }`** - interpolates state values into strings
154
+ - **`{ "$computed": "fn", "args": { ... } }`** - calls registered functions with resolved args
155
+
156
+ ```json
157
+ {
158
+ "type": "Input",
159
+ "props": {
160
+ "value": { "$bindState": "/form/email" },
161
+ "placeholder": "Email"
162
+ }
163
+ }
164
+ ```
165
+
166
+ Components do not use a `statePath` prop for two-way binding. Use `{ "$bindState": "/path" }` on the natural value prop instead.
167
+
168
+ Components receive already-resolved props. For two-way bound props, use the `useBoundProp` hook with the `bindings` map the renderer provides.
169
+
170
+ Register `$computed` functions via the `functions` prop on `JSONUIProvider` or `createRenderer`:
171
+
172
+ ```tsx
173
+ <JSONUIProvider
174
+ functions={{ fullName: (args) => `${args.first} ${args.last}` }}
175
+ >
176
+ ```
177
+
178
+ ## Event System
179
+
180
+ Components use `emit` to fire named events, or `on()` to get an event handle with metadata. The element's `on` field maps events to action bindings:
181
+
182
+ ```tsx
183
+ // Simple event firing
184
+ Button: ({ props, emit }) => (
185
+ <button onClick={() => emit("press")}>{props.label}</button>
186
+ ),
187
+
188
+ // Event handle with metadata (e.g. preventDefault)
189
+ Link: ({ props, on }) => {
190
+ const click = on("click");
191
+ return (
192
+ <a href={props.href} onClick={(e) => {
193
+ if (click.shouldPreventDefault) e.preventDefault();
194
+ click.emit();
195
+ }}>{props.label}</a>
196
+ );
197
+ },
198
+ ```
199
+
200
+ ```json
201
+ {
202
+ "type": "Button",
203
+ "props": { "label": "Submit" },
204
+ "on": { "press": { "action": "submit" } }
205
+ }
206
+ ```
207
+
208
+ The `EventHandle` returned by `on()` has: `emit()`, `shouldPreventDefault` (boolean), and `bound` (boolean).
209
+
210
+ ## State Watchers
211
+
212
+ Elements can declare a `watch` field (top-level, sibling of type/props/children) to trigger actions when state values change:
213
+
214
+ ```json
215
+ {
216
+ "type": "Select",
217
+ "props": {
218
+ "value": { "$bindState": "/form/country" },
219
+ "options": ["US", "Canada"]
220
+ },
221
+ "watch": { "/form/country": { "action": "loadCities" } },
222
+ "children": []
223
+ }
224
+ ```
225
+
226
+ ## Built-in Actions
227
+
228
+ The `setState`, `pushState`, `removeState`, and `validateForm` actions are built into the React schema and handled automatically by `ActionProvider`. They are injected into AI prompts without needing to be declared in catalog `actions`:
229
+
230
+ ```json
231
+ { "action": "setState", "params": { "statePath": "/activeTab", "value": "home" } }
232
+ { "action": "pushState", "params": { "statePath": "/items", "value": { "text": "New" } } }
233
+ { "action": "removeState", "params": { "statePath": "/items", "index": 0 } }
234
+ { "action": "validateForm", "params": { "statePath": "/formResult" } }
235
+ ```
236
+
237
+ `validateForm` validates all registered fields and writes `{ valid, errors }` to state.
238
+
239
+ Note: `statePath` in action params (e.g. `setState.statePath`) targets the mutation path. Two-way binding in component props uses `{ "$bindState": "/path" }` on the value prop, not `statePath`.
240
+
241
+ ## useBoundProp
242
+
243
+ For form components that need two-way binding, use `useBoundProp` with the `bindings` map the renderer provides when a prop uses `{ "$bindState": "/path" }` or `{ "$bindItem": "field" }`:
244
+
245
+ ```tsx
246
+ import { useBoundProp } from "@json-render/react";
247
+
248
+ Input: ({ element, bindings }) => {
249
+ const [value, setValue] = useBoundProp<string>(
250
+ element.props.value,
251
+ bindings?.value
252
+ );
253
+ return (
254
+ <input
255
+ value={value ?? ""}
256
+ onChange={(e) => setValue(e.target.value)}
257
+ />
258
+ );
259
+ },
260
+ ```
261
+
262
+ `useBoundProp(propValue, bindingPath)` returns `[value, setValue]`. The `value` is the resolved prop; `setValue` writes back to the bound state path (no-op if not bound).
263
+
264
+ ## BaseComponentProps
265
+
266
+ For building reusable component libraries not tied to a specific catalog (e.g. `@json-render/shadcn`):
267
+
268
+ ```typescript
269
+ import type { BaseComponentProps } from "@json-render/react";
270
+
271
+ const Card = ({ props, children }: BaseComponentProps<{ title?: string }>) => (
272
+ <div>{props.title}{children}</div>
273
+ );
274
+ ```
275
+
276
+ ## defineRegistry
277
+
278
+ `defineRegistry` conditionally requires the `actions` field only when the catalog declares actions. Catalogs with `actions: {}` can omit it.
279
+
280
+ ## Key Exports
281
+
282
+ | Export | Purpose |
283
+ | ----------------------- | ----------------------------------------------------------------------------------------------------- |
284
+ | `defineRegistry` | Create a type-safe component registry from a catalog |
285
+ | `Renderer` | Render a spec using a registry |
286
+ | `schema` | Element tree schema (includes built-in state actions: setState, pushState, removeState, validateForm) |
287
+ | `useStateStore` | Access state context |
288
+ | `useStateValue` | Get single value from state |
289
+ | `useBoundProp` | Two-way binding for `$bindState`/`$bindItem` expressions |
290
+ | `useActions` | Access actions context |
291
+ | `useAction` | Get a single action dispatch function |
292
+ | `useOptionalValidation` | Non-throwing variant of useValidation (returns null if no provider) |
293
+ | `useUIStream` | Stream specs from an API endpoint |
294
+ | `createStateStore` | Create a framework-agnostic in-memory `StateStore` |
295
+ | `StateStore` | Interface for plugging in external state management |
296
+ | `BaseComponentProps` | Catalog-agnostic base type for reusable component libraries |
297
+ | `EventHandle` | Event handle type (`emit`, `shouldPreventDefault`, `bound`) |
298
+ | `ComponentContext` | Typed component context (catalog-aware) |
@@ -0,0 +1,111 @@
1
+ ---
2
+ name: remotion
3
+ description: Remotion renderer for json-render that turns JSON timeline specs into videos. Use when working with @json-render/remotion, building video compositions from JSON, creating video catalogs, or rendering AI-generated video timelines.
4
+ ---
5
+
6
+ # @json-render/remotion
7
+
8
+ Remotion renderer that converts JSON timeline specs into video compositions.
9
+
10
+ ## Quick Start
11
+
12
+ ```typescript
13
+ import { Player } from "@remotion/player";
14
+ import { Renderer, type TimelineSpec } from "@json-render/remotion";
15
+
16
+ function VideoPlayer({ spec }: { spec: TimelineSpec }) {
17
+ return (
18
+ <Player
19
+ component={Renderer}
20
+ inputProps={{ spec }}
21
+ durationInFrames={spec.composition.durationInFrames}
22
+ fps={spec.composition.fps}
23
+ compositionWidth={spec.composition.width}
24
+ compositionHeight={spec.composition.height}
25
+ controls
26
+ />
27
+ );
28
+ }
29
+ ```
30
+
31
+ ## Using Standard Components
32
+
33
+ ```typescript
34
+ import { defineCatalog } from "@json-render/core";
35
+ import {
36
+ schema,
37
+ standardComponentDefinitions,
38
+ standardTransitionDefinitions,
39
+ standardEffectDefinitions,
40
+ } from "@json-render/remotion";
41
+
42
+ export const videoCatalog = defineCatalog(schema, {
43
+ components: standardComponentDefinitions,
44
+ transitions: standardTransitionDefinitions,
45
+ effects: standardEffectDefinitions,
46
+ });
47
+ ```
48
+
49
+ ## Adding Custom Components
50
+
51
+ ```typescript
52
+ import { z } from "zod";
53
+
54
+ const catalog = defineCatalog(schema, {
55
+ components: {
56
+ ...standardComponentDefinitions,
57
+ MyCustomClip: {
58
+ props: z.object({ text: z.string() }),
59
+ type: "scene",
60
+ defaultDuration: 90,
61
+ description: "My custom video clip",
62
+ },
63
+ },
64
+ });
65
+
66
+ // Pass custom component to Renderer
67
+ <Player
68
+ component={Renderer}
69
+ inputProps={{
70
+ spec,
71
+ components: { MyCustomClip: MyCustomComponent },
72
+ }}
73
+ />
74
+ ```
75
+
76
+ ## Timeline Spec Structure
77
+
78
+ ```json
79
+ {
80
+ "composition": { "id": "video", "fps": 30, "width": 1920, "height": 1080, "durationInFrames": 300 },
81
+ "tracks": [{ "id": "main", "name": "Main", "type": "video", "enabled": true }],
82
+ "clips": [
83
+ { "id": "clip-1", "trackId": "main", "component": "TitleCard", "props": { "title": "Hello" }, "from": 0, "durationInFrames": 90 }
84
+ ],
85
+ "audio": { "tracks": [] }
86
+ }
87
+ ```
88
+
89
+ ## Standard Components
90
+
91
+ | Component | Type | Description |
92
+ |-----------|------|-------------|
93
+ | `TitleCard` | scene | Full-screen title with subtitle |
94
+ | `TypingText` | scene | Terminal-style typing animation |
95
+ | `ImageSlide` | image | Full-screen image display |
96
+ | `SplitScreen` | scene | Two-panel comparison |
97
+ | `QuoteCard` | scene | Quote with attribution |
98
+ | `StatCard` | scene | Animated statistic display |
99
+ | `TextOverlay` | overlay | Text overlay |
100
+ | `LowerThird` | overlay | Name/title overlay |
101
+
102
+ ## Key Exports
103
+
104
+ | Export | Purpose |
105
+ |--------|---------|
106
+ | `Renderer` | Render spec to Remotion composition |
107
+ | `schema` | Timeline schema |
108
+ | `standardComponents` | Pre-built component registry |
109
+ | `standardComponentDefinitions` | Catalog definitions |
110
+ | `useTransition` | Transition animation hook |
111
+ | `ClipWrapper` | Wrap clips with transitions |