Add TanStack Router + Start support to live mode

Live mode had no TanStack coverage: a TanStack Start user hit disconnects
and static previews because there is no static index.html to inject and no
adapter for the SSR root document.

- New tanstack-adapter.mjs, modeled on the SvelteKit/Nuxt adapters: detects
  a TanStack Start project (@tanstack/react-start + src/routes/__root.tsx)
  and patches the __root document to mount a generated dev-only React
  component (src/impeccable/ImpeccableLiveRoot) that appends the live bundle
  on the client after hydration, carrying the ?token= param via
  buildLiveScriptSrc. Patch/unpatch round-trips byte-for-byte and is
  idempotent; refuses to clobber an unmanaged file at the component path.
- Wire detection into live-inject.mjs (insert + remove + gitignore),
  ordered so SvelteKit/Nuxt win and a plain TanStack Router SPA falls
  through to the baseline Vite index.html path.
- tanstack-router-vite fixture (baseline, no adapter) and tanstack-start
  fixture (SSR adapter), both with runtime blocks. Both pass the full
  live-e2e cycle (handshake, steer, pick, Go, cycle, accept, carbonize,
  reloadProbe).
- Unit tests for detection + patch round-trip + apply/remove; tanstack-start
  branches in framework-fixtures.test.mjs; live.md framework table + adapter note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-07-22 22:49:44 -07:00
co-authored by Claude Fable 5
parent d4d02b69f2
commit 4cd5ea7547
22 changed files with 786 additions and 1 deletions
@@ -0,0 +1,12 @@
import { createRouter as createTanStackRouter } from '@tanstack/react-router';
import { routeTree } from './routeTree.gen';
export function getRouter() {
return createTanStackRouter({ routeTree, scrollRestoration: true });
}
declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof getRouter>;
}
}
@@ -0,0 +1,26 @@
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router';
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'TanStack Start Fixture' },
],
}),
shellComponent: RootDocument,
});
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
);
}
@@ -0,0 +1,14 @@
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/')({
component: Home,
});
function Home() {
return (
<main className="page">
<h1 className="hero-title">Start Home Hero</h1>
<p className="hero-hook">Server-rendered by TanStack Start.</p>
</main>
);
}