@xmachines/play-solid-router-demo
Examples / @xmachines/play-solid-router-demo
SolidJS Router adapter demonstration with authentication flow using the XMachines Play architecture and provider-based router integration.
What This Demonstrates
- Shared auth machine reused without framework-specific business logic
PlayRouterProviderrenderer-based integration with Solid Router- Shell-driven rendering via
PlayRendererwith actor-authoritative navigation - Canonical TC39 Signals lifecycle integration with Solid’s fine-grained reactivity
- Non-browser invariant tests plus browser E2E coverage
Running the Demo
From the repository root:
npm installnpm run dev -w @xmachines/play-solid-router-demoThen open http://localhost:3002.
Step-by-Step Code Flow
Use this order to understand the implementation:
src/main.tsxbootstraps the demo and mounts<App />onto#app.src/runtime.tssets up the actor, registry, routes, and route map — all shared module-level singletons.src/App.tsxwires Solid Router routes and thePlayRouterProviderusing the runtime exports.- A
routeMapis created by callingcreateRouteMap(authMachine)insrc/runtime.ts. PlayRouterProviderforwards navigation intent from@solidjs/routerto the actor, and reflects actor-approved routes back to the URL.Shell(from@xmachines/play-solid-demo) renders actor-projected views (PlayRenderer) and provides the shared UI shell.test/library-pattern.test.tsandtest/browser/verify invariants and runtime routing behavior.
// src/main.tsx (shape)render(() => <App />, document.getElementById("app")!);// src/runtime.ts (shape)const createPlayer = definePlayer({ machine: authMachine });export const actor = createPlayer();actor.start();
export const routeMap = createRouteMap(authMachine);// src/App.tsx (shape)const Layout: ParentComponent = () => { const navigate = useNavigate(); const location = useLocation(); const params = useParams();
return ( <PlayRouterProvider actor={actor} routeMap={routeMap} router={{ navigate, location, params }} renderer={(currentActor, currentRouter) => ( <Shell actor={currentActor} router={currentRouter} registryResult={registryResult} /> )} /> );};Key Files
src/runtime.ts- actor lifecycle, registry, route extraction, and route map creationsrc/App.tsx- Solid Router wiring,PlayRouterProviderintegration, and renderer compositionsrc/main.tsx- Vite bootstrap that mounts<App />via Solid’srendertest/library-pattern.test.ts- architecture boundary and invariant assertionstest/browser/shared-demo.browser.test.ts- browser startup and full auth flow coverage
State Machine & Architecture Details
The demo utilizes XMachines architectural invariants:
- Actor Authority: When a user navigates to a protected route, the Solid Router updates the URL. The
PlayRouterProviderintercepts this, translates it to aplay.routeevent, and sends it to the actor. The actor evaluates guards (e.g., is the user logged in?) and transitions to the appropriate state. - Passive Infrastructure: Solid components hold no business state. They observe
actor.currentViewto know what to render, andactor.currentRouteto reflect the active path. - Signal-Only Reactivity: Instead of React-like re-renders, Solid uses
createEffectinternally within theRouterBridgeto react precisely when signals update.
Watcher Lifecycle and Cleanup Contract
This demo follows the canonical watcher lifecycle:
notifyqueueMicrotaskgetPending()- Read actor signals and update Solid-local render triggers
- Re-arm with
watch()/watch(...signals)
Watcher notifications are one-shot. Cleanup is explicit and lifecycle-bound: Solid teardown uses onCleanup, and provider/bridge teardown must call disconnect/unwatch paths rather than relying on GC-only cleanup. This is crucial to prevent memory leaks during component unmounting.
Adapter Boundaries
Solid Router integration remains passive infrastructure. RouterBridgeBase stays the shared policy point; the Solid adapter only implements framework port behavior (calling navigate() and tracking location.pathname).
Available Scripts
These commands are defined in package.json:
| Command | Description |
|---|---|
npm run dev -w @xmachines/play-solid-router-demo | Start Vite dev server |
npm run build -w @xmachines/play-solid-router-demo | Build production bundle |
npm run preview -w @xmachines/play-solid-router-demo | Preview built bundle |
npm run test -w @xmachines/play-solid-router-demo | Run Vitest test suite |
npm run test:browser -w @xmachines/play-solid-router-demo | Run browser-focused Vitest suite |
Verification
Use these checks to validate README claims against the current demo implementation:
npm run test -w @xmachines/play-solid-router-demonpm run test:browser -w @xmachines/play-solid-router-demoExpected result: library-pattern invariant tests and the browser shared-demo suite both pass, confirming login/logout transitions update both view and URL correctly.