Add ZodRecord and ZodDefault cases to formatZodType() in both core and
yaml packages. Fix ZodLiteral to support Zod 4's def.values array
in addition to Zod 3's def.value.
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add @json-render/gsplat package
Standalone Gaussian Splatting renderer using Hugging Face's gsplat.js.
Provides GaussianSplat and GaussianSplatViewer components with progress
indicator, orbit controls, and Zod-based catalog definitions — no
Three.js dependency required.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add GaussianSplat component to react-three-fiber
Adds GaussianSplat to the R3F renderer using drei's Splat loader,
bringing the component count to 20. Splats are composable with all
existing R3F components (lights, controls, post-processing, etc.).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add standalone gsplat example
Demo app showcasing @json-render/gsplat with 5 scenes (bonsai, garden,
bicycle, kitchen, stump) loaded from Hugging Face datasets. Includes
scene selector, live JSON spec viewer, and progress indicator.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add react-three-fiber gsplat example
Demo app showcasing GaussianSplat in R3F with 5 scenes: splat showroom,
splat with primitives, multi-splat, post-processing effects (bloom +
vignette), and animated floating splat with sparkles.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add gsplat API reference and update navigation
Adds API documentation for @json-render/gsplat, updates the R3F docs
to reflect 20 components, and registers both example apps in the
docs navigation, examples list, and page titles.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: add changeset and update lockfile for gsplat
Adds @json-render/gsplat to the fixed version group and creates a
changeset for the minor release of gsplat and react-three-fiber.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: wire up GaussianSplatViewer props to gsplat.js API
The catalog declared controls, autoRotate, autoRotateSpeed,
cameraPosition, cameraTarget, and fov props but the component
silently ignored them. Now:
- cameraPosition sets camera.position via SPLAT.Vector3
- cameraTarget calls controls.setCameraTarget()
- fov converts to focal length via camera.data.fx/fy
- controls=false skips OrbitControls creation
- autoRotate rotates the camera around Y in the render loop
- Updated gsplat.d.ts with full Camera/OrbitControls type surface
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(gsplat): address review issues — transforms, progress bar, themeable colors
- Apply per-splat position/rotation/scale after LoadAsync (splats were
rendering at origin regardless of config)
- Add eulerToQuaternion helper to convert Vec3 degrees to Quaternion
- Expose Splat class and correct LoadAsync return type (Promise<Splat>)
in gsplat.d.ts so transforms can be applied imperatively
- Forward visible prop through GaussianSplatHandle and SplatEntry
- Fix progress bar regression: use Math.max so bar never jumps backwards
- Make ProgressIndicator colors themeable via progressBarColor,
progressTrackColor, progressTextColor, progressBackgroundColor props
on GaussianSplatViewer
- Remove quality/alphaHash/toneMapped from standalone gsplat catalog —
these gsplat.js renderer has no equivalent API for them (they remain
in @json-render/react-three-fiber where drei's Splat supports them)
- Fix pre-existing TS2769/TS2322 Vec3 type errors in GaussianSplat.tsx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(gsplat): pass required progress color props in example
The new themeable progress indicator props are nullable (required keys
that accept null) in the catalog schema. The example was missing them,
causing TS2739 in CI.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(gsplat): drop standalone @json-render/gsplat package
Per discussion in #259, the standalone gsplat viewer is better positioned
as an experimental example than as a published package — there's no real
spec tree to compose, and the R3F GaussianSplat component already covers
the productized use case.
- Remove packages/gsplat (was @json-render/gsplat)
- Inline the viewer component into examples/gsplat as an experimental demo
- Drop @json-render/{core,react,gsplat} deps from the example
- Remove gsplat from changeset config and feat-gsplat.md
- Remove docs/api/gsplat page and its navigation entries
- Update README to drop the standalone install/snippet
* fix(gsplat): address review issues, add ExtrudedText component, improve a11y
- Fix GridHelper prop names (color1/color2 → color/secondaryColor) in all R3F scene files
- Fix Text3D prop mismatch in splat-with-primitives (size → fontSize, remove unsupported bevel/font props)
- Fix autoRotate to orbit around camera target instead of world origin
- Add ExtrudedText component to @json-render/react-three-fiber (geometry-based 3D text with depth, bevel, and custom font support)
- Add multi-offset scene to gsplat example to demonstrate off-center orbit
- Redesign splat-with-primitives scene (triangle logo + extruded label, remove floor plane)
- Improve gsplat example accessibility (ARIA labels, keyboard nav, semantic HTML, focus management)
- Debounce resize handler and use consistent 100dvh in gsplat viewer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Lucian Fialho <lucianfialhobp@hotmail.com>
* feat(web): fetch GitHub star count dynamically
Replace the hardcoded "12k" star count in the header with a live value
from the GitHub API, revalidated every 24 hours. Gracefully hides the
count if the fetch fails.
* fix: add GITHUB_TOKEN to turbo.json globalEnv
* fix: remove GITHUB_TOKEN usage from star count fetch
* Update official links to use json-render.dev domain
- Change dashboard example Docs link from json-render.vercel.app to json-render.dev
- Change Svelte Chat demo URL from json-render-svelte-chat-demo.labs.vercel.dev to svelte-chat-demo.json-render.dev
Fixes#264
* Revert svelte-chat demo URL change
Keep the original labs.vercel.dev URL for the Svelte Chat demo.
---------
Co-authored-by: ctate <366502+ctate@users.noreply.github.com>
Add outputFileTracingIncludes so the Geist font TTF is bundled at the
symlink path the code reads from. In a pnpm monorepo the file was only
traced at the .pnpm store path, which Vercel does not map back to the
node_modules/geist/ symlink.
The Remotion schema defines props on composition entries, but generatePrompt
did not include those props in its output. As a result, the model had no
knowledge of the expected prop shape when generating JSON, causing runtime
failures when prop names didn't match the component's expected interface.
Changes:
- Import zod type for TypeScript support
- Extract formatZodType from PromptContext
- Add props field to component type definition
- Include formatted props string in component description
Fixes#224
* init
* fix: resolve all type errors, runtime bugs, and test failures in @json-render/shadcn-svelte
- Add /index.js extensions to all ../ui/* imports (NodeNext moduleResolution)
- Type shadcnComponents as Record<string, Component<any>> to fix d.ts generation
- Call getBoundProp() once at top level instead of inside a binding() function
called from event handlers (getContext() only works during initialization)
- Move getOptionalValidationContext() call to top level; update createValidation()
to accept the context as first param instead of calling getContext() itself
- Wrap validation.register() in untrack() to break the fieldConfigs read-write
cycle that caused effect_update_depth_exceeded in tests
- Fix implicit any on Input onkeydown handler (KeyboardEvent type)
- Use untrack() for $state() initializers that read reactive props values
- Call getStateValue() once at top level in Dialog/Drawer (not in a function
called from event handlers)
- Fix test fixtures: use named imports { StateProvider, ValidationProvider }
- Add server.deps.inline for bits-ui and @lucide/svelte so vitest can process
their .svelte source files; add root svelte.config.js with runes: true
- Add role/aria-modal/tabindex/onkeydown a11y attributes to Dialog and Drawer
- Fix self-closing non-void elements in Skeleton, Spinner, Textarea
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* update shadcn-svelte components
* fixes
* fixes
* fix: address PR review issues for shadcn-svelte renderer
- Fix missing comma in .changeset/config.json (invalid JSON)
- Fix Slider.svelte type errors (single-mode expects number, not array)
- Replace raw <button> with shadcn Button in Pagination.svelte
- Remove global font import and body/html overrides from app.css
- Remove root svelte.config.js (duplicates package-level config)
- Revert unrelated packageManager version bump
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add @json-render/ink terminal renderer and ink-chat example
Adds a new `@json-render/ink` package that brings json-render specs to
terminal UIs via Ink (React for CLIs). Includes 24 standard components
(layout, text, inputs, markdown, etc.), context providers for state,
validation, visibility, actions, focus, and repeat scopes, plus a
streaming JSONL hook for progressive spec rendering.
Also adds an `ink-chat` example app demonstrating an AI chat interface
in the terminal with streaming responses, tool calls, and interactive
wizard flows.
Includes 76 tests (24 unit + 52 e2e), docs page, and web app integration.
* feat: show live spec preview during streaming
Render the spec progressively as JSONL patches arrive instead of only
showing a spinner. The preview disappears when streaming completes and
the finalized message replaces it in history.
* feat: clip streaming preview to 6 lines
* refactor: move spinner into input box, show full streaming preview
* fix: skip spacer during streaming to prevent clipping tall previews
* fix: strip invisible colors on dark terminal backgrounds
Drop foreground colors like "black" and "#000000" from AI-generated
specs so text remains readable on dark terminals. Removed hardcoded
color="black" from Badge and added safeColor() guard to all components
that accept user-specified color props.
* fix: always show spacer to keep input pinned to bottom
* fix: show dash placeholder for empty values in Table and KeyValue
Empty or null values in Table cells and KeyValue now render as "—"
instead of blank space. Also removed dimColor from ListItem subtitle
and trailing for better readability on dark terminals.
* fix: division by zero in Sparkline sampling when maxWidth is 1
* fix: Review feedback
Signed-off-by: Alexis Rico <sferadev@gmail.com>
* fix: Update readme
Signed-off-by: Alexis Rico <sferadev@gmail.com>
---------
Signed-off-by: Alexis Rico <sferadev@gmail.com>
pnpm creates separate copies of remotion@4.0.418 when peer dependency
versions differ between workspace packages (e.g. react@19.2.3 vs
react@19.2.4). This causes two React contexts, so useVideoConfig()
in @json-render/remotion cannot see the Player's context.
Add turbopack.resolveAlias to force all remotion imports to resolve
from the app's node_modules, ensuring a single instance.
* add yaml wire format and universal edit modes
**Summary**
- Add `@json-render/yaml` package with streaming parser, YAML prompt generation, and AI SDK transform
- Add universal edit modes (patch, merge, diff) to `@json-render/core`, usable across both JSONL and YAML formats
- Integrate YAML support and edit mode selection into the web playground with format toggle, token usage display, and prompt caching
* improvements
* fixes
* fixes ci
* docs
* feat: add strict mode to jsonSchema() for LLM structured outputs
This PR adds support for generating strict JSON schemas compatible with LLM structured output APIs (OpenAI, Google Gemini, Anthropic, etc.).
## Problem
`catalog.jsonSchema()` was generating schemas that OpenAI's strict mode rejected due to:
- Use of `propertyNames` keyword (not permitted)
- Missing `additionalProperties: false` on nested objects
- Optional properties not being handled correctly for strict validation
## Changes
- Added `JsonSchemaOptions` interface with `strict` boolean flag
- Updated `catalog.jsonSchema()` to accept optional `JsonSchemaOptions` parameter
- When `strict: true`, the schema generator:
- Sets `additionalProperties: false` on all object types
- Removes `propertyNames` constraints
- Lists all properties (including optional ones) in `required` arrays, using nullable types for optionals
- Converts record types to fixed-key objects without additional property schemas
- Fixed Zod 4 compatibility issue in type name resolution
- Added comprehensive test suite covering all strict mode requirements
- Exported `JsonSchemaOptions` type from core package
## Usage
```typescript
// Default behavior (unchanged)
const schema = catalog.jsonSchema();
// Strict mode for LLM APIs
const strictSchema = catalog.jsonSchema({ strict: true });
```
The default behavior remains unchanged to maintain backward compatibility.
Fixes#180
* fix: document record type limitation and add anyOf nullable test
- Add clear JSDoc documenting that record/map types become opaque objects
in strict mode (LLM strict schemas require additionalProperties: false)
- Improve inline comment on the record case in zodToJsonSchema
- Add test exercising the anyOf nullable wrapping for optional properties
using a non-record schema so the path is directly verified
---------
Co-authored-by: ctate <366502+ctate@users.noreply.github.com>
* solid: add renderer implementation
This adds a Solid renderer with the same core capabilities as the
existing framework packages, including typed registry helpers,
providers, streaming hooks, docs, and example integration.
* fix: solid reactivity bugs in validation + state
---------
Co-authored-by: Patrick <phall@Patricks-MacBook-Pro.local>
This PR adds the changeset file to prepare for the v0.12.1 release, documenting important breaking changes and bug fixes.
## Changes
**@json-render/core**
- Renamed generation modes from `"generate"`/`"chat"` to `"standalone"`/`"inline"` (old names deprecated with warnings)
**@json-render/mcp**
- Fixed React duplicate module error causing `useRef` to return null by adding Vite `resolve.dedupe` configuration
- Added `./build-app-html` export entry point
**Other improvements**
- Updated homepage URLs across all packages to https://json-render.dev
- Reorganized skills directory structure
- Added skills documentation page to web app
Fixes#198
Fixes a React runtime error where `useRef` was null due to multiple React instances being bundled.
## Changes Made
- **Vite configuration**: Added `resolve.dedupe` for `react` and `react-dom` in `examples/mcp/vite.config.ts` to ensure only one instance of React is used during bundling
- **React version constraints**: Changed from exact versions (`19.2.3`) to flexible ranges (`^19.0.0`) in `examples/mcp/package.json` to improve compatibility
- **Build entry point**: Added new `build-app-html-entry.ts` file and updated `tsup.config.ts` to include it as a build target
- **Package exports**: Added `./build-app-html` export path in `packages/mcp/package.json`
- **Minor fixes**: Updated Next.js type reference path in stripe-app example
The root cause was React being duplicated in the bundle, causing hooks like `useRef` to fail when components tried to access React's internal state from the wrong instance. The `dedupe` configuration ensures Vite resolves all React imports to the same module instance.
Fixes#190