{"id":41574163,"url":"https://github.com/greydragon888/real-router","last_synced_at":"2026-07-19T21:00:56.231Z","repository":{"id":333826133,"uuid":"1087808090","full_name":"greydragon888/real-router","owner":"greydragon888","description":"A real router. Just routing, nothing else.","archived":false,"fork":false,"pushed_at":"2026-07-15T09:57:06.000Z","size":22173,"stargazers_count":8,"open_issues_count":22,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-15T11:10:06.212Z","etag":null,"topics":["framework-agnostic","monorepo","react","router","routing","state-machine","typescript","universal"],"latest_commit_sha":null,"homepage":"https://github.com/greydragon888/real-router/wiki","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/greydragon888.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["greydragon888"],"ko_fi":"greydragon888"}},"created_at":"2025-11-01T17:28:01.000Z","updated_at":"2026-07-15T09:54:36.000Z","dependencies_parsed_at":"2026-02-14T12:04:46.583Z","dependency_job_id":null,"html_url":"https://github.com/greydragon888/real-router","commit_stats":null,"previous_names":["greydragon888/real-router"],"tags_count":1555,"template":false,"template_full_name":null,"purl":"pkg:github/greydragon888/real-router","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydragon888%2Freal-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydragon888%2Freal-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydragon888%2Freal-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydragon888%2Freal-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/greydragon888","download_url":"https://codeload.github.com/greydragon888/real-router/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greydragon888%2Freal-router/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35665444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-19T02:00:06.923Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["framework-agnostic","monorepo","react","router","routing","state-machine","typescript","universal"],"created_at":"2026-01-24T08:07:49.540Z","updated_at":"2026-07-19T21:00:56.217Z","avatar_url":"https://github.com/greydragon888.png","language":"TypeScript","funding_links":["https://github.com/sponsors/greydragon888","https://ko-fi.com/greydragon888"],"categories":[],"sub_categories":[],"readme":"# Real-Router\n\n\u003cdiv align=\"center\"\u003e\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)\n[![npm](https://img.shields.io/npm/v/@real-router/core.svg?style=flat-square\u0026logo=npm)](https://www.npmjs.com/package/@real-router/core)\n[![npm downloads](https://img.shields.io/npm/dm/@real-router/core.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/core)\n[![TypeScript](https://img.shields.io/badge/TypeScript-6.0-blue?style=flat-square\u0026logo=typescript)](https://www.typescriptlang.org/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)\n[![Engineered with Claude Code](https://img.shields.io/badge/Engineered%20with-Claude%20Code-5865F2?style=flat-square\u0026logo=anthropic\u0026logoColor=white)](https://claude.com/claude-code)\n\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eData-first router for JavaScript — the most declarative router for client applications\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/greydragon888/real-router/wiki\"\u003eWiki\u003c/a\u003e ·\n  \u003ca href=\"https://github.com/greydragon888/real-router/wiki/recipes\"\u003eRecipes\u003c/a\u003e ·\n  \u003ca href=\"https://github.com/greydragon888/real-router/issues/296\"\u003eRoadmap\u003c/a\u003e ·\n  \u003ca href=\"https://github.com/greydragon888/real-router/releases\"\u003eChangelog\u003c/a\u003e ·\n  \u003ca href=\"CONTRIBUTING.md\"\u003eContributing\u003c/a\u003e ·\n  \u003ca href=\"https://github.com/greydragon888/real-router/issues\"\u003eIssues\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\nEvery router you know maps URLs to **components**. Real-Router maps URLs to **data**.\n\n```\nReact Router:     URL  →  \u003cComponent /\u003e     (router decides what to render)\nVue Router:       URL  →  component: View   (router decides what to render)\nReal-Router:      URL  →  { name, params }  (you decide what to do)\n```\n\n**The router tells you where. You decide what.**\n\nThis is not a minor API difference — it's a fundamentally different architecture.\\\nThe router is a **lifecycle manager**, not a data layer.\\\nIt tells you when transitions happen; what to do with that — render a page, load data, set a title, track analytics, or ignore it entirely — is your decision.\n\n\u003e Built from scratch with TypeScript-first design. Independent project inspired by [router5](https://github.com/router5/router5)'s declarative philosophy, not a fork.\n\n\u003e **Pre-1.0**: Core API and plugin interfaces are stable. Minor versions preserve backward compatibility. The high release count reflects monorepo-wide coordinated publishing — one change in core triggers version bumps across all ~30 dependent packages. See [Roadmap](https://github.com/greydragon888/real-router/issues/296) for the path to 1.0 and [Quality \u0026 Testing](#quality--testing) for reliability guarantees.\n\n## Why Real-Router?\n\nYour routing logic lives in one place — route config plus a plugin or two.\nAdding a page means adding a config entry; changing auth means touching one module.\n\n### One-Way Data Flow in UI\n\nOther routers push data fetching into components — `useParams()` + `useEffect()` + `fetch()` is imperative boilerplate that every page repeats.\n\nReal-Router inverts this: routing state arrives as external data, plugins handle data loading, titles, analytics outside the component tree.\nComponents just render what they receive.\n\n### Declarative Route Config\n\nOne config object declares everything — routing, access control, data loading, and any custom concern. No logic scattered across component files.\n\nCompare where routing logic lives across routers:\n\n```\nReact Router v7:   guards in loaders, meta in page files — one route module per file\nVue Router v4:     guards in beforeEach(), data in components, titles wired manually\nTanStack Router:   beforeLoad + loader + head per route file, scattered across file tree\nReal-Router:       guards + data + titles + any router related logic in one config object → generic plugins\n```\n\nWith [`@real-router/lifecycle-plugin`](packages/lifecycle-plugin), data loading, titles, and cleanup live next to the route they belong to — no wrapper components, no HOCs, no scattered `useEffect` in pages:\n\n```typescript\nimport { lifecyclePluginFactory } from \"@real-router/lifecycle-plugin\";\n\nrouter.usePlugin(lifecyclePluginFactory());\n\nconst routes = [\n  {\n    name: \"users\",\n    path: \"/users\",\n    canActivate: authGuard,\n    onNavigate: (state) =\u003e {\n      store.users.load(state.params);\n    },\n    children: [\n      {\n        name: \"profile\",\n        path: \"/:id\",\n        onNavigate: (state) =\u003e {\n          document.title = `User ${state.params.id}`;\n          store.users.loadOne(state.params.id);\n        },\n      },\n    ],\n  },\n];\n```\n\nOne config, one place. Adding a new page = one config entry. See [Recipes](https://github.com/greydragon888/real-router/wiki/recipes) for full examples.\n\n#### Writing your own plugin when lifecycle-plugin isn't enough\n\nFor custom transition phases, cross-route coordination, or domain-specific concerns, you can write a generic plugin that reads your own fields from route config:\n\n```typescript\nconst routes = [\n  {\n    name: \"users\",\n    path: \"/users\",\n    loadData: (p, api) =\u003e api.getUsers(p), // custom field → your plugin\n  },\n];\n\nconst dataPlugin: PluginFactory = (router, getDep) =\u003e {\n  const { getRouteConfig } = getPluginApi(router);\n\n  return {\n    onTransitionSuccess: (toState) =\u003e {\n      const route = getRouteConfig(toState.name);\n\n      route?.loadData?.(toState.params, getDep(\"api\"));\n    },\n  };\n};\n```\n\nThe plugin reads custom fields from any route — no hardcoded route names, works across the entire config.\n\n### Runtime Route Management\n\nSwap entire route trees in one call — auth flows, feature flags, A/B experiments.\n\nFull CRUD for routes at runtime — add, remove, update, replace, clear.\\\nNo other router offers `update()` for modifying guards, redirects, or defaults of individual routes without remove+add.\\\n`replace()` is atomic with state revalidation — designed for HMR and dynamic feature flags.\n\nThe most direct demonstration is an auth-driven tree swap:\n\n```typescript\nimport { getRoutesApi } from \"@real-router/core/api\";\n\nasync function login(credentials) {\n  await api.login(credentials);\n\n  const routes = getRoutesApi(router);\n  routes.clear();\n  routes.add(privateRoutes);\n  router.navigate(\"dashboard\");\n}\n\nasync function logout() {\n  await api.logout();\n\n  const routes = getRoutesApi(router);\n  routes.clear();\n  routes.add(publicRoutes);\n  router.navigate(\"auth\");\n}\n```\n\nIn URL→Component routers, private routes exist in the tree regardless of auth state — something must match them and decide to redirect. Real-Router takes a different path: when the user isn't authenticated, private routes aren't in the tree at all. Nothing to match, nothing to mount. An entire class of auth-related edge cases disappears by construction.\n\n\u003e This is a client-side state consistency pattern, not a security boundary. Data authorization still belongs on the server (auth middleware, RLS, scoped tokens). The router keeps the client tree consistent with auth state; it doesn't protect data.\n\n### Capability-Based API\n\nDifferent consumers see different surfaces:\n\n- **Application code** uses the router directly — `navigate`, `subscribe`, `usePlugin`, etc.\n- **UI components** get `Navigator` — a frozen object with only the methods components actually need (`navigate`, `getState`, `isActiveRoute`, `canNavigateTo`, `subscribe`, `subscribeLeave`, `isLeaveApproved`). No way to accidentally call `dispose()` or mutate routes.\n- **Plugin authors** explicitly import `getPluginApi(router)` to access interceptors, state context claims, and internals. These are gated behind a separate import — invisible to everyone else.\n\nMost applications never encounter plugin APIs. Most components never see dangerous methods. The right surface at the right layer.\n\nOne practical payoff — RBAC-aware menus without a second permission table:\n\n```tsx\n// canNavigateTo runs the same guards navigate would —\n// so your menu shows only what the current user is actually allowed to reach.\nconst visibleItems = menuItems.filter((item) =\u003e\n  navigator.canNavigateTo(item.route),\n);\n```\n\nNo separate permission table to keep in sync with route guards. One source of truth, used both to decide what to show and what to let through.\n\n### Minimal Runtime Footprint\n\nThe core is platform-agnostic — no DOM, no History API, no framework dependencies in the routing layer.\nIt works in any JavaScript runtime, not just browsers: SSR, SSG, Service Workers, edge functions, React Native — all without special modes or framework-specific adapters.\nSwap the platform plugin, reuse everything else.\n\nRuns in **browser, terminal (Ink), and desktop (Electron, Tauri)** — same router, different plugins. See [Desktop Integration Guide](https://github.com/greydragon888/real-router/wiki/Desktop-Integration).\n\n### First-Class SSR · Streaming · SSG\n\nThe only standalone router that ships the **same SSR contract** across React 19, Preact 10, Vue 3, Solid, Svelte 5, and Angular 22+ — without locking you into Next.js, Nuxt, SolidStart, or SvelteKit. ~300+ e2e scenarios covering classical SSR, streaming, SSG, and RSC pipelines.\n\n| Adapter   | SSR | Streaming SSR                          | SSG | e2e scenarios |\n| --------- | --- | -------------------------------------- | --- | ------------- |\n| React 19  | ✓   | OOO `\u003cSuspense\u003e` + `use()`             | ✓   | 36+           |\n| Preact 10 | ✓   | OOO `\u003cpreact-island\u003e` + `\u003cAwait\u003e`      | ✓   | 4 pipelines   |\n| Vue 3     | ✓   | chunked + blocking Suspense            | ✓   | 55            |\n| Solid     | ✓   | OOO + selective hydration              | ✓   | 59            |\n| Svelte 5  | ✓   | deferred-data via `{#await}`           | ✓   | 52            |\n| Angular   | ✓   | TransferState bridge                   | ✓   | 4 pipelines   |\n\n**Unique primitives at the routing layer:**\n\n- **Per-route SSR mode** — `full` / `data-only` / `client-only` + function form `(state) =\u003e SsrMode` (data-driven, not path-based)\n- **Cross-adapter SSR components** — `\u003cClientOnly\u003e`, `\u003cServerOnly\u003e`, `\u003cAwait\u003e`, `\u003cStreamed\u003e`, `\u003cHttpStatusCode\u003e` shipped symmetric across 5 adapters via `/ssr` subpath\n- **Typed loader errors → HTTP** — `LoaderRedirect` / `LoaderNotFound` / `LoaderTimeout` mapped to 301/302/404/504 in both SSR and RSC pipelines\n- **`createRequestScope(req, baseRouter, deps)`** — correct-by-construction request DI: clone + AbortController + `req.on(\"close\")` + dispose in one call\n- **Network-level cancellation** — `withTimeout()` composes deadline + client-disconnect into one `AbortSignal`; in-flight `fetch` aborts at TCP level when deadline fires\n- **Post-hydration loader skip** — zero fetch on first paint after hydration, automatic in all 6 adapters\n\n[SSR](examples/web/react/ssr-examples/ssr) · [Streaming SSR](examples/web/react/ssr-examples/ssr-streaming) · [SSG](examples/web/react/ssr-examples/ssg) · [RSC](examples/web/react/ssr-examples/ssr-rsc) · [Wiki: SSR](https://github.com/greydragon888/real-router/wiki/ssr) · [Streaming SSR](https://github.com/greydragon888/real-router/wiki/Streaming-SSR) · [SSR Hydration](https://github.com/greydragon888/real-router/wiki/SSR-Hydration)\n\n### Performance\n\nNavigation stays fast as your route tree grows — from 10 routes to 1000, the cost per navigation barely moves.\nThe Segment Trie matcher traverses in O(segments), not O(routes).\n\nMeasured in the [cross-router benchmark](benchmarks/README.md) — real Chromium (Playwright + CDP), production Vite builds, every serious competitor in each framework cohort, per-cohort verdicts only.\n\n**vs TanStack Router** (same snapshot, per cohort):\n\n| Cohort | Navigation latency | Transient GC per navigation |\n| ------ | ------------------ | --------------------------- |\n| React  | **~2.6× faster**   | **~12× fewer allocations**  |\n| Solid  | **~6× faster**     | **~17× fewer allocations**  |\n| Vue    | **~3.5× faster**   | **~24× fewer allocations**  |\n\nIn the isolated matcher microbench ([`matcher-bench`](benchmarks/cross-router/matcher-bench/README.md)), only real-router and TanStack hold a flat **O(1)** curve as the route table widens — every other measured router scans O(N) — and real-router **wins the deep-tree match in every cohort**.\n\n### Key Features\n\n- **Framework-agnostic** — React, Preact, Solid, Vue, Svelte, Angular, or vanilla JS\n- **First-class SSR / Streaming / SSG / RSC** — same primitives across React 19, Preact 10, Vue 3, Solid, Svelte 5, Angular 22+ — no meta-framework lock-in. [See above](#first-class-ssr--streaming--ssg)\n- **Named nested routes** — dot-notation hierarchy (`users.profile`)\n- **Lifecycle guards** — `canActivate` / `canDeactivate` per route or globally\n- **AbortController** — cancel navigations via standard `AbortSignal`\n- **Dynamic route management** — add, remove, update, replace routes at runtime\n- **Dependency injection** — type-safe DI container for guards and plugins\n- **Plugin architecture** — intercept and extend router behavior\n- **Observable state** — RxJS and TC39 Observable compatible\n- **Immutable state** — deeply frozen, predictable state management\n- **Scroll restoration** — opt-in via `RouterProvider.scrollRestoration` ([docs](https://github.com/greydragon888/real-router/wiki/Scroll-Restoration)); restores on back/forward, scrolls to top / `#hash` on push; `restore` / `top` / `manual` modes; custom scroll containers\n- **Scroll spy** — opt-in via `RouterProvider.scrollSpy` ([docs](https://github.com/greydragon888/real-router/wiki/Scroll-Spy)); router-coordinated `IntersectionObserver` syncs the URL hash to the topmost visible anchor as you scroll\n\n## Quick Start\n\n```bash\nnpm install @real-router/core\n```\n\n```typescript\nimport { createRouter } from \"@real-router/core\";\nimport { browserPluginFactory } from \"@real-router/browser-plugin\";\n\nconst routes = [\n  { name: \"home\", path: \"/\" },\n  {\n    name: \"users\",\n    path: \"/users\",\n    children: [\n      {\n        name: \"profile\",\n        path: \"/:id\",\n      },\n    ],\n  },\n];\n\nconst router = createRouter(routes);\nrouter.usePlugin(browserPluginFactory(), __DEV__ \u0026\u0026 validationPlugin());\n\nawait router.start();\nawait router.navigate(\"users.profile\", { id: \"123\" });\n```\n\n\u003e **Recommended for development:** add [`@real-router/validation-plugin`](https://www.npmjs.com/package/@real-router/validation-plugin) for descriptive runtime errors on every API call. Falsy values in `usePlugin()` are silently skipped, so inline conditionals work naturally:\n\u003e\n\u003e ```typescript\n\u003e import { validationPlugin } from \"@real-router/validation-plugin\";\n\u003e\n\u003e router.usePlugin(browserPluginFactory(), __DEV__ \u0026\u0026 validationPlugin());\n\u003e ```\n\n\u003e **Route-level lifecycle hooks:** add [`@real-router/lifecycle-plugin`](https://www.npmjs.com/package/@real-router/lifecycle-plugin) to attach `onNavigate`, `onEnter`, `onStay`, `onLeave` callbacks directly to route definitions — no `subscribe()` boilerplate:\n\u003e\n\u003e ```typescript\n\u003e import { lifecyclePluginFactory } from \"@real-router/lifecycle-plugin\";\n\u003e\n\u003e const routes = [\n\u003e   {\n\u003e     name: \"home\",\n\u003e     path: \"/\",\n\u003e     onLeave: () =\u003e cleanup(),\n\u003e   },\n\u003e   {\n\u003e     name: \"users.view\",\n\u003e     path: \"/users/:id\",\n\u003e     onNavigate: (s) =\u003e track(s.params.id),\n\u003e   },\n\u003e ];\n\u003e\n\u003e router.usePlugin(lifecyclePluginFactory());\n\u003e ```\n\n### With React\n\n```tsx\nimport { RouterProvider, RouteView, Link } from \"@real-router/react\";\n\nfunction App() {\n  return (\n    \u003cRouterProvider router={router}\u003e\n      \u003cnav\u003e\n        \u003cLink routeName=\"home\"\u003eHome\u003c/Link\u003e\n        \u003cLink routeName=\"users\"\u003eUsers\u003c/Link\u003e\n      \u003c/nav\u003e\n      \u003cRouteView nodeName=\"\"\u003e\n        \u003cRouteView.Match routeName=\"home\"\u003e\n          \u003cHomePage /\u003e\n        \u003c/RouteView.Match\u003e\n        \u003cRouteView.Match routeName=\"users\"\u003e\n          \u003cUsersPage /\u003e\n        \u003c/RouteView.Match\u003e\n        \u003cRouteView.NotFound\u003e\n          \u003cNotFoundPage /\u003e\n        \u003c/RouteView.NotFound\u003e\n      \u003c/RouteView\u003e\n    \u003c/RouterProvider\u003e\n  );\n}\n```\n\n`RouteView` with `keepAlive` requires React 19.2+ (React Activity API). For React 18+, use `@real-router/react/legacy` — all hooks and `Link`, no `RouteView`.\n\n## Packages\n\n### Core\n\n| Package                                     | Version                                                                                                                           | Description                                                                                                        |\n| ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |\n| [`@real-router/core`](packages/core)        | [![npm](https://img.shields.io/npm/v/@real-router/core.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/core)   | Router implementation                                                                                              |\n| `@real-router/core/api`                     |                                                                                                                                   | Tree-shakeable modular API: `getRoutesApi`, `getDependenciesApi`, `getLifecycleApi`, `getPluginApi`, `cloneRouter` |\n| `@real-router/core/utils`                   |                                                                                                                                   | Utility functions: `serializeState` (XSS-safe JSON for SSR), `getStaticPaths` (static path generation for SSG)     |\n| [`@real-router/types`](packages/core-types) | [![npm](https://img.shields.io/npm/v/@real-router/types.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/types) | Shared TypeScript type definitions                                                                                 |\n\n### Framework Integration\n\n| Package                                    | Version                                                                                                                               | Description                                                                                |\n| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |\n| [`@real-router/react`](packages/react)     | [![npm](https://img.shields.io/npm/v/@real-router/react.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/react)     | React 19.2+ (hooks, `RouteView`, `Link`). React 18+ via `./legacy`                         |\n| [`@real-router/preact`](packages/preact)   | [![npm](https://img.shields.io/npm/v/@real-router/preact.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/preact)   | Preact (hooks, `RouteView`, `Link`, Suspense)                                              |\n| [`@real-router/solid`](packages/solid)     | [![npm](https://img.shields.io/npm/v/@real-router/solid.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/solid)     | Solid.js (signals, `RouteView`, `Link`, store-based state)                                 |\n| [`@real-router/vue`](packages/vue)         | [![npm](https://img.shields.io/npm/v/@real-router/vue.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/vue)         | Vue 3 (composables, `RouteView`, `Link`, `KeepAlive`, `v-link`)                            |\n| [`@real-router/svelte`](packages/svelte)   | [![npm](https://img.shields.io/npm/v/@real-router/svelte.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/svelte)   | Svelte 5 (runes, `RouteView` with snippets, `Lazy`, `use:link`)                            |\n| [`@real-router/angular`](packages/angular) | [![npm](https://img.shields.io/npm/v/@real-router/angular.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/angular) | Angular 22+ (signals, `inject*` functions, `\u003croute-view\u003e`, `realLink` directive, zoneless) |\n\n### Plugins\n\n| Package                                                                      | Version                                                                                                                                                                 | Description                                             |\n| ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |\n| [`@real-router/browser-plugin`](packages/browser-plugin)                     | [![npm](https://img.shields.io/npm/v/@real-router/browser-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/browser-plugin)                     | Browser History API and URL synchronization             |\n| [`@real-router/navigation-plugin`](packages/navigation-plugin)               | [![npm](https://img.shields.io/npm/v/@real-router/navigation-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/navigation-plugin)               | Navigation API integration + route-level history        |\n| [`@real-router/memory-plugin`](packages/memory-plugin)                       | [![npm](https://img.shields.io/npm/v/@real-router/memory-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/memory-plugin)                       | In-memory history: back/forward/go (no DOM)             |\n| [`@real-router/hash-plugin`](packages/hash-plugin)                           | [![npm](https://img.shields.io/npm/v/@real-router/hash-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/hash-plugin)                           | Hash-based routing (`#/path`)                           |\n| [`@real-router/logger-plugin`](packages/logger-plugin)                       | [![npm](https://img.shields.io/npm/v/@real-router/logger-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/logger-plugin)                       | Development logging with transition tracking            |\n| [`@real-router/persistent-params-plugin`](packages/persistent-params-plugin) | [![npm](https://img.shields.io/npm/v/@real-router/persistent-params-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/persistent-params-plugin) | Parameter persistence across navigations                |\n| [`@real-router/ssr-data-plugin`](packages/ssr-data-plugin)                   | [![npm](https://img.shields.io/npm/v/@real-router/ssr-data-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/ssr-data-plugin)                   | SSR per-route data loading via interceptor              |\n| [`@real-router/rsc-server-plugin`](packages/rsc-server-plugin)               | [![npm](https://img.shields.io/npm/v/@real-router/rsc-server-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/rsc-server-plugin)               | RSC per-route ReactNode loading (bundler-agnostic)      |\n| [`@real-router/lifecycle-plugin`](packages/lifecycle-plugin)                 | [![npm](https://img.shields.io/npm/v/@real-router/lifecycle-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/lifecycle-plugin)                 | Route-level hooks: onNavigate, onEnter, onStay, onLeave |\n| [`@real-router/preload-plugin`](packages/preload-plugin)                     | [![npm](https://img.shields.io/npm/v/@real-router/preload-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/preload-plugin)                     | Preload on navigation intent (hover, touch)             |\n| [`@real-router/validation-plugin`](packages/validation-plugin)               | [![npm](https://img.shields.io/npm/v/@real-router/validation-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/validation-plugin)               | Runtime argument validation for development             |\n| [`@real-router/search-schema-plugin`](packages/search-schema-plugin)         | [![npm](https://img.shields.io/npm/v/@real-router/search-schema-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/search-schema-plugin)         | Search param validation via Standard Schema             |\n\n### Utilities\n\n| Package                                            | Version                                                                                                                                       | Description                                                                                                                                                              |\n| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| [`@real-router/sources`](packages/sources)         | [![npm](https://img.shields.io/npm/v/@real-router/sources.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/sources)         | Reactive subscription sources for UI bindings — per-router cached `getTransitionSource` / `createDismissableError` / `createActiveNameSelector` + canonical params cache |\n| [`@real-router/rx`](packages/rx)                   | [![npm](https://img.shields.io/npm/v/@real-router/rx.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/rx)                   | Observable API: `state$`, `events$`, operators, TC39 Observable                                                                                                          |\n| [`@real-router/route-utils`](packages/route-utils) | [![npm](https://img.shields.io/npm/v/@real-router/route-utils.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/route-utils) | Route tree queries: `getRouteUtils`, segment testers, `areRoutesRelated`                                                                                                 |\n| [`@real-router/logger`](packages/logger)           | [![npm](https://img.shields.io/npm/v/@real-router/logger.svg?style=flat-square)](https://www.npmjs.com/package/@real-router/logger)           | Structured logging utility                                                                                                                                               |\n\n## Documentation\n\nFull documentation is available in the [Wiki](https://github.com/greydragon888/real-router/wiki).\n\n### Getting Started\n\n- [Core Concepts](https://github.com/greydragon888/real-router/wiki/core-concepts) — overview and mental model\n- [Defining Routes](https://github.com/greydragon888/real-router/wiki/Route) — route configuration, nesting, path syntax\n- [Navigation Lifecycle](https://github.com/greydragon888/real-router/wiki/navigation-lifecycle) — transitions, guards, hooks\n\n### API Reference\n\n- [createRouter](https://github.com/greydragon888/real-router/wiki/createRouter) · [navigate](https://github.com/greydragon888/real-router/wiki/navigate) · [start](https://github.com/greydragon888/real-router/wiki/start) · [stop](https://github.com/greydragon888/real-router/wiki/stop) · [buildPath](https://github.com/greydragon888/real-router/wiki/buildPath) · [isActiveRoute](https://github.com/greydragon888/real-router/wiki/isActiveRoute)\n- [Guards](https://github.com/greydragon888/real-router/wiki/guards) · [State](https://github.com/greydragon888/real-router/wiki/State) · [NavigationOptions](https://github.com/greydragon888/real-router/wiki/NavigationOptions) · [RouterOptions](https://github.com/greydragon888/real-router/wiki/RouterOptions) · [RouterError](https://github.com/greydragon888/real-router/wiki/RouterError)\n- [Plugin Architecture](https://github.com/greydragon888/real-router/wiki/plugin-architecture) · [getRoutesApi](https://github.com/greydragon888/real-router/wiki/addRoute) · [getDependenciesApi](https://github.com/greydragon888/real-router/wiki/getDependency) · [getLifecycleApi](https://github.com/greydragon888/real-router/wiki/addActivateGuard) · [cloneRouter](https://github.com/greydragon888/real-router/wiki/clone)\n\n### React\n\n- [RouterProvider](https://github.com/greydragon888/real-router/wiki/RouterProvider) · [RouteView](https://github.com/greydragon888/real-router/wiki/RouteView) · [Link](https://github.com/greydragon888/real-router/wiki/Link) · [useRouter](https://github.com/greydragon888/real-router/wiki/useRouter) · [useRoute](https://github.com/greydragon888/real-router/wiki/useRoute) · [useRouteNode](https://github.com/greydragon888/real-router/wiki/useRouteNode) · [useNavigator](https://github.com/greydragon888/real-router/wiki/useNavigator)\n\n### Preact / Solid / Vue / Svelte / Angular\n\n- [Preact Integration](https://github.com/greydragon888/real-router/wiki/Preact-Integration) · [Solid Integration](https://github.com/greydragon888/real-router/wiki/Solid-Integration) · [Vue Integration](https://github.com/greydragon888/real-router/wiki/Vue-Integration) · [Svelte Integration](https://github.com/greydragon888/real-router/wiki/Svelte-Integration) · [Angular Integration](https://github.com/greydragon888/real-router/wiki/Angular-Integration)\n\n### Plugins\n\n- [browser-plugin](https://github.com/greydragon888/real-router/wiki/browser-plugin) · [navigation-plugin](https://github.com/greydragon888/real-router/wiki/Navigation-Plugin) · [hash-plugin](https://github.com/greydragon888/real-router/wiki/hash-plugin) · [logger-plugin](https://github.com/greydragon888/real-router/wiki/logger-plugin) · [persistent-params-plugin](https://github.com/greydragon888/real-router/wiki/persistent-params-plugin) · [search-schema-plugin](https://github.com/greydragon888/real-router/wiki/search-schema-plugin) · [ssr-data-plugin](https://github.com/greydragon888/real-router/wiki/ssr-data-plugin) · [rsc-server-plugin](https://github.com/greydragon888/real-router/wiki/rsc-server-plugin) · [lifecycle-plugin](https://github.com/greydragon888/real-router/wiki/lifecycle-plugin) · [preload-plugin](https://github.com/greydragon888/real-router/wiki/preload-plugin) · [memory-plugin](https://github.com/greydragon888/real-router/wiki/memory-plugin) · [validation-plugin](https://github.com/greydragon888/real-router/wiki/validation-plugin) · [rx](https://github.com/greydragon888/real-router/wiki/rx-package) · [sources](https://github.com/greydragon888/real-router/wiki/sources-package) · [route-utils](https://github.com/greydragon888/real-router/wiki/route-utils)\n\n### Server-Side Rendering \u0026 RSC\n\n- [Server-Side Rendering](https://github.com/greydragon888/real-router/wiki/ssr) — `cloneRouter` per request, `start(url)` resolution, `dispose()` cleanup\n- [SSR Hydration](https://github.com/greydragon888/real-router/wiki/SSR-Hydration) — `serializeRouterState` + `hydrateRouter` round-trip, `excludeContext` for non-serializable namespaces\n- [Data Loading](https://github.com/greydragon888/real-router/wiki/Data-Loading) — `ssr-data-plugin` for plain JSON, fetcher patterns\n- [**Streaming SSR**](https://github.com/greydragon888/real-router/wiki/Streaming-SSR) — React 19 `renderToReadableStream` + `\u003cSuspense\u003e` + `use(promise)` for deferred sections. Zero router-specific API — pure delegation to React 19 native primitives. Reference: [`examples/web/react/ssr-examples/ssr-streaming/`](examples/web/react/ssr-examples/ssr-streaming)\n- [**RSC Integration**](https://github.com/greydragon888/real-router/wiki/RSC-Integration) — React Server Components end-to-end: `@vitejs/plugin-rsc` setup, two-endpoint architecture (HTML + `/__rsc`), Flight injection, client mount. Reference implementation: [`examples/web/react/ssr-examples/ssr-rsc/`](examples/web/react/ssr-examples/ssr-rsc)\n\n## Examples\n\nMany runnable examples across the most popular frameworks — each is a standalone Vite app:\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eFeature matrix — 6 adapters × 12 features (+ framework-specific)\u003c/b\u003e\u003c/summary\u003e\n\n| Feature                 | [React](examples/web/react) | [Preact](examples/web/preact) | [Solid](examples/web/solid) | [Vue](examples/web/vue) | [Svelte](examples/web/svelte) | [Angular](examples/web/angular) |\n| ----------------------- | --------------------------- | ----------------------------- | --------------------------- | ----------------------- | ----------------------------- | ------------------------------- |\n| Basic routing           | [basic](examples/web/react/basic) | [basic](examples/web/preact/basic) | [basic](examples/web/solid/basic) | [basic](examples/web/vue/basic) | [basic](examples/web/svelte/basic) | [basic](examples/web/angular/basic) |\n| Nested routes           | [nested-routes](examples/web/react/nested-routes) | [nested-routes](examples/web/preact/nested-routes) | [nested-routes](examples/web/solid/nested-routes) | [nested-routes](examples/web/vue/nested-routes) | [nested-routes](examples/web/svelte/nested-routes) | [nested-routes](examples/web/angular/nested-routes) |\n| Auth guards             | [auth-guards](examples/web/react/auth-guards) | [auth-guards](examples/web/preact/auth-guards) | [auth-guards](examples/web/solid/auth-guards) | [auth-guards](examples/web/vue/auth-guards) | [auth-guards](examples/web/svelte/auth-guards) | — |\n| Data loading            | [data-loading](examples/web/react/data-loading) | [data-loading](examples/web/preact/data-loading) | [data-loading](examples/web/solid/data-loading) | [data-loading](examples/web/vue/data-loading) | [data-loading](examples/web/svelte/data-loading) | — |\n| Lazy loading            | [lazy-loading](examples/web/react/lazy-loading) | [lazy-loading](examples/web/preact/lazy-loading) | [lazy-loading](examples/web/solid/lazy-loading) | [lazy-loading](examples/web/vue/lazy-loading) | [lazy-loading](examples/web/svelte/lazy-loading) | [lazy-loading](examples/web/angular/lazy-loading) |\n| Async guards            | [async-guards](examples/web/react/async-guards) | [async-guards](examples/web/preact/async-guards) | [async-guards](examples/web/solid/async-guards) | [async-guards](examples/web/vue/async-guards) | [async-guards](examples/web/svelte/async-guards) | — |\n| Hash routing            | [hash-routing](examples/web/react/hash-routing) | [hash-routing](examples/web/preact/hash-routing) | [hash-routing](examples/web/solid/hash-routing) | [hash-routing](examples/web/vue/hash-routing) | [hash-routing](examples/web/svelte/hash-routing) | [hash-routing](examples/web/angular/hash-routing) |\n| Persistent params       | [persistent-params](examples/web/react/persistent-params) | [persistent-params](examples/web/preact/persistent-params) | [persistent-params](examples/web/solid/persistent-params) | [persistent-params](examples/web/vue/persistent-params) | [persistent-params](examples/web/svelte/persistent-params) | [persistent-params](examples/web/angular/persistent-params) |\n| Search schema           | [search-schema](examples/web/react/search-schema) | [search-schema](examples/web/preact/search-schema) | [search-schema](examples/web/solid/search-schema) | [search-schema](examples/web/vue/search-schema) | [search-schema](examples/web/svelte/search-schema) | — |\n| Error handling          | [error-handling](examples/web/react/error-handling) | [error-handling](examples/web/preact/error-handling) | [error-handling](examples/web/solid/error-handling) | [error-handling](examples/web/vue/error-handling) | [error-handling](examples/web/svelte/error-handling) | — |\n| Dynamic routes          | [dynamic-routes](examples/web/react/dynamic-routes) | [dynamic-routes](examples/web/preact/dynamic-routes) | [dynamic-routes](examples/web/solid/dynamic-routes) | [dynamic-routes](examples/web/vue/dynamic-routes) | [dynamic-routes](examples/web/svelte/dynamic-routes) | [dynamic-routes](examples/web/angular/dynamic-routes) |\n| Combined (all features) | [combined](examples/web/react/combined) | [combined](examples/web/preact/combined) | [combined](examples/web/solid/combined) | [combined](examples/web/vue/combined) | [combined](examples/web/svelte/combined) | [combined](examples/web/angular/combined) |\n| **Framework-specific**  | [keepAlive](examples/web/react/keepAlive), [legacy-entry](examples/web/react/legacy-entry), [hmr](examples/web/react/hmr), [link-hash](examples/web/react/hash-examples/link-hash), [navigation-api](examples/web/react/navigation-api), [scroll-restoration](examples/web/react/hash-examples/scroll-restoration), [scroll-spy](examples/web/react/hash-examples/scroll-spy), [ink-demo](examples/console/react-ink) | — | [store-based-state](examples/web/solid/store-based-state), [use-link-directive](examples/web/solid/use-link-directive), [signal-primitives](examples/web/solid/signal-primitives) | [plugin-installation](examples/web/vue/plugin-installation), [v-link-directive](examples/web/vue/v-link-directive), [keep-alive](examples/web/vue/keep-alive) | [link-action](examples/web/svelte/link-action), [lazy-loading-svelte](examples/web/svelte/lazy-loading-svelte), [snippets-routing](examples/web/svelte/snippets-routing), [reactive-source](examples/web/svelte/reactive-source) | — |\n\n\u003c/details\u003e\n\n### Server rendering — cross-framework symmetry\n\nEvery pipeline below ships as a standalone Vite app per adapter — `pnpm dev` from any folder. All 6 web adapters cover the same 4 SSR pipelines through one `ssr-data-plugin` contract; React additionally has RSC + Flight via `@real-router/rsc-server-plugin`.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSSR pipeline matrix — 6 adapters × 4 pipelines (+ RSC for React)\u003c/b\u003e\u003c/summary\u003e\n\n| Pipeline       | [React](examples/web/react/ssr-examples)                       | [Preact](examples/web/preact/ssr-examples)                       | [Vue](examples/web/vue/ssr-examples)                       | [Solid](examples/web/solid/ssr-examples)                       | [Svelte](examples/web/svelte/ssr-examples)                       | [Angular](examples/web/angular/ssr-examples)                       |\n| -------------- | -------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------ |\n| Classical SSR  | [ssr](examples/web/react/ssr-examples/ssr)                     | [ssr](examples/web/preact/ssr-examples/ssr)                      | [ssr](examples/web/vue/ssr-examples/ssr)                   | [ssr](examples/web/solid/ssr-examples/ssr)                     | [ssr](examples/web/svelte/ssr-examples/ssr)                      | [ssr](examples/web/angular/ssr-examples/ssr)                       |\n| Streaming SSR  | [ssr-streaming](examples/web/react/ssr-examples/ssr-streaming) | [ssr-streaming](examples/web/preact/ssr-examples/ssr-streaming)  | [ssr-streaming](examples/web/vue/ssr-examples/ssr-streaming) | [ssr-streaming](examples/web/solid/ssr-examples/ssr-streaming) | [ssr-streaming](examples/web/svelte/ssr-examples/ssr-streaming)  | [ssr-streaming](examples/web/angular/ssr-examples/ssr-streaming)   |\n| Mixed SSR modes| [ssr-mixed](examples/web/react/ssr-examples/ssr-mixed)         | [ssr-mixed](examples/web/preact/ssr-examples/ssr-mixed)          | [ssr-mixed](examples/web/vue/ssr-examples/ssr-mixed)       | [ssr-mixed](examples/web/solid/ssr-examples/ssr-mixed)         | [ssr-mixed](examples/web/svelte/ssr-examples/ssr-mixed)          | [ssr-mixed](examples/web/angular/ssr-examples/ssr-mixed)           |\n| SSG            | [ssg](examples/web/react/ssr-examples/ssg)                     | [ssg](examples/web/preact/ssr-examples/ssg)                      | [ssg](examples/web/vue/ssr-examples/ssg)                   | [ssg](examples/web/solid/ssr-examples/ssg)                     | [ssg](examples/web/svelte/ssr-examples/ssg)                      | [ssg](examples/web/angular/ssr-examples/ssg)                       |\n| RSC + Flight   | [ssr-rsc](examples/web/react/ssr-examples/ssr-rsc)             | —                                                                | —                                                          | —                                                              | —                                                                | —                                                                  |\n\n\u003c/details\u003e\n\n### Animations — cross-framework symmetry\n\nEach adapter ships four standalone animation pipelines under `animation-examples/` (24 apps in total). See [Routing Animations](https://github.com/greydragon888/real-router/wiki/Routing-Animations) and [View Transitions](https://github.com/greydragon888/real-router/wiki/View-Transitions).\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAnimation pipeline matrix — 6 adapters × 4 pipelines\u003c/b\u003e\u003c/summary\u003e\n\n| Pipeline          | [React](examples/web/react/animation-examples) | [Preact](examples/web/preact/animation-examples) | [Solid](examples/web/solid/animation-examples) | [Vue](examples/web/vue/animation-examples) | [Svelte](examples/web/svelte/animation-examples) | [Angular](examples/web/angular/animation-examples) |\n| ----------------- | ---------------------------------------------- | ------------------------------------------------ | ---------------------------------------------- | ------------------------------------------ | ------------------------------------------------ | -------------------------------------------------- |\n| Motion animations | [motion-animations](examples/web/react/animation-examples/motion-animations) | [motion-animations](examples/web/preact/animation-examples/motion-animations) | [motion-animations](examples/web/solid/animation-examples/motion-animations) | [motion-animations](examples/web/vue/animation-examples/motion-animations) | [motion-animations](examples/web/svelte/animation-examples/motion-animations) | [motion-animations](examples/web/angular/animation-examples/motion-animations) |\n| Page animations   | [page-animations](examples/web/react/animation-examples/page-animations)     | [page-animations](examples/web/preact/animation-examples/page-animations)     | [page-animations](examples/web/solid/animation-examples/page-animations)     | [page-animations](examples/web/vue/animation-examples/page-animations)     | [page-animations](examples/web/svelte/animation-examples/page-animations)     | [page-animations](examples/web/angular/animation-examples/page-animations)     |\n| Route animations  | [route-animations](examples/web/react/animation-examples/route-animations)   | [route-animations](examples/web/preact/animation-examples/route-animations)   | [route-animations](examples/web/solid/animation-examples/route-animations)   | [route-animations](examples/web/vue/animation-examples/route-animations)   | [route-animations](examples/web/svelte/animation-examples/route-animations)   | [route-animations](examples/web/angular/animation-examples/route-animations)   |\n| View Transitions  | [view-transitions](examples/web/react/animation-examples/view-transitions)   | [view-transitions](examples/web/preact/animation-examples/view-transitions)   | [view-transitions](examples/web/solid/animation-examples/view-transitions)   | [view-transitions](examples/web/vue/animation-examples/view-transitions)   | [view-transitions](examples/web/svelte/animation-examples/view-transitions)   | [view-transitions](examples/web/angular/animation-examples/view-transitions)   |\n\n\u003c/details\u003e\n\n| **Terminal UI (Ink)** | [ink-demo](examples/console/react-ink) — CLI app via [@real-router/react/ink](packages/react/README.md#ink-terminal-ui) + memory-plugin |\n\n| **Desktop (Electron, Tauri)** | [electron/react](examples/desktop/electron/react) (`browser-plugin` + `app://`), [electron/react-hash](examples/desktop/electron/react-hash) (`hash-plugin` + `file://`), [electron/react-navigation](examples/desktop/electron/react-navigation) (`navigation-plugin` + HistoryPanel), [tauri/react](examples/desktop/tauri/react) (Tauri v2 + `browser-plugin`), [tauri/react-navigation](examples/desktop/tauri/react-navigation) (Tauri v2 + `navigation-plugin`). See [Desktop Integration Guide](https://github.com/greydragon888/real-router/wiki/Desktop-Integration) |\n\nRun any example: `cd examples/web/react/basic \u0026\u0026 pnpm dev` (the Ink demo is tsx-based — `cd examples/console/react-ink \u0026\u0026 pnpm dev`; Electron — `cd examples/desktop/electron/react \u0026\u0026 pnpm dev`; Tauri — `cd examples/desktop/tauri/react \u0026\u0026 pnpm tauri dev`, requires Rust toolchain).\n\n## Relationship to Router5\n\nReal-Router is an **independent project** — not a fork. Built from scratch with different algorithms (Segment Trie vs linear scan), modern TypeScript API, and independent roadmap. Inspired by router5's declarative routing philosophy (named routes, hierarchical routing, lifecycle guards).\n\n## Quality \u0026 Testing\n\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=greydragon888_real-router\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=greydragon888_real-router)\n[![Vitest](https://img.shields.io/badge/tested%20with-vitest-6E9F18?style=flat-square\u0026logo=vitest)](https://vitest.dev/)\n[![Playwright](https://img.shields.io/badge/e2e-playwright-2EAD33?style=flat-square\u0026logo=playwright)](https://playwright.dev/)\n[![Property-Based Testing](https://img.shields.io/badge/PBT-fast--check-FF4785?style=flat-square)](https://fast-check.dev/)\n\nReal-Router treats testing as a first-class engineering concern, not an afterthought.\n\n- **100% code coverage** — enforced in CI across all packages, no exceptions\n- **Static analysis** — SonarCloud quality gate on every PR: zero bugs, zero vulnerabilities, zero code smells\n- **Property-based testing** — 1000+ property tests via [fast-check](https://fast-check.dev/) across 31 packages, each running hundreds of generated inputs to verify invariants that hand-written tests miss (URL encoding, parameter serialization, route tree operations, reactive subscription ordering)\n- **Stress testing** — 500+ dedicated stress tests across core, plugins, and all 6 framework adapters: thousands of concurrent navigations, guard removal mid-execution, route CRUD under load, heap snapshots confirming zero memory leaks, mount/unmount lifecycle validation, subscription fanout granularity, and full SPA simulations\n- **Playwright e2e testing** — 1000+ end-to-end test cases across 100+ Playwright suites covering all 6 framework adapters (React, Preact, Solid, Vue, Svelte, Angular). Tests verify real browser behavior: navigation, guards, data loading, error handling, hash routing, nested routes, dynamic routes, and async guards\n- **Mutation testing** — [Stryker](https://stryker-mutator.io/) mutates source code and verifies that tests catch every mutation, ensuring test suite quality beyond line coverage\n- **Continuous performance benchmarking** — core hot-path navigation gated by [CodSpeed](https://codspeed.io/) on every PR: deterministic CPU-instruction-count measurement (not wall-clock) catches regressions before merge\n\n## Development\n\nThis is a pnpm monorepo with [Turborepo](https://turbo.build/repo) for task orchestration.\n\n```bash\npnpm install          # Install all dependencies\npnpm build            # Build all packages (errors-only output)\npnpm build:verbose    # Build with full output (debugging)\npnpm test -- --run    # Run tests once (errors-only output)\npnpm test:verbose     # Tests with full output (debugging)\npnpm type-check       # TypeScript type checking\npnpm lint             # ESLint check only — the gate (no --fix)\npnpm lint:fix         # ESLint with --fix (local auto-fix)\npnpm lint:e2e         # Verify e2e directories have spec files\npnpm lint:unused      # Check for unused code (knip)\n```\n\n### Windows: enable symlinks\n\nThe repo uses git-tracked symlinks to share source files across framework adapters (`packages/*/src/dom-utils` → `shared/dom-utils/` — see [IMPLEMENTATION_NOTES.md](IMPLEMENTATION_NOTES.md) for the rationale). Unix/macOS/Linux contributors need no extra setup. Windows contributors need a one-time configuration:\n\n```bash\n# 1. Enable symlink support in git (one-time, global)\ngit config --global core.symlinks true\n```\n\nAdditionally, enable [Developer Mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging) in Windows Settings, or run git from an elevated shell. After enabling both, re-clone the repo (or run `git checkout` on an existing clone) to materialize the symlinks. Without this, `pnpm install`, `pnpm build`, and `pnpm test` fail with \"file not found\" errors for paths under `src/dom-utils/`.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for full development setup, coding standards, and PR guidelines.\n\n## Contributing\n\nContributions are welcome! Please read the [contributing guidelines](CONTRIBUTING.md) before submitting a pull request.\n\n- [Good first issues](https://github.com/greydragon888/real-router/labels/good%20first%20issue) — great starting points for new contributors\n- [Help wanted](https://github.com/greydragon888/real-router/labels/help%20wanted) — issues where community input is needed\n\n## Changelog\n\nThe [changelog](https://github.com/greydragon888/real-router/releases) is regularly updated to reflect what's changed in each new release.\n\n## Security\n\nFor details on supported versions and reporting security vulnerabilities, please refer to the [security policy](SECURITY.md).\n\n## License\n\n[MIT](LICENSE) © [Oleg Ivanov](https://github.com/greydragon888)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreydragon888%2Freal-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgreydragon888%2Freal-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreydragon888%2Freal-router/lists"}