vercel-labs / vercel-labs/json-render
Proposal: Stencil / Web Component renderer (discussion before PR)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 16.8k
- Forks
- 901
- Avg merge
- 3h 14m
- Merged PRs (30d)
- 4
Description
Hi maintainers — opening this as a proposal/discussion before sinking time into a PR, since hasDiscussionsEnabled: false on the repo. Happy to move/close if there's a better venue.
Motivation
I'd like to use json-render with Stencil — primarily because Stencil is widely adopted for design-system authoring (Ionic, several internal DS at companies including the one I work at) and the output is plain Web Components, framework-agnostic.
After reading through packages/core, packages/svelte and packages/solid, two distinct paths emerge and I'd value your steer on which (if either) you'd accept:
Path A — @json-render/stencil
A renderer package symmetric to the existing ones, targeting Stencil component authors. defineRegistry accepts Stencil FunctionalComponents; Renderer is itself a Stencil component (<json-render-renderer>).
Path B — @json-render/element (framework-agnostic Web Component, built with Stencil)
The package ships a single Custom Element <json-render-renderer> that any host — Angular, Lit, plain HTML, htmx, Astro, even no framework — can drop in. The registry accepts either inline render functions or tag names (e.g. { Card: 'my-card' }), so users can register existing Web Components from any source. Stencil is just the authoring tool, not a peer dep for consumers.
Path B is the value-add I find most compelling: there's no current escape hatch from json-render's per-framework adapter model for hosts that don't have one. Path A is the more conventional addition; Path B is the more architecturally novel one.
Technical feasibility
Reading the codebase, the heavy lifting (resolveElementProps, resolveBindings, evaluateVisibility, resolveActionParam, createStateStore, SpecStream, JSON-Pointer) already lives in @json-render/core. A new adapter is mostly:
- Plumbing core's pure functions into the framework's reactivity model
- A substitute for Context API (the 7 providers: State/Visibility/Action/Validation/RepeatScope/Functions/Directives)
Stencil doesn't have a native Context API, but I noticed that StateContext, ActionContext, etc. are plain JS objects ({ get, set, update, getSnapshot, subscribe }) — not framework primitives. So they can be passed down as props through the internal renderer tree, or scoped via a per-instance singleton keyed on renderer id. No Context API required.
For comparison, scanning the Svelte and Solid adapters:
- ~110 LOC schema (copy-paste from existing adapter)
- ~200–870 LOC ElementRenderer
- ~975–1820 LOC context providers
- ~280 LOC defineRegistry / createRenderer
- ~530 LOC streaming utils
- Plus tests
So order-of-magnitude 3–4k LOC + tests, and the AGENTS.md checklist (README row, renderer section, apps/web/app/(main)/docs/api/<name>/page.mdx, page-titles + docs-navigation, docs-chat system prompt, skills/<name>/SKILL.md, package README).
Open questions for maintainers
- Is this within the scope you want to maintain in-monorepo, or would a community package be a better fit? The package list is already dense; I don't want to add load without buy-in.
- Path A, Path B, both, or neither? If both, would you prefer them as two packages (
@json-render/stencilfor the typed authoring story,@json-render/elementfor the framework-agnostic drop-in) or a single package that does both? - Naming preference if Path B lands:
@json-render/element/@json-render/web-component/ something else? - Devtools adapter: I see
devtools-react/vue/svelte/solidfollow each renderer. Would a Stencil/WC devtools adapter be expected in the same PR, or acceptable as a follow-up?
Commitment
If you're open to it, I'll follow the AGENTS.md workflow end-to-end: version sync, README packages table row, renderer section, API docs page, docs-chat system prompt entry, navigation entries, skill, package README, and pnpm type-check green before opening the PR. I'd ship Path B first if you have to pick one, since it's the broader unlock.
Happy to take this any direction you'd prefer — including "not now" or "build it as a community package first." Mainly want to align on direction before writing code.
Thanks!
Saludos desde Argentina 🇦🇷
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
First review packages/core, packages/svelte, packages/solid, and AGENTS.md, then obtain maintainer direction on Path A versus Path B and package scope before coding. If accepted, define the selected adapter's API, implement its renderer and context plumbing, add tests, and complete the listed documentation, package, skill, version-sync, and type-check updates.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, web-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100