Skip to content

feat(start): add @json-render/start — TanStack Start support - #309

Open
brunorodmoreira wants to merge 8 commits into
vercel-labs:mainfrom
brunorodmoreira:feat/tanstack-start
Open

feat(start): add @json-render/start — TanStack Start support#309
brunorodmoreira wants to merge 8 commits into
vercel-labs:mainfrom
brunorodmoreira:feat/tanstack-start

Conversation

@brunorodmoreira

@brunorodmoreira brunorodmoreira commented Jul 13, 2026

Copy link
Copy Markdown

Adds @json-render/start, a TanStack Start integration that mirrors the @json-render/next API, plus a start-website-builder example.

The schema/router/metadata core is ported from the next package and kept framework-agnostic. createStartApp wires routes, loaders and head descriptors into TanStack Router, and pages render through the same JSONUIProvider as the other integrations. Specs are serialized as plain JSON in loaders so they survive Start's SSR serialization.

The example is a port of next-website-builder running on Start: same website component catalog, resizable editor with live preview, and spec persistence through a server route.

Tested with the new vitest suites (schema, router, metadata, create-app), tsc --noEmit across the package and example, and manually in the browser (SSR, client navigation, head/metadata resolution).

Sets up the TanStack Start renderer package with dual client/server
entry points, tsup build config, and workspace wiring mirroring
@json-render/next conventions.
Ports the app spec schema, route matcher, and metadata resolver from
@json-render/next, adapted to TanStack conventions:

- Route patterns use $slug dynamic segments and $ splat (catch-all)
  instead of [slug]/[...path]; splat params captured under _splat
- resolveMetadata keeps Next-style merging semantics (title templates,
  shallow-merged openGraph/twitter); new metadataToHead compiles the
  result into TanStack Start head() meta/link descriptors
- collectStaticPaths returns concrete pathnames for prerender.pages
- Prompt template teaches TanStack Router URL patterns
Ports the app factory and React components from @json-render/next,
adapted to TanStack Start / TanStack Router:

- createStartApp returns getPageData({pathname}) / getHead({pathname})
  / getStaticPaths() for use in a $ splat catch-all route's loader,
  head() option, and prerender.pages config
- StartAppProvider/useStartApp hold registry + handlers and expose a
  navigate function backed by router.navigate({ to })
- PageRenderer wires State/Visibility/Validation/Action providers and
  injects page content into layout Slot components (same as next)
- Link wraps @tanstack/react-router Link; href→to, prefetch→preload
- StartErrorBoundary/StartLoading/StartNotFound map to the route's
  errorComponent/pendingComponent/notFoundComponent options
- No "use client" directives — TanStack Start is Vite-based, not RSC
- schema.test.ts mirrors @json-render/next's suite (validation shape,
  optional metadata, required children, inferred optional fields)
- router.test.ts covers $slug/$ splat extraction, _splat arrays,
  specificity ordering (static > dynamic > splat), and static path
  collection with staticParams expansion
- metadata.test.ts covers title templates, shallow og/twitter merging,
  and metadataToHead descriptor compilation (meta/links)
- create-app.test.ts covers state merge order (global < page < loader),
  loader params, layout resolution, async spec factories, getHead, and
  getStaticPaths
Replaces the hand-rolled StateProvider/VisibilityProvider/ValidationProvider/
ActionProvider stack (duplicated across the layout and no-layout branches)
with the combined JSONUIProvider from @json-render/react. Also picks up
FunctionsContext, DirectivesContext, and ConfirmationDialogManager, so
$computed functions, custom directives, and confirm-gated actions now work
on Start pages.
- Apply the global title template to route titles declared as
  { default: ... } objects, not just string titles (previously the raw
  object was returned and titleToString dropped the template entirely).
- Replace every %s occurrence in the template (Next.js uses a global
  replace), and use a function replacement so titles containing
  $-replacement patterns (e.g. "Cash $& Carry") are inserted verbatim.
- Add regression tests for all three behaviors.
Port of next-website-builder to TanStack Start, demonstrating
@json-render/start in a Start app:

- Catch-all `$.tsx` route SSR-rendering pages from the JSON spec via
  createStartApp + PageRenderer, with head() wired to getHead()
- /builder split-pane editor: JSON spec tree + live preview iframe
- GET/PUT /api/spec through route server.handlers backed by an
  in-memory spec store
- createServerFn (fetchSitePage) so client-side navigations read the
  live server spec store; wire-typed as JsonValue to satisfy Start's
  server-fn serializability check (Spec props are Record<string, unknown>)
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@brunorodmoreira is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​tanstack/​react-router@​1.170.17751008498100
Addednpm/​@​tanstack/​react-start@​1.168.27991008498100
Addednpm/​vite-tsconfig-paths@​5.1.410010010085100
Addednpm/​@​tailwindcss/​vite@​4.3.21001009098100

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant