Client-side routing
Three URLs, one router — running in the browser. Each is still its own static file.
server-rendered — the file the build wrote, before any JavaScript ran
A fetch router in the browser
client/spa/app.tsx is a createRouter() like the one in server/router.ts: middleware, params, status codes, a default handler. It maps routes.spa.show — the same route object the server maps, from the same client/routes.ts. Nothing here parses a URL by hand.
What @remix-run/spa adds is two functions. render() is middleware whose responses carry a component tree instead of a body, and run(router) points the Remix runtime at the router, so a navigation is dispatched rather than fetched.