vercel-labs / vercel-labs/json-render

Proposal: Stencil / Web Component renderer (discussion before PR)

Open
#289 0 comments 3 reactions 0 assignees View on GitHub

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:

  1. Plumbing core's pure functions into the framework's reactivity model
  2. 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

  1. 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.
  2. Path A, Path B, both, or neither? If both, would you prefer them as two packages (@json-render/stencil for the typed authoring story, @json-render/element for the framework-agnostic drop-in) or a single package that does both?
  3. Naming preference if Path B lands: @json-render/element / @json-render/web-component / something else?
  4. Devtools adapter: I see devtools-react/vue/svelte/solid follow 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.