@xmachines/play-vue-router-demo
Examples / @xmachines/play-vue-router-demo
Vue Router integration demo for the XMachines Play architecture using Vue Composition API.
What This Demonstrates
- Shared auth machine reused without framework-specific business logic
PlayRouterProviderrenderer-based integration with Vue Router- Shell-driven rendering via
PlayRendererwith actor-authoritative navigation - Vue Composition API mapping to TC39 Signals lifecycle
- Non-browser invariant tests plus browser E2E coverage
Running the Demo
From the repository root:
npm installnpm run dev -w @xmachines/play-vue-router-demoThen open http://localhost:3001.
Step-by-Step Code Flow
Use this order to understand how the demo is wired:
src/main.tscreates the Vue app, installs Vue Router, mounts, and wires HMR cleanup.src/runtime.tscreates the actor, starts it, builds the sharedregistryResult, and creates therouteMap.src/router.tsinstalls a single catch-all route;PlayRendererselects the actual view from actor state.src/App.vuerenders<PlayRouterProvider>with the shared actor, routeMap, router instance, and arenderShellrenderer function.- The renderer function creates the shared
Shellcomponent with actor, router, and registry as props. PlayRouterProviderwaits forrouter.isReady()so direct URL loads are handled correctly.- Browser tests in
test/browser/validate startup and auth route transitions.
// src/main.ts (shape)const app = createApp(App);app.use(router);app.mount("#app");// src/router.ts (shape)export const routes = [{ path: "/:pathMatch(.*)*", name: "xmachines-play", component: RouteHost }];<!-- src/App.vue (shape) --><script setup lang="ts">import { actor, routeMap, registryResult } from "./runtime.js";
const renderShell = (currentActor, currentRouter) => h(SharedShell, { actor: currentActor, router: currentRouter, registryResult });</script>
<template> <PlayRouterProvider :actor="actor" :route-map="routeMap" :router="router" :renderer="renderShell" /></template>// src/runtime.ts (shape)export const actor = createPlayer();actor.start();
export const routeMap = createRouteMap(authMachine);export const registryResult = defineRegistry(authCatalog, { components, actions });Key Files
src/main.ts- Vue app bootstrap (mount + router install + HMR cleanup)src/runtime.ts- actor startup, routeMap creation, and registry constructionsrc/router.ts- single catch-all route recordsrc/App.vue-PlayRouterProviderwiring and renderer composition using the shared runtimetest/reactivity.test.ts- reactive integration 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 via a link, Vue Router updates the location. The
PlayRouterProviderintercepts this, translates it to aplay.routeevent, and sends it to the actor. The actor evaluates guards (e.g.isAuthenticated) and transitions. - Passive Infrastructure: The router does not execute Vue route guards for business logic. The actor dictates whether navigation is permitted. The Vue application only renders the state.
- Signal-Only Reactivity: The bridge leverages Vue’s
watchandtriggerRefinternally to react precisely when signals update, without polluting the Vue component tree with reactive refs that hold business state.
Watcher Lifecycle and Cleanup Contract
This demo follows the canonical watcher lifecycle:
notifyqueueMicrotaskgetPending()- Read actor signals and sync Vue-local render state
- Re-arm with
watch()/watch(...signals)
Notifications are one-shot, so re-arm is required. Teardown is explicit: provider/bridge cleanup must flow through disconnect and watcher unwatch, not GC-only assumptions. The PlayRouterProvider wires this seamlessly into the component’s onUnmounted hook.
Adapter Boundaries
Vue Router integration remains passive infrastructure. RouterBridgeBase owns shared synchronization policy and the Vue adapter is a thin framework port. Route extraction override strategies remain supported when teams need custom route-name mapping.
Available Scripts
These commands are defined in package.json:
| Command | Description |
|---|---|
npm run dev -w @xmachines/play-vue-router-demo | Start Vite dev server |
npm run build -w @xmachines/play-vue-router-demo | Build production bundle |
npm run preview -w @xmachines/play-vue-router-demo | Preview built bundle |
npm run test -w @xmachines/play-vue-router-demo | Run Vitest test suite |
npm run test:browser -w @xmachines/play-vue-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-vue-router-demonpm run test:browser -w @xmachines/play-vue-router-demoExpected result: reactivity integration tests and the browser shared-demo suite both pass, confirming login/logout transitions update both view and URL correctly.