TanStack Router

TanStack Router — a fully type-safe web router — ported onto Sparkling to drive native multi-page navigation. Each page is a separate LynxView with its own JS context; navigating between pages is a native container open, connected by a generated file-based route manifest.

The full design, the feature support matrix, and the comparison with TanStack's own React Native effort are in the TanStack Router guide. These demos come from the tanstack-router-demo package.

Web preview vs. on device

The web preview runs the router live in your browser, so every button below navigates for real. In-page navigation (routes within one bundle) uses TanStack Router's in-memory history. Cross-page navigation goes through the Sparkling bridge: on a real device each page is a separate native LynxView with its own JS context, but a go-web <Go> card renders a single bundle and can't swap to another, so the bridge routes the open back into this card and renders the destination route in-page (the bundle already carries the whole route tree). You still see the path and search params cross the boundary via the scheme — scan the QR code tab to see the true native page split on device.

Router on ReactLynx (single page)

The feasibility spike: TanStack Router running on ReactLynx with a memory history. Tap → go to /about — this is a live in-page route transition (typed search params included), no native bridge involved.

Multi-page app (MPA)

The home bundle of the multi-page demo. Home ↔ Profile is an in-page transition (both live in this one bundle). The Detail and Settings buttons cross a native-page boundary: on device they open separate native LynxViews, and their path/search params arrive in the fresh JS context via the launch scheme. In this web preview all four navigate live — the Sparkling bridge renders the cross-page destinations in-page here (see the tip above), and the location: line shows the params making the trip. Tap Detail #42 → to watch /detail/42?ref=home render with id=42 reconstructed from the scheme.

Page-transition animation is the container's job, not the app's: on device a cross-page open animates through the native container (the animated flag on sparkling-navigation's open/close). The go-web web preview renders the destination in-page and doesn't reproduce that container animation, so the swap here is instant — scan the QR code to see the native transition on device.

How it's wired

Browse the source in the embeds above. The key pieces:

  • src/routes/* — file-based routes (createFileRoute), plus a page export marking native-page boundaries (our MPA extension).
  • src/routeTree.gen.ts — generated by the official @tanstack/router-generator, running inside the Rspeedy build.
  • src/routes.manifest.ts + src/page-entries.gen.ts — generated by scripts/gen-mpa.mjs: the route→bundle mapping and one entry per native page.
  • src/mpa/create-router.tsx — wires createRouter to sparkling-navigation through the reusable sparkling-history shim (createMpaHistory + createSparklingHost).
  • src/shims/* — the four bundler-level shims that let TanStack Router run on ReactLynx (no react-dom, no DOM).