{"_id":"@doeixd/combi-router","_rev":"2-b19512431e0ff750ddc17fc4c23a9c5e","name":"@doeixd/combi-router","dist-tags":{"latest":"0.0.4"},"versions":{"0.0.3":{"name":"@doeixd/combi-router","version":"0.0.3","keywords":["pridepack","router","typescript","type-safe","composable","parser-combinators","standard-schema","routing","url","navigation","combi-parse","@doeixd/combi-router","client router"],"author":{"name":"Patrick Glenn"},"license":"MIT","_id":"@doeixd/combi-router@0.0.3","maintainers":[{"name":"doeixd","email":"doeixd@gmail.com"}],"homepage":"https://github.com/doeixd/combi-router","bugs":{"url":"https://github.com/doeixd/combi-router/issues"},"dist":{"shasum":"460ce8e11fd4c5551018bf7051d22611595ee430","tarball":"https://registry.npmjs.org/@doeixd/combi-router/-/combi-router-0.0.3.tgz","fileCount":166,"integrity":"sha512-ys8VlOG7wWDdQz8TAPk/l2JgDwQ+nndAnbMEcQCLqodAm2GBuu43FSNPP7TCw+q+bN0d0K42pY8ivTSHwrD3dg==","signatures":[{"sig":"MEYCIQDCLvO2N/jPyzunvMQ8e/cy9QEoBlqw/UVxHeDd1tPPxAIhANS1JkL4HpSaV5B0uURVr9WKPUyO9YmMvpA+Fv4HN4DW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":6844680},"engines":{"node":">=16"},"exports":{"0":{"types":"./dist/types/index.d.ts","import":"./dist/esm/production/0.js","require":"./dist/cjs/production/0.js","development":{"import":"./dist/esm/development/0.js","require":"./dist/cjs/development/0.js"}},"1":{"types":"./dist/types/components.d.ts","import":"./dist/esm/production/1.js","require":"./dist/cjs/production/1.js","development":{"import":"./dist/esm/development/1.js","require":"./dist/cjs/development/1.js"}},"2":{"types":"./dist/types/components-standalone.d.ts","import":"./dist/esm/production/2.js","require":"./dist/cjs/production/2.js","development":{"import":"./dist/esm/development/2.js","require":"./dist/cjs/development/2.js"}},"3":{"types":"./dist/types/utils.d.ts","import":"./dist/esm/production/3.js","require":"./dist/cjs/production/3.js","development":{"import":"./dist/esm/development/3.js","require":"./dist/cjs/development/3.js"}}},"gitHead":"61cbfcd1302d63e0708bcd51370d2adc7d7ae126","private":false,"scripts":{"dev":"pridepack dev","test":"vitest --run","build":"pridepack build && node scripts/fix-standalone.js","clean":"pridepack clean","start":"pridepack start","watch":"pridepack watch","release":"standard-version && git push --follow-tags origin main","type-check":"pridepack check","prepublishOnly":"pridepack clean && pridepack build && node scripts/fix-standalone.js"},"_npmUser":{"name":"doeixd","email":"doeixd@gmail.com"},"repository":{"url":"git+https://github.com/doeixd/combi-router.git","type":"git"},"_npmVersion":"8.19.4","description":"A router based on parser combinators","directories":{},"_nodeVersion":"16.20.2","dependencies":{"@doeixd/combi-parse":"^0.0.5","@standard-schema/spec":"^1.0.0"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"0":["./dist/types/index.d.ts"],"1":["./dist/types/components.d.ts"],"2":["./dist/types/components-standalone.d.ts"],"3":["./dist/types/utils.d.ts"]}},"_hasShrinkwrap":false,"devDependencies":{"zod":"^3.25.67","jsdom":"^26.1.0","tslib":"^2.8.1","vitest":"^2.1.8","pridepack":"2.6.4","typescript":"^5.7.2","@types/node":"^22.10.2","@types/jsdom":"^21.1.7","standard-version":"^9.5.0"},"_npmOperationalInternal":{"tmp":"tmp/combi-router_0.0.3_1754921552644_0.18545470238359552","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"@doeixd/combi-router","version":"0.0.4","engines":{"node":">=16"},"license":"MIT","keywords":["pridepack","router","typescript","type-safe","composable","parser-combinators","standard-schema","routing","url","navigation","combi-parse","@doeixd/combi-router","client router"],"devDependencies":{"@types/jsdom":"^21.1.7","@types/node":"^22.10.2","jsdom":"^26.1.0","pridepack":"2.6.4","standard-version":"^9.5.0","tslib":"^2.8.1","typescript":"^5.7.2","vitest":"^2.1.8","zod":"^3.25.67"},"scripts":{"release":"standard-version && git push --follow-tags origin main","prepublishOnly":"pridepack clean && pridepack build && node scripts/fix-standalone.js","build":"pridepack build && node scripts/fix-standalone.js","type-check":"pridepack check","clean":"pridepack clean","watch":"pridepack watch","start":"pridepack start","dev":"pridepack dev","test":"vitest --run"},"private":false,"description":"A router based on parser combinators","repository":{"url":"git+https://github.com/doeixd/combi-router.git","type":"git"},"homepage":"https://github.com/doeixd/combi-router","bugs":{"url":"https://github.com/doeixd/combi-router/issues"},"author":{"name":"Patrick Glenn"},"publishConfig":{"access":"public"},"dependencies":{"@doeixd/combi-parse":"^0.0.5","@standard-schema/spec":"^1.0.0"},"exports":{"0":{"types":"./dist/types/index.d.ts","development":{"require":"./dist/cjs/development/0.js","import":"./dist/esm/development/0.js"},"require":"./dist/cjs/production/0.js","import":"./dist/esm/production/0.js"},"1":{"types":"./dist/types/components.d.ts","development":{"require":"./dist/cjs/development/1.js","import":"./dist/esm/development/1.js"},"require":"./dist/cjs/production/1.js","import":"./dist/esm/production/1.js"},"2":{"types":"./dist/types/components-standalone.d.ts","development":{"require":"./dist/cjs/development/2.js","import":"./dist/esm/development/2.js"},"require":"./dist/cjs/production/2.js","import":"./dist/esm/production/2.js"},"3":{"types":"./dist/types/utils.d.ts","development":{"require":"./dist/cjs/development/3.js","import":"./dist/esm/development/3.js"},"require":"./dist/cjs/production/3.js","import":"./dist/esm/production/3.js"}},"typesVersions":{"*":{"0":["./dist/types/index.d.ts"],"1":["./dist/types/components.d.ts"],"2":["./dist/types/components-standalone.d.ts"],"3":["./dist/types/utils.d.ts"]}},"gitHead":"4592914e1e19b5111d7834dbd8940b6d7778d4b7","_id":"@doeixd/combi-router@0.0.4","_nodeVersion":"16.20.2","_npmVersion":"8.19.4","dist":{"integrity":"sha512-dVunZ50McyCx51EZpNed7eADx1G5f49NyaT8x2Fos1UKLU90Xx2JosyLGWYg5R9qgYSz8w7ZJvhQhY4Yk7BtrQ==","shasum":"ef981a981b80c702893be2f190e233fda4042f76","tarball":"https://registry.npmjs.org/@doeixd/combi-router/-/combi-router-0.0.4.tgz","fileCount":166,"unpackedSize":6838998,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBlcZqeaYeTcl1HonxPPvtF8WrCHJZaZkWoLdufVAcdRAiA+B4qOxCWVoaTPCxkwIKZ3DPE9EKt/pAhfw/0O7Mq0bg=="}]},"_npmUser":{"name":"doeixd","email":"doeixd@gmail.com"},"directories":{},"maintainers":[{"name":"doeixd","email":"doeixd@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/combi-router_0.0.4_1754950786438_0.8166532552625239"},"_hasShrinkwrap":false}},"time":{"created":"2025-08-11T14:12:32.576Z","modified":"2025-08-11T22:19:46.905Z","0.0.3":"2025-08-11T14:12:32.998Z","0.0.4":"2025-08-11T22:19:46.632Z"},"bugs":{"url":"https://github.com/doeixd/combi-router/issues"},"author":{"name":"Patrick Glenn"},"license":"MIT","homepage":"https://github.com/doeixd/combi-router","keywords":["pridepack","router","typescript","type-safe","composable","parser-combinators","standard-schema","routing","url","navigation","combi-parse","@doeixd/combi-router","client router"],"repository":{"url":"git+https://github.com/doeixd/combi-router.git","type":"git"},"description":"A router based on parser combinators","maintainers":[{"name":"doeixd","email":"doeixd@gmail.com"}],"readme":"[![npm version](https://badge.fury.io/js/@doeixd%2Fcombi-router.svg)](https://badge.fury.io/js/@doeixd%2Fcombi-router) [![TypeScript](https://img.shields.io/badge/-TypeScript-blue?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/) [![Build Status](https://img.shields.io/github/actions/workflow/status/doeixd/combi-router/ci.yml?branch=main)](https://github.com/doeixd/combi-router/actions)\n\n# Combi-Router 🛤️\n\nA composable, type-safe router built on my parser combinator library [Combi Parse](https://github.com/doeixd/combi-parse) that thinks in trees. Routes are defined functionally and composed by reference, creating natural hierarchies that mirror your application structure.\n\n<br />\n\n## 📦 Installation\n\n```bash\nnpm install @doeixd/combi-router @doeixd/combi-parse zod\n```\n\nCombi-Router is built on `@doeixd/combi-parse` for robust URL parsing and uses `zod` for powerful, type-safe parameter validation.\n\n<br />\n\n## ✨ Key Features\n&nbsp;&nbsp;🔗 **Type-Safe & Composable**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Build routes functionally and compose them by reference for perfect type safety and effortless refactoring.\n\n&nbsp;&nbsp;🌳 **Hierarchical & Introspective**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Routes create natural trees that mirror your app's structure, with built-in utilities to analyze the hierarchy.\n\n&nbsp;&nbsp;⚡ **Powerful Parallel Data Loading**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Automatically run data loaders for all nested routes in parallel (not sequentially), achieving 2-3x faster page loads. Advanced resource system with Suspense, caching, retries, and invalidation.\n\n&nbsp;&nbsp;🧩 **Composable Layer Architecture**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Build your ideal router by mixing and matching feature layers (data, performance, dev tools) or creating your own.\n\n&nbsp;&nbsp; 🛡️ **Advanced Navigation & Guards**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Navigate with detailed results, cancellation support, and robust, type-safe route guards for fine-grained access control.\n\n&nbsp;&nbsp;🎨 **Enhanced View Layer**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Universal template support with morphdom integration, true nested routing with outlets, and support for any templating system.\n\n&nbsp;&nbsp;🔎 **Integrated SEO & Head Management**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dynamically manage document head tags, including titles, meta descriptions, and social cards, directly from your route definitions.\n\n&nbsp;&nbsp; ✂️ **Tree-Shakeable & Modular**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A modular design ensures you only bundle the features you use, keeping your app lean and fast.\n\n&nbsp;&nbsp; 🛠️ **Superior Developer Experience**  \n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get dev-mode warnings, advanced debugging utilities, and detailed route analysis right out of the box.\n\n\n\n<!--\n  🔗 **Type-Safe & Composable:** Build routes functionally and compose them by reference for perfect type safety and effortless refactoring.\n  \n  🌳 **Hierarchical & Introspective:** Routes create natural trees that mirror your app's structure, with built-in utilities to analyze the hierarchy.\n  \n  ⚡ **Powerful Data Loading:** Run data loaders for nested routes in parallel, with an advanced resource system featuring Suspense, caching, retries, and invalidation.\n\n  🧩 **Composable Layer Architecture:** Build your ideal router by mixing and matching feature layers (data, performance, dev tools) or creating your own.\n  \n  ✂️ **Tree-Shakeable & Modular:** A modular design ensures you only bundle the features you use, keeping your app lean and fast.\n  \n  🚀 **Production Ready:** Includes intelligent prefetching, scroll restoration, memory management, and automatic support for the native View Transitions API.\n  \n  🛠️ **Superior Developer Experience:** Get dev-mode warnings, advanced debugging utilities, and detailed route analysis right out of the box.\n  \n  🌐 **Framework Agnostic:** Works seamlessly with any framework (React, Vue, Svelte) or vanilla JS, including a set of ready-to-use helpers and Web Components.\n\n### **Core Routing**\n- **Reference-Based Navigation**: Navigate using route objects for perfect type safety.\n- **Functional Composition**: Build routes by composing pure functions instead of method chaining.\n- **Hierarchical Matching**: Routes extend each other by reference, creating intuitive, nested trees.\n- **Route Introspection**: Built-in utilities for analyzing route structure (depth, ancestors, static paths).\n- **Advanced Navigation**: Detailed NavigationResult with error handling and cancellation support.\n- **Typed Guards**: Type-safe route protection with full parameter and context access.\n\n### **Data Loading & Resources**\n- **Parallel Data Loading**: Loaders for all active nested routes run concurrently for maximum speed.\n- **Suspense & Resources**: Elegant, built-in support for handling asynchronous data states.\n- **Advanced Resource System**: Enhanced resources with retry logic, caching, and invalidation strategies.\n- **Cache Tags & Invalidation**: Powerful cache management with tag-based invalidation.\n- **Global Resource State**: Centralized resource monitoring and observability.\n\n### **Composable Layer Architecture** 🧩\n- **Layer-Based Composition**: Build routers by composing independent feature layers using `makeLayered`.\n- **Built-in Layers**: Core navigation, data management, dev tools, performance, scroll restoration, transitions.\n- **User-Extensible**: Create custom layers for analytics, authentication, or any business logic.\n- **Self-Aware Layers**: Layers can call methods from previous layers for powerful orchestration.\n- **Conditional Composition**: Apply layers based on environment or feature flags.\n- **Type-Safe Extensions**: TypeScript correctly infers the final router shape across all layers.\n- **Tree-Shaking Optimized**: Only bundle the layers you actually use.\n\n### **Modular Architecture**\n- **Core Module**: Essential routing functionality (`@doeixd/combi-router/core`).\n- **Data Module**: Advanced resource and caching features (`@doeixd/combi-router/data`).\n- **Features Module**: Production optimizations (`@doeixd/combi-router/features`).\n- **Layers Module**: Composable layer system (`@doeixd/combi-router/layers`).\n- **Dev Module**: Development tools and debugging (`@doeixd/combi-router/dev`).\n- **Utils Module**: Framework-agnostic utilities (`@doeixd/combi-router/utils`).\n\n### **Integrated Layer System**\n- **Data Layer**: Advanced caching, resource management, and suspense-based data fetching.\n- **Dev Layer**: Comprehensive development tools, debugging, and performance monitoring.\n- **Performance Layer**: Intelligent prefetching, viewport-aware loading, and memory management.\n- **Scroll Restoration Layer**: Configurable scroll position management with state preservation.\n- **Transitions Layer**: Sophisticated page transitions with proper lifecycle management.\n- **Head Management Layer**: Dynamic document head management for SEO and social sharing.\n\n### **Developer Experience**\n- **Dev Mode Warnings**: Comprehensive development-time validation and conflict detection.\n- **Enhanced Debugging**: Advanced debugging utilities with performance monitoring.\n- **Route Analysis**: Detailed route structure analysis and optimization suggestions.\n- **Type Safety Improvements**: Better StandardSchema integration and parameter inference.\n\n### **Production Features**\n- **Performance Optimizations**: Intelligent prefetching, viewport-aware loading, and memory management.\n- **Scroll Restoration**: Configurable scroll position management with state preservation.\n- **Enhanced Code Splitting**: Advanced lazy loading strategies with priority-based prefetching.\n- **Advanced Transition System**: Sophisticated page transitions with proper lifecycle management.\n- **View Transitions**: App-like animated page transitions enabled by default in supported browsers.\n\n### **Framework Support**\n- **End-to-End Type Safety**: Full TypeScript inference from route definition to data access.\n- **Production Ready**: Caching, preloading, guards, lazy-loading, and error boundaries.\n- **Framework Agnostic**: Works with React, Vue, Svelte, or vanilla JavaScript.\n- **Web Components**: Ready-to-use declarative routing components.\n\n-->\n\n<br />\n\n## 🚀 Quick Start\n\nLet's start simple and build up your understanding step by step.\n\n### Understanding Routes\n\nA **route** in Combi-Router is a blueprint that describes a URL's structure and behavior.\n\n```typescript\nimport { route, path } from '@doeixd/combi-router';\n\n// This route matches the exact path \"/users\"\nexport const usersRoute = route(path('users'));\n```\n\nThe `route()` function creates a new route from **matchers**. Matchers are small building blocks that each handle one part of a URL.\n\n**Why export routes?** Routes are first-class objects you'll reference throughout your app for navigation, so treating them as exportable values makes them reusable and type-safe.\n\n### Basic Matchers\n\n```typescript\nimport { route, path, param } from '@doeixd/combi-router';\nimport { z } from 'zod';\n\n// Static path segment\nexport const aboutRoute = route(path('about'));  // matches \"/about\"\n\n// Dynamic parameter with validation\nexport const userRoute = route(\n  path('users'),\n  param('id', z.number())  // matches \"/users/123\" -> params.id is a number\n);\n```\n\n**Why validation?** URLs are just strings. By validating during route matching, you catch errors early and get proper TypeScript types for your parameters.\n\n### Building Route Trees\n\nThe real power comes from **composing routes by reference**. Instead of redefining common parts, you `extend` existing routes:\n\n```typescript\nimport { extend } from '@doeixd/combi-router';\n\n// Base route\nexport const dashboardRoute = route(path('dashboard'));\n\n// Extend the base route\nexport const usersRoute = extend(dashboardRoute, path('users'));\nexport const userRoute = extend(usersRoute, param('id', z.number()));\n\n// This creates a natural tree:\n// /dashboard           <- dashboardRoute\n// /dashboard/users     <- usersRoute  \n// /dashboard/users/123 <- userRoute\n```\n\n**Why extend?** When you change the base route (e.g., to `/admin`), all extended routes automatically update. Your route structure mirrors your application structure.\n\n### Adding Behavior with Higher-Order Functions\n\nEnhance routes with additional behavior using `pipe()` and higher-order functions:\n\n```typescript\nimport { meta, loader, layout, pipe } from '@doeixd/combi-router';\n\nexport const enhancedUserRoute = pipe(\n  userRoute,\n  meta({ title: 'User Profile' }),\n  loader(async ({ params }) => {\n    const user = await fetchUser(params.id);\n    return { user };\n  }),\n  layout(ProfileLayout)\n);\n```\n\n**Why higher-order functions?** They're composable and reusable. You can create your own enhancers and mix them with built-in ones.\n\n### Creating the Router\n\nOnce you have routes, create a router instance from an array of all your routes:\n\n```typescript\nimport { createRouter } from '@doeixd/combi-router';\n\nconst router = createRouter([\n  dashboardRoute,\n  usersRoute,\n  enhancedUserRoute\n]);\n\n// Reference-based navigation with detailed results\nconst result = await router.navigate(enhancedUserRoute, { id: 123 });\nif (result.success) {\n  console.log('Navigation successful');\n} else {\n  console.error('Navigation failed:', result.error);\n}\n\n// Simple navigation for backward compatibility  \nconst success = await router.navigateSimple(enhancedUserRoute, { id: 123 });\n\n// Type-safe URL building\nconst userUrl = router.build(enhancedUserRoute, { id: 123 }); // \"/dashboard/users/123\"\n```\n\n**Why route references?** Using actual route objects instead of string names provides perfect type inference and makes refactoring safe. TypeScript knows exactly what parameters each route needs.\n\n<br />\n\n## 🏗️ Core Concepts\n\n### Route Building Improvements\n\n#### Route Introspection Utilities\n\nRoutes now provide powerful introspection capabilities to analyze their structure:\n\n```typescript\nimport { route, extend, path, param } from '@doeixd/combi-router';\nimport { z } from 'zod';\n\nconst dashboardRoute = route(path('dashboard'));\nconst usersRoute = extend(dashboardRoute, path('users'));\nconst userRoute = extend(usersRoute, param('id', z.number()));\n\n// Analyze route structure\nconsole.log(userRoute.depth);        // 2 (dashboard -> users -> user)\nconsole.log(userRoute.ancestors);    // [dashboardRoute, usersRoute]\nconsole.log(userRoute.staticPath);   // \"/dashboard/users\"\nconsole.log(userRoute.paramNames);   // [\"id\"]\nconsole.log(userRoute.isDynamic);    // true\nconsole.log(userRoute.routeChain);   // [dashboardRoute, usersRoute, userRoute]\n```\n\n#### Route Validation at Creation Time\n\nRoutes are now validated when created, catching common configuration errors early:\n\n```typescript\nimport { RouteValidationError } from '@doeixd/combi-router';\n\ntry {\n  // This will throw if there are duplicate parameter names\n  const problematicRoute = extend(\n    route(param('id', z.string())),\n    param('id', z.number()) // Error: Duplicate parameter name 'id'\n  );\n} catch (error) {\n  if (error instanceof RouteValidationError) {\n    console.error('Route configuration error:', error.message);\n  }\n}\n```\n\n#### Parent-Child Relationships\n\nRoutes maintain explicit parent-child relationships for better debugging and tooling:\n\n```typescript\nconsole.log(userRoute.parent === usersRoute);     // true\nconsole.log(usersRoute.parent === dashboardRoute); // true\nconsole.log(dashboardRoute.parent);               // null (root route)\n\n// Walk up the hierarchy\nlet current = userRoute;\nwhile (current) {\n  console.log(current.staticPath);\n  current = current.parent;\n}\n// Output: \"/dashboard/users\", \"/dashboard\", \"/\"\n```\n\n### Route Matchers\n\nMatchers are the building blocks of routes. Each matcher handles one aspect of URL parsing:\n\n```typescript\n// Path segments\npath('users')                    // matches \"/users\"\npath.optional('category')        // matches \"/category\" or \"\"\npath.wildcard('segments')        // matches \"/any/number/of/segments\"\n\n// Parameters with validation\nparam('id', z.number())          // matches \"/123\" and validates as number\nparam('slug', z.string().min(3)) // matches \"/hello\" with minimum length\n\n// Query parameters\nquery('page', z.number().default(1)) // matches \"?page=5\"\nquery.optional('search', z.string()) // matches \"?search=term\"\n\n// Other components\nend                              // ensures no remaining path segments\n// subdomain(...) and hash(...) can be added with similar patterns\n```\n\n### Route Composition\n\nRoutes are composed functionally using `extend()`:\n\n```typescript\nexport const apiRoute = route(path('api'), path('v1'));\nexport const usersRoute = extend(apiRoute, path('users'));\nexport const userRoute = extend(usersRoute, param('id', z.number()));\n\n// userRoute now matches /api/v1/users/123\n```\n\nParameters from parent routes are automatically inherited and merged into a single `params` object.\n\n### Parallel Data Loading\n\nCombi-Router automatically executes loaders for all nested routes **in parallel**, not sequentially. This is a key performance feature that makes deeply nested routes load 2-3x faster.\n\n```typescript\n// Example: Three-level nested route with loaders\nconst orgRoute = pipe(\n  route(path('org'), param('orgId', z.string())),\n  loader(async ({ params }) => {\n    // Fetches organization data (500ms)\n    return { org: await fetchOrg(params.orgId) };\n  })\n);\n\nconst teamRoute = pipe(\n  extend(orgRoute, path('team'), param('teamId', z.string())),\n  loader(async ({ params }) => {\n    // Fetches team data (400ms)\n    return { team: await fetchTeam(params.teamId) };\n  })\n);\n\nconst memberRoute = pipe(\n  extend(teamRoute, path('member'), param('memberId', z.string())),\n  loader(async ({ params }) => {\n    // Fetches member data (300ms)\n    return { member: await fetchMember(params.memberId) };\n  })\n);\n\n// When navigating to /org/1/team/2/member/3:\n// ✅ All three loaders execute simultaneously\n// ✅ Total load time: 500ms (the slowest loader)\n// ❌ Without parallel loading: 1200ms (500+400+300)\n```\n\n**Why it matters:** Traditional routers often load data sequentially, causing waterfalls. Combi-Router's parallel loading ensures optimal performance by default, without any configuration needed.\n\n### Higher-Order Route Enhancers\n\nEnhance routes with additional functionality:\n\n```typescript\nimport { pipe, meta, loader, guard, cache, lazy } from '@doeixd/combi-router';\n\nexport const userRoute = pipe(\n  route(path('users'), param('id', z.number())),\n  meta({ title: (params) => `User ${params.id}` }),\n  loader(async ({ params }) => ({ user: await fetchUser(params.id) })),\n  guard(async () => await isAuthenticated() || '/login'),\n  cache({ ttl: 5 * 60 * 1000 }), // Cache for 5 minutes\n  lazy(() => import('./UserProfile'))\n);\n```\n\n<br />\n\n## 🔧 Modular Architecture\n\nCombi-Router now features a modular architecture optimized for tree-shaking and selective feature adoption.\n\n### Import Paths\n\n```typescript\n// Core routing functionality (always included)\nimport { route, extend, createRouter } from '@doeixd/combi-router';\n\n// Enhanced view layer with morphdom and template support\nimport { \n  createEnhancedViewLayer,\n  enhancedView,\n  lazyView,\n  conditionalView\n} from '@doeixd/combi-router/enhanced-view';\n\n// Advanced data loading and caching\nimport { createAdvancedResource, resourceState } from '@doeixd/combi-router/data';\n\n// Production features and optimizations\nimport { \n  PerformanceManager,\n  ScrollRestorationManager,\n  TransitionManager \n} from '@doeixd/combi-router/features';\n\n// Development tools and debugging\nimport { \n  createWarningSystem, \n  analyzeRoutes,\n  DebugUtils \n} from '@doeixd/combi-router/dev';\n\n// Framework-agnostic utilities\nimport { \n  createLink, \n  createActiveLink,\n  createOutlet \n} from '@doeixd/combi-router/utils';\n```\n\n### Module Breakdown\n\n#### Core Module (`@doeixd/combi-router`)\nEssential routing functionality including route definition, matching, navigation, and basic data loading.\n\n```typescript\nimport { \n  route, extend, path, param, query,\n  createRouter, pipe, meta, loader, guard\n} from '@doeixd/combi-router';\n```\n\n#### Data Module (`@doeixd/combi-router/data`)\nAdvanced resource management with caching, retry logic, and global state management.\n\n```typescript\nimport { \n  createAdvancedResource,\n  resourceState,\n  globalCache \n} from '@doeixd/combi-router/data';\n\n// Enhanced resource with retry and caching\nconst userResource = createAdvancedResource(\n  () => api.fetchUser(userId),\n  {\n    retry: { attempts: 3 },\n    cache: { ttl: 300000, invalidateOn: ['user'] },\n    staleTime: 60000,\n    backgroundRefetch: true\n  }\n);\n```\n\n#### Features Module (`@doeixd/combi-router/features`)\nProduction-ready features for performance optimization and user experience.\n\n```typescript\nimport { \n  PerformanceManager,\n  ScrollRestorationManager,\n  TransitionManager,\n  CodeSplittingManager \n} from '@doeixd/combi-router/features';\n\n// Initialize performance monitoring\nconst performanceManager = new PerformanceManager({\n  prefetchOnHover: true,\n  prefetchViewport: true,\n  enablePerformanceMonitoring: true,\n  connectionAware: true\n});\n```\n\n#### Dev Module (`@doeixd/combi-router/dev`)\nDevelopment tools for debugging and route analysis.\n\n```typescript\nimport { \n  createWarningSystem,\n  analyzeRoutes,\n  DebugUtils,\n  ConflictDetector \n} from '@doeixd/combi-router/dev';\n\n// Create warning system for development\nconst warningSystem = createWarningSystem(router, {\n  runtimeWarnings: true,\n  performanceWarnings: true\n});\n\n// Quick route analysis\nanalyzeRoutes(router);\n```\n\n#### Utils Module (`@doeixd/combi-router/utils`)\nFramework-agnostic utilities for DOM integration.\n\n```typescript\nimport { \n  createLink,\n  createActiveLink,\n  createOutlet,\n  createMatcher,\n  createRouterStore \n} from '@doeixd/combi-router/utils';\n```\n\n### Bundle Size Optimization\n\nThe modular architecture enables significant bundle size optimization:\n\n```typescript\n// Minimal bundle - only core routing\nimport { route, extend, createRouter } from '@doeixd/combi-router';\n\n// With advanced resources\nimport { createAdvancedResource } from '@doeixd/combi-router/data';\n\n// With production features\nimport { PerformanceManager } from '@doeixd/combi-router/features';\n\n// Development tools (excluded in production)\nimport { createWarningSystem } from '@doeixd/combi-router/dev';\n// (dev only)\n```\n\n<br />\n\n## 📊 Enhanced Resource System\n\nThe new resource system provides production-ready data loading with advanced features.\n\n### Basic Resources with Parallel Loading\n\n```typescript\nimport { createResource } from '@doeixd/combi-router';\n\n// Simple suspense-based resource with automatic parallel fetching\nconst userRoute = pipe(\n  route(path('users'), param('id', z.number())),\n  loader(({ params }) => ({\n    // These resources load in parallel automatically\n    user: createResource(() => fetchUser(params.id)),\n    posts: createResource(() => fetchUserPosts(params.id))\n  }))\n);\n\n// In your component\nfunction UserProfile() {\n  const { user, posts } = router.currentMatch.data;\n  \n  // These will suspend until data is ready\n  const userData = user.read();\n  const postsData = posts.read();\n  \n  return <div>...</div>;\n}\n```\n\n### Advanced Resources\n\n```typescript\nimport { createAdvancedResource, resourceState } from '@doeixd/combi-router/data';\n\n// Enhanced resource with all features\nconst userResource = createAdvancedResource(\n  () => api.fetchUser(userId),\n  {\n    // Retry configuration with exponential backoff\n    retry: {\n      attempts: 3,\n      delay: (attempt) => Math.min(1000 * Math.pow(2, attempt - 1), 10000),\n      shouldRetry: (error) => error.status >= 500,\n      onRetry: (error, attempt) => console.log(`Retry ${attempt}:`, error)\n    },\n    \n    // Caching with tags for invalidation\n    cache: {\n      ttl: 300000, // 5 minutes\n      invalidateOn: ['user', 'profile'],\n      priority: 'high'\n    },\n    \n    // Stale-while-revalidate behavior\n    staleTime: 60000, // 1 minute\n    backgroundRefetch: true\n  }\n);\n\n// Check state without suspending\nif (userResource.isLoading) {\n  console.log('Loading user...');\n}\n\n// Non-suspending peek at cached data\nconst cachedUser = userResource.peek();\nif (cachedUser) {\n  console.log('Cached user:', cachedUser);\n}\n\n// Force refresh\nawait userResource.refetch();\n\n// Invalidate resource\nuserResource.invalidate();\n```\n\n### Cache Management\n\n```typescript\nimport { resourceState } from '@doeixd/combi-router/data';\n\n// Global resource state monitoring\nconst globalState = resourceState.getGlobalState();\nconsole.log('Loading resources:', globalState.loadingCount);\n\n// Event system for observability\nconst unsubscribe = resourceState.onEvent((event) => {\n  switch (event.type) {\n    case 'fetch-start':\n      console.log('Started loading:', event.resource);\n      break;\n    case 'fetch-success':\n      console.log('Loaded successfully:', event.data);\n      break;\n    case 'fetch-error':\n      console.error('Loading failed:', event.error);\n      break;\n    case 'retry':\n      console.log(`Retry attempt ${event.attempt}:`, event.error);\n      break;\n  }\n});\n\n// Cache invalidation by tags\nresourceState.invalidateByTags(['user', 'profile']);\n```\n\n<br />\n\n## 🚀 Performance Features\n\n### Intelligent Prefetching\n\n```typescript\nimport { PerformanceManager } from '@doeixd/combi-router/features';\n\nconst performanceManager = new PerformanceManager({\n  // Prefetch on hover with delay\n  prefetchOnHover: true,\n  \n  // Prefetch when links enter viewport\n  prefetchViewport: true,\n  \n  // Adjust behavior based on connection\n  connectionAware: true,\n  \n  // Monitor performance metrics\n  enablePerformanceMonitoring: true,\n  \n  // Preload critical routes immediately\n  preloadCriticalRoutes: ['dashboard', 'user-profile'],\n  \n  // Memory management\n  memoryManagement: {\n    enabled: true,\n    maxCacheSize: 50,\n    maxCacheAge: 30 * 60 * 1000,\n    cleanupInterval: 5 * 60 * 1000\n  }\n});\n\n// Setup hover prefetching for a link\nconst cleanup = performanceManager.setupHoverPrefetch(linkElement, 'user-route');\n\n// Setup viewport prefetching\nconst cleanupViewport = performanceManager.setupViewportPrefetch(linkElement, 'user-route');\n\n// Get performance report\nconst report = performanceManager.getPerformanceReport();\nconsole.log('Prefetch hit rate:', report.prefetchHitRate);\n```\n\n### Scroll Restoration\n\n```typescript\nimport { ScrollRestorationManager } from '@doeixd/combi-router/features';\n\nconst scrollManager = new ScrollRestorationManager({\n  enabled: true,\n  restoreOnBack: true,\n  restoreOnForward: true,\n  saveScrollState: true,\n  smoothScrolling: true,\n  scrollBehavior: 'smooth',\n  debounceTime: 100,\n  \n  // Advanced configuration\n  customScrollContainer: '#main-content',\n  excludeRoutes: ['modal-routes'],\n  persistScrollState: true\n});\n\n// Manual scroll position management\nscrollManager.saveScrollPosition(routeId);\nscrollManager.restoreScrollPosition(routeId);\nscrollManager.scrollToTop();\nscrollManager.scrollToElement('#section');\n```\n\n### Advanced Transitions\n\n```typescript\nimport { TransitionManager } from '@doeixd/combi-router/features';\n\nconst transitionManager = new TransitionManager({\n  enabled: true,\n  duration: 300,\n  easing: 'ease-in-out',\n  type: 'fade',\n  \n  // Per-route transition configuration\n  routeTransitions: {\n    'user-profile': { type: 'slide-left', duration: 400 },\n    'settings': { type: 'fade', duration: 200 }\n  },\n  \n  // Custom transition classes\n  transitionClasses: {\n    enter: 'page-enter',\n    enterActive: 'page-enter-active',\n    exit: 'page-exit',\n    exitActive: 'page-exit-active'\n  }\n});\n\n// Manual transition control\nawait transitionManager.performTransition(fromRoute, toRoute, {\n  direction: 'forward',\n  customData: { userId: 123 }\n});\n```\n\n<br />\n\n## 🛠️ Development Experience\n\n### Development Warnings\n\n```typescript\nimport { createWarningSystem, analyzeRoutes } from '@doeixd/combi-router/dev';\n\n// Create comprehensive warning system\nconst warningSystem = createWarningSystem(router, {\n  runtimeWarnings: true,\n  staticWarnings: true,\n  performanceWarnings: true,\n  severityFilter: ['warning', 'error']\n});\n\n// Quick route analysis\nanalyzeRoutes(router);\n\n// Get warnings programmatically\nconst warnings = warningSystem.getWarnings();\nconst conflictWarnings = warningSystem.getWarningsByType('conflicting-routes');\nconst errorWarnings = warningSystem.getWarningsBySeverity('error');\n```\n\n### Debugging Tools\n\n```typescript\nimport { DebugUtils } from '@doeixd/combi-router/dev';\n\n// Route structure debugging\nDebugUtils.logRouteTree(router);\nDebugUtils.analyzeRoutePerformance(router);\nDebugUtils.checkRouteConflicts(router);\n\n// Navigation debugging\nDebugUtils.enableNavigationLogging(router);\nDebugUtils.logMatchDetails(currentMatch);\n\n// Performance debugging\nDebugUtils.enablePerformanceMonitoring(router);\nconst metrics = DebugUtils.getPerformanceMetrics();\n```\n\n### Enhanced Error Handling\n\n```typescript\nimport { NavigationErrorType } from '@doeixd/combi-router';\n\nconst result = await router.navigate(userRoute, { id: 123 });\n\nif (!result.success) {\n  switch (result.error?.type) {\n    case NavigationErrorType.RouteNotFound:\n      console.error('Route not found');\n      break;\n    case NavigationErrorType.GuardRejected:\n      console.error('Navigation blocked:', result.error.message);\n      break;\n    case NavigationErrorType.LoaderFailed:\n      console.error('Data loading failed:', result.error.originalError);\n      break;\n    case NavigationErrorType.ValidationFailed:\n      console.error('Parameter validation failed');\n      break;\n    case NavigationErrorType.Cancelled:\n      console.log('Navigation was cancelled');\n      break;\n  }\n}\n```\n\n<br />\n\n## 🔄 Migration Guide\n\n### From v1.x to v2.x\n\n#### Modular Imports\n\n**Before:**\n```typescript\nimport { createRouter, createResource, createLink } from '@doeixd/combi-router';\n```\n\n**After:**\n```typescript\n// Core functionality\nimport { createRouter } from '@doeixd/combi-router';\n\n// Advanced resources (optional)\nimport { createAdvancedResource } from '@doeixd/combi-router/data';\n\n// Utilities (optional)\nimport { createLink } from '@doeixd/combi-router/utils';\n```\n\n#### Enhanced Resources\n\n**Before:**\n```typescript\nconst resource = createResource(() => fetchUser(id));\n```\n\n**After:**\n```typescript\n// Simple resource (same API)\nconst resource = createResource(() => fetchUser(id));\n\n// Or enhanced resource with more features\nconst resource = createAdvancedResource(\n  () => fetchUser(id),\n  {\n    retry: { attempts: 3 },\n    cache: { ttl: 300000 },\n    staleTime: 60000\n  }\n);\n```\n\n#### Navigation API\n\nThe navigation API is fully backward compatible. Enhanced error handling is opt-in:\n\n```typescript\n// Old way (still works)\nconst success = await router.navigateSimple(route, params);\n\n// New way (detailed error information)\nconst result = await router.navigate(route, params);\nif (result.success) {\n  // Handle success\n} else {\n  // Handle specific error types\n}\n```\n\n<br />\n\n## 🎨 Enhanced View Layer\n\nThe Enhanced View Layer extends Combi-Router with advanced DOM rendering capabilities, efficient updates through morphdom, and true nested routing support.\n\n### Universal Template Support\n\nWork with any templating system - lit-html, uhtml, Handlebars, or plain strings:\n\n```typescript\nimport { createEnhancedViewLayer, enhancedView } from '@doeixd/combi-router/enhanced-view';\nimport { html } from 'lit-html';\n\n// Using lit-html templates\nconst userRoute = pipe(\n  route(path('user'), param('id', z.string()), end),\n  enhancedView(({ match }) => html`\n    <div class=\"user-profile\">\n      <h1>${match.data.user.name}</h1>\n      <p>Email: ${match.data.user.email}</p>\n    </div>\n  `)\n);\n\n// Using custom template engines\nimport Handlebars from 'handlebars';\n\nconst template = Handlebars.compile(`\n  <div class=\"product\">\n    <h2>{{name}}</h2>\n    <p>Price: \\${{price}}</p>\n  </div>\n`);\n\nconst productRoute = pipe(\n  route(path('product'), param('id', z.string()), end),\n  enhancedView(({ match }) => ({\n    html: template(match.data.product)\n  }))\n);\n\n// Configure the router with enhanced view layer\nconst router = createLayeredRouter(routes)\n  (createCoreNavigationLayer())\n  (createEnhancedViewLayer({\n    root: '#app',\n    useMorphdom: true,\n    templateRenderer: (result, container) => {\n      // Custom renderer for your template library\n      if (result._$litType$) {\n        litRender(result, container);\n      }\n    }\n  }))\n  ();\n```\n\n### Morphdom Integration\n\nEnable efficient DOM patching that preserves form state, focus, and scroll position:\n\n```typescript\nimport morphdom from 'morphdom';\nimport { setMorphdom } from '@doeixd/combi-router/enhanced-view';\n\n// Provide morphdom implementation\nsetMorphdom(morphdom);\n\n// Configure morphdom behavior\nconst router = createLayeredRouter(routes)\n  (createCoreNavigationLayer())\n  (createEnhancedViewLayer({\n    root: '#app',\n    useMorphdom: true,\n    morphdomOptions: {\n      onBeforeElUpdated: (fromEl, toEl) => {\n        // Preserve focus\n        if (fromEl === document.activeElement) {\n          return false;\n        }\n        // Preserve form values\n        if (fromEl.tagName === 'INPUT') {\n          toEl.value = fromEl.value;\n        }\n        return true;\n      },\n      onElUpdated: (el) => {\n        // Add animation classes\n        el.classList.add('updated');\n        setTimeout(() => el.classList.remove('updated'), 300);\n      }\n    }\n  }))\n  ();\n```\n\n### True Nested Routing with Outlets\n\nLeverage the hierarchical route structure for automatic nested view rendering:\n\n```typescript\n// Parent route with outlet\nconst appRoute = pipe(\n  route(path('')),\n  enhancedView(() => html`\n    <div class=\"app\">\n      <header>\n        <nav>\n          <a href=\"/\">Home</a>\n          <a href=\"/dashboard\">Dashboard</a>\n        </nav>\n      </header>\n      <!-- Child routes render here automatically -->\n      <main router-outlet></main>\n    </div>\n  `)\n);\n\n// Dashboard with its own nested outlet\nconst dashboardRoute = pipe(\n  extend(appRoute, path('dashboard')),\n  enhancedView(({ match }) => html`\n    <div class=\"dashboard\">\n      <aside>\n        <a href=\"/dashboard/overview\">Overview</a>\n        <a href=\"/dashboard/analytics\">Analytics</a>\n      </aside>\n      <!-- Nested child routes render here -->\n      <section router-outlet router-outlet-parent=\"${match.route.id}\">\n      </section>\n    </div>\n  `)\n);\n\n// Child routes automatically render in parent outlets\nconst overviewRoute = pipe(\n  extend(dashboardRoute, path('overview'), end),\n  enhancedView(() => html`\n    <div class=\"overview\">\n      <h2>Dashboard Overview</h2>\n      <p>Your stats and metrics...</p>\n    </div>\n  `)\n);\n```\n\n### Parallel Data Loading in Nested Routes\n\nOne of Combi-Router's most powerful features is **automatic parallel data fetching** for nested routes. When navigating to a deeply nested route, all loaders execute simultaneously, not sequentially.\n\n#### How It Works\n\n```typescript\n// Each route has its own loader\nconst workspaceRoute = pipe(\n  extend(appRoute, path('workspace'), param('workspaceId', z.string())),\n  loader(async ({ params }) => {\n    const workspace = await fetchWorkspace(params.workspaceId); // Takes 500ms\n    return { workspace };\n  })\n);\n\nconst projectRoute = pipe(\n  extend(workspaceRoute, path('project'), param('projectId', z.string())),\n  loader(async ({ params }) => {\n    const project = await fetchProject(params.projectId); // Takes 400ms\n    return { project };\n  })\n);\n\nconst taskRoute = pipe(\n  extend(projectRoute, path('task'), param('taskId', z.string())),\n  loader(async ({ params }) => {\n    const task = await fetchTask(params.taskId); // Takes 300ms\n    return { task };\n  })\n);\n\n// When navigating to /workspace/123/project/456/task/789:\n// ALL three loaders start simultaneously!\n// Total time: ~500ms (the longest loader), NOT 1200ms!\n```\n\n#### Performance Impact\n\n- **Sequential Loading**: 500ms + 400ms + 300ms = **1200ms** ❌\n- **Parallel Loading**: max(500ms, 400ms, 300ms) = **500ms** ✅\n\nThis results in **2-3x faster page loads** for deeply nested routes!\n\n#### Configuration\n\n```typescript\nconst router = createLayeredRouter(routes)\n  (createCoreNavigationLayer())\n  (createLoaderLayer({\n    parallelLoading: true,  // Enabled by default\n    loaderTimeout: 10000,   // Timeout applies to each loader individually\n  }))\n  ();\n```\n\n#### Best Practices\n\n```typescript\n// ✅ Good: Independent loaders using URL params\nconst teamRoute = pipe(\n  extend(orgRoute, path('team'), param('teamId', z.string())),\n  loader(async ({ params }) => {\n    // Uses teamId from URL, doesn't wait for parent data\n    const team = await fetchTeam(params.teamId);\n    return { team };\n  })\n);\n\n// ✅ Good: Access parent data after parallel loading\nconst projectView = enhancedView(({ match }) => {\n  // All data is available after parallel loading completes\n  const workspace = match.parent?.data?.workspace;\n  const project = match.data.project;\n  \n  return html`\n    <h1>${workspace.name} / ${project.name}</h1>\n  `;\n});\n```\n\n#### Outlet Configuration\n\n```html\n<!-- Basic outlet -->\n<div router-outlet></div>\n\n<!-- Outlet with specific parent route -->\n<div router-outlet router-outlet-parent=\"42\"></div>\n\n<!-- Outlet with transitions -->\n<div \n  router-outlet\n  router-outlet-enter=\"fade-in\"\n  router-outlet-leave=\"fade-out\"\n  router-outlet-duration=\"300\">\n</div>\n\n<!-- Preserve scroll position -->\n<div router-outlet router-outlet-preserve-scroll></div>\n```\n\n### Advanced View Functions\n\n#### Lazy Loading Views\n\n```typescript\nconst route = pipe(\n  route(path('heavy'), end),\n  lazyView(\n    () => import('./heavy-view').then(m => m.default),\n    () => '<div>Loading...</div>' // Loading view while importing\n  )\n);\n```\n\n#### Conditional Views\n\n```typescript\nconst route = pipe(\n  route(path('profile'), param('id'), end),\n  conditionalView(\n    ({ match }) => match.data.user.isAdmin,\n    ({ match }) => html`<admin-dashboard user=\"${match.data.user}\"></admin-dashboard>`,\n    ({ match }) => html`<user-profile user=\"${match.data.user}\"></user-profile>`\n  )\n);\n```\n\n#### Error Boundary Views\n\n```typescript\nconst route = pipe(\n  route(path('fragile'), end),\n  errorBoundaryView(\n    ({ match }) => riskyRenderFunction(match),\n    (error) => html`\n      <div class=\"error\">\n        <h2>Something went wrong</h2>\n        <p>${error.message}</p>\n      </div>\n    `\n  )\n);\n```\n\n#### Composed Views\n\n```typescript\nconst route = pipe(\n  route(path('complex'), end),\n  composeViews({\n    header: ({ match }) => html`<header>${match.data.title}</header>`,\n    sidebar: () => html`<nav>Menu items...</nav>`,\n    content: ({ match }) => html`<main>${match.data.content}</main>`\n  }, (parts) => html`\n    <div class=\"layout\">\n      ${parts.header}\n      <div class=\"body\">\n        ${parts.sidebar}\n        ${parts.content}\n      </div>\n    </div>\n  `)\n);\n```\n\n#### Cached Views\n\n```typescript\nconst route = pipe(\n  route(path('expensive'), param('id'), end),\n  cachedView(\n    ({ match }) => expensiveRender(match.data),\n    ({ match }) => `cache-${match.params.id}`, // Cache key\n    60000 // Cache for 1 minute\n  )\n);\n```\n\n### Configuration Options\n\n```typescript\ninterface EnhancedViewLayerConfig {\n  // Root element for rendering (required)\n  root: HTMLElement | string;\n  \n  // Enable morphdom for efficient updates\n  useMorphdom?: boolean;\n  \n  // Morphdom configuration\n  morphdomOptions?: MorphdomOptions;\n  \n  // Custom template renderer for your library\n  templateRenderer?: (result: any, container: HTMLElement) => void;\n  \n  // State views\n  loadingView?: () => any;\n  errorView?: (error: NavigationError) => any;\n  notFoundView?: () => any;\n  \n  // Nested routing support\n  enableOutlets?: boolean;\n  outletAttribute?: string; // default: 'router-outlet'\n}\n```\n\n### Why Enhanced View Layer?\n\nThe enhanced view layer solves common SPA rendering challenges:\n\n- **No Template Lock-in**: Use lit-html, uhtml, Handlebars, or any other template system\n- **Efficient Updates**: Morphdom ensures only changed DOM nodes are updated\n- **True Nested Routing**: Hierarchical routes automatically manage nested views through outlets\n- **Progressive Enhancement**: Start with simple string templates, upgrade to advanced features as needed\n- **Performance Optimized**: Built-in caching, lazy loading, and smart update strategies\n- **Developer Friendly**: Intuitive outlet system mirrors your route hierarchy\n\n### Enhanced View Layer API Reference\n\n#### Core Functions\n\n##### `createEnhancedViewLayer(config)`\nCreates an enhanced view layer with morphdom support and nested routing.\n\n```typescript\nfunction createEnhancedViewLayer(config: EnhancedViewLayerConfig): RouterLayer\n\ninterface EnhancedViewLayerConfig {\n  root: HTMLElement | string;              // Root element for rendering (required)\n  useMorphdom?: boolean;                   // Enable morphdom for efficient updates\n  morphdomOptions?: MorphdomOptions;       // Morphdom configuration\n  templateRenderer?: (result: TemplateResult, container: HTMLElement) => void;\n  loadingView?: () => string | Node | TemplateResult;\n  errorView?: (error: NavigationError) => string | Node | TemplateResult;\n  notFoundView?: () => string | Node | TemplateResult;\n  linkSelector?: string;                   // Custom link selector (default: 'a[href]')\n  disableLinkInterception?: boolean;       // Disable automatic SPA navigation\n  enableOutlets?: boolean;                 // Enable nested routing outlets\n  outletAttribute?: string;                // Outlet attribute name (default: 'router-outlet')\n}\n```\n\n##### `enhancedView(factory)`\nCreates an enhanced view for a route supporting multiple template formats.\n\n```typescript\nfunction enhancedView<TParams>(\n  factory: (context: ViewContext<TParams>) => \n    string | Node | TemplateResult | HTMLTemplateResult | Promise<any>\n): (route: Route<TParams>) => Route<TParams>\n\ninterface ViewContext<TParams> {\n  match: RouteMatch<TParams>;  // Full route match with params, data, etc.\n}\n```\n\n##### `htmlTemplate(html, options)`\nCreates an HTML template result with lifecycle hooks.\n\n```typescript\nfunction htmlTemplate(\n  html: string,\n  options?: {\n    afterRender?: (element: HTMLElement) => void;\n    beforeRender?: () => void;\n  }\n): HTMLTemplateResult\n```\n\n##### `lazyView(loader, loadingView)`\nCreates a lazily loaded view with optional loading state.\n\n```typescript\nfunction lazyView<TParams>(\n  loader: () => Promise<EnhancedViewFactory<TParams>>,\n  loadingView?: EnhancedViewFactory<TParams>\n): (route: Route<TParams>) => Route<TParams>\n```\n\n##### `conditionalView(condition, trueView, falseView)`\nRenders different views based on a condition.\n\n```typescript\nfunction conditionalView<TParams>(\n  condition: (context: ViewContext<TParams>) => boolean,\n  trueView: EnhancedViewFactory<TParams>,\n  falseView: EnhancedViewFactory<TParams>\n): (route: Route<TParams>) => Route<TParams>\n```\n\n##### `errorBoundaryView(view, errorView)`\nWraps a view with error handling.\n\n```typescript\nfunction errorBoundaryView<TParams>(\n  view: EnhancedViewFactory<TParams>,\n  errorView: (error: Error) => string | Node | TemplateResult\n): (route: Route<TParams>) => Route<TParams>\n```\n\n##### `composeViews(parts, composer)`\nComposes multiple view parts into a single view.\n\n```typescript\nfunction composeViews<TParams, TParts extends Record<string, any>>(\n  parts: { [K in keyof TParts]: EnhancedViewFactory<TParams> },\n  composer: (parts: TParts) => string | Node | TemplateResult\n): (route: Route<TParams>) => Route<TParams>\n```\n\n##### `cachedView(factory, keyFn, ttl)`\nCaches rendered views for performance.\n\n```typescript\nfunction cachedView<TParams>(\n  factory: EnhancedViewFactory<TParams>,\n  keyFn: (context: ViewContext<TParams>) => string,\n  ttl?: number  // Time to live in milliseconds (default: 60000)\n): (route: Route<TParams>) => Route<TParams>\n```\n\n##### `streamingView(generator)`\nCreates a streaming view that updates progressively.\n\n```typescript\nfunction streamingView<TParams>(\n  generator: (context: ViewContext<TParams>) => \n    AsyncGenerator<string | Node | TemplateResult>\n): (route: Route<TParams>) => Route<TParams>\n```\n\n#### Morphdom Integration\n\n##### `setMorphdom(morphdom)`\nSets the morphdom implementation to use.\n\n```typescript\nfunction setMorphdom(morphdom: MorphdomFn): void\n\ntype MorphdomFn = (\n  fromNode: Element,\n  toNode: Element | string,\n  options?: MorphdomOptions\n) => Element\n```\n\n##### `createMorphdomIntegration(options)`\nCreates a morphdom configuration with defaults.\n\n```typescript\nfunction createMorphdomIntegration(options?: Partial<MorphdomOptions>): {\n  morphdom: MorphdomFn;\n  options: MorphdomOptions;\n}\n\ninterface MorphdomOptions {\n  childrenOnly?: boolean;\n  onBeforeElUpdated?: (fromEl: Element, toEl: Element) => boolean;\n  onElUpdated?: (el: Element) => void;\n  onBeforeNodeAdded?: (node: Node) => Node | boolean;\n  onNodeAdded?: (node: Node) => void;\n  onBeforeNodeDiscarded?: (node: Node) => boolean;\n  onNodeDiscarded?: (node: Node) => void;\n  onBeforeElChildrenUpdated?: (fromEl: Element, toEl: Element) => boolean;\n}\n```\n\n#### Nested Routing\n\n##### `createNestedRouter(config)`\nCreates a nested router for parent-child route relationships.\n\n```typescript\nfunction createNestedRouter(config: NestedRouterConfig): {\n  parent: Route<any>;\n  children: Route<any>[];\n  outlets: Map<string, RouterOutlet>;\n  findChildMatch: (match: RouteMatch | null) => RouteMatch | null;\n  renderChild: (match: RouteMatch | null, outlet?: HTMLElement) => void;\n  destroy: () => void;\n}\n\ninterface NestedRouterConfig {\n  parentRoute: Route<any>;\n  childRoutes: Route<any>[];\n  outlet?: HTMLElement | string;\n  autoManageOutlet?: boolean;\n}\n```\n\n##### `createRouterOutlet(router, config)`\nCreates a router outlet for automatic child route rendering.\n\n```typescript\nfunction createRouterOutlet(\n  router: ComposableRouter<any>,\n  config: OutletConfig\n): RouterOutlet & {\n  update: (match: RouteMatch | null) => void;\n  clear: () => void;\n  destroy: () => void;\n}\n\ninterface OutletConfig {\n  element: HTMLElement;\n  parentRouteId?: number;\n  render?: (match: RouteMatch | null, element: HTMLElement) => void;\n  transition?: {\n    enter?: string;\n    leave?: string;\n    duration?: number;\n  };\n  preserveScroll?: boolean;\n  loadingView?: () => string | Node;\n  errorView?: (error: Error) => string | Node;\n}\n```\n\n##### `setupAutoOutlets(router, routes, container, attribute)`\nAutomatically discovers and sets up outlets in a container.\n\n```typescript\nfunction setupAutoOutlets(\n  router: ComposableRouter<any>,\n  routes: Route<any>[],\n  container?: HTMLElement,  // default: document.body\n  attribute?: string        // default: 'router-outlet'\n): () => void  // Returns cleanup function\n```\n\n#### Layer Extensions\n\nThe enhanced view layer provides these methods on the router:\n\n```typescript\ninterface EnhancedViewLayerExtensions {\n  rerender(): void;                                    // Re-render current view\n  getRootElement(): HTMLElement | null;                // Get root element\n  updateConfig(config: Partial<EnhancedViewLayerConfig>): void;\n  registerOutlet(outlet: RouterOutlet): void;          // Register outlet\n  unregisterOutlet(outlet: RouterOutlet): void;        // Unregister outlet\n  morphUpdate(content: string | Node): void;           // Force morphdom update\n}\n\n// Access layer extensions\nconst viewLayer = router.getLayer('EnhancedViewLayer');\nviewLayer.rerender();\nviewLayer.morphUpdate('<div>New content</div>');\n```\n\n#### Type Definitions\n\n```typescript\n// Template result types for various libraries\ninterface TemplateResult {\n  strings?: TemplateStringsArray;\n  values?: unknown[];\n  _$litType$?: number;  // lit-html marker\n  [key: string]: any;\n}\n\ninterface HTMLTemplateResult {\n  template?: HTMLTemplateElement;\n  render?: () => Node | string;\n  html?: string;\n  dom?: DocumentFragment;\n}\n\n// Enhanced view factory supporting multiple return types\ntype EnhancedViewFactory<TParams = any> = (\n  context: ViewContext<TParams>\n) => string | Node | TemplateResult | HTMLTemplateResult | Promise<any>;\n\n// Router outlet interface\ninterface RouterOutlet {\n  element: HTMLElement;\n  parentRouteId?: number;\n  render: (match: RouteMatch | null) => void;\n}\n```\n\n<br />\n\n## 🗂️ Advanced Features\n\n### Document Head Management\n\nThe head management module provides comprehensive document head tag management with support for dynamic content, SEO optimization, and server-side rendering.\n\n#### Basic Head Management\n\n```typescript\nimport { head, seoMeta } from '@doeixd/combi-router/features';\n\n// Static head data\nconst aboutRoute = pipe(\n  route(path('about')),\n  head({\n    title: 'About Us',\n    meta: [\n      { name: 'description', content: 'Learn more about our company' },\n      { name: 'keywords', content: 'about, company, team' }\n    ],\n    link: [\n      { rel: 'canonical', href: 'https://example.com/about' }\n    ]\n  })\n);\n\n// Dynamic head data based on route parameters\nconst userRoute = pipe(\n  route(path('users'), param('id', z.number())),\n  head(({ params }) => ({\n    title: `User Profile - ${params.id}`,\n    meta: [\n      { name: 'description', content: `Profile page for user ${params.id}` }\n    ]\n  }))\n);\n```\n\n#### SEO Optimization\n\n```typescript\n// Complete SEO setup with Open Graph and Twitter Cards\nconst productRoute = pipe(\n  route(path('products'), param('id', z.number())),\n  head(({ params }) => ({\n    title: `Product ${params.id}`,\n    titleTemplate: 'Store | %s', // Results in: \"Store | Product 123\"\n    \n    // Basic SEO\n    ...seoMeta.basic({\n      description: `Amazing product ${params.id}`,\n      keywords: ['product', 'store', 'shopping'],\n      robots: 'index,follow'\n    }),\n    \n    // Open Graph tags\n    ...seoMeta.og({\n      title: `Product ${params.id}`,\n      description: 'The best product you will ever buy',\n      image: `https://example.com/products/${params.id}/image.jpg`,\n      url: `https://example.com/products/${params.id}`,\n      type: 'product'\n    }),\n    \n    // Twitter Cards\n    ...seoMeta.twitter({\n      card: 'summary_large_image',\n      title: `Product ${params.id}`,\n      description: 'An amazing product',\n      image: `https://example.com/products/${params.id}/twitter.jpg`\n    })\n  }))\n);\n```\n\n#### Advanced Features\n\n```typescript\n// Scripts, styles, and HTML attributes\nconst dashboardRoute = pipe(\n  route(path('dashboard')),\n  head({\n    title: 'Dashboard',\n    script: [\n      { src: 'https://analytics.example.com/track.js', async: true },\n      { innerHTML: 'window.config = { theme: \"dark\" };' }\n    ],\n    style: [\n      { innerHTML: 'body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }' }\n    ],\n    htmlAttrs: { lang: 'en', 'data-theme': 'dark' },\n    bodyAttrs: { class: 'dashboard dark-mode' }\n  })\n);\n```\n\n#### DOM Integration\n\n```typescript\nimport { HeadManager, resolveHeadData } from '@doeixd/combi-router/features';\n\n// Initialize head manager\nconst headManager = new HeadManager(document);\n\n// Update head tags on navigation\nrouter.onNavigate((match) => {\n  if (match?.route._head) {\n    const resolvedHead = resolveHeadData(match.route._head, match);\n    headManager.apply(resolvedHead);\n  }\n});\n```\n\nFor complete documentation, see [Head Management Guide](docs/head-management.md).\n\n### Navigation Improvements\n\n#### NavigationResult with Detailed Error Handling\n\nThe `navigate()` method now returns a `NavigationResult` object with comprehensive information about the navigation attempt:\n\n```typescript\nimport { NavigationErrorType } from '@doeixd/combi-router';\n\nconst result = await router.navigate(userRoute, { id: 123 });\n\nif (result.success) {\n  console.log('Navigation completed successfully');\n  console.log('Active match:', result.match);\n} else {\n  // Handle different types of navigation errors\n  switch (result.error?.type) {\n    case NavigationErrorType.RouteNotFound:\n      console.error('Route not found');\n      break;\n    case NavigationErrorType.GuardRejected:\n      console.error('Navigation blocked by guard:', result.error.message);\n      break;\n    case NavigationErrorType.LoaderFailed:\n      console.error('Data loading failed:', result.error.originalError);\n      break;\n    case NavigationErrorType.ValidationFailed:\n      console.error('Parameter validation failed');\n      break;\n    case NavigationErrorType.Cancelled:\n      console.log('Navigation was cancelled');\n      break;\n  }\n}\n```\n\n#### Navigation Cancellation with NavigationController\n\nLong-running navigations can now be cancelled, which is especially useful for preventing race conditions:\n\n```typescript\n// Start a navigation and get a controller\nconst controller = router.currentNavigation;\n\nif (controller) {\n  console.log('Navigating to:', controller.route);\n  \n  // Cancel the navigation if needed\n  setTimeout(() => {\n    if (!controller.cancelled) {\n      controller.cancel();\n      console.log('Navigation cancelled');\n    }\n  }, 1000);\n  \n  // Wait for the result\n  const result = await controller.promise;\n  if (result.cancelled) {\n    console.log('Navigation was cancelled');\n  }\n}\n```\n\n#### Backward Compatibility with navigateSimple()\n\nFor simple use cases, the `navigateSimple()` method provides the traditional boolean return value:\n\n```typescript\n// Simple boolean result for straightforward cases\nconst success = await router.navigateSimple(userRoute, { id: 123 });\nif (success) {\n  console.log('Navigation successful');\n} else {\n  console.log('Navigation failed');\n}\n\n// Still get full details when needed\nconst detailedResult = await router.navigate(userRoute, { id: 123 });\n```\n\n### Typed Guards\n\n#### Enhanced Guard Context and Type Safety\n\nThe new `typedGuard()` function provides better type safety and more context for route protection:\n\n```typescript\nimport { typedGuard, GuardContext } from '@doeixd/combi-router';\nimport { z } from 'zod';\n\n// Define a route with parameters\nconst adminUserRoute = route(\n  path('admin'), \n  path('users'), \n  param('userId', z.string())\n);\n\n// Create a typed guard with full context access\nconst adminGuard = typedGuard<{ userId: string }>(({ params, to, from, searchParams }) => {\n  // Full type safety on params\n  const userId = params.userId; // TypeScript knows this is a string\n  \n  // Access to route context\n  console.log('Navigating to:', to.url);\n  console.log('Coming from:', from?.url || 'initial load');\n  console.log('Search params:', searchParams.get('redirect'));\n  \n  // Return boolean for allow/deny or string for redirect\n  if (!isCurrentUserAdmin()) {\n    return '/login?redirect=' + encodeURIComponent(to.url);\n  }\n  \n  // Additional validation based on the user ID\n  if (!canAccessUser(userId)) {\n    return false; // Block navigation\n  }\n  \n  return true; // Allow navigation\n});\n\n// Apply the guard to the route\nconst protectedRoute = pipe(\n  adminUserRoute,\n  guard(adminGuard)\n);\n```\n\n### Nested Routes and Parallel Data Loading\n\nWhen a nested route like `/dashboard/users/123` is matched, Combi-Router builds a tree of match objects. If both `dashboardRoute` and `userRoute` have a `loader`, they are executed **in parallel**, and you can access data from any level of the hierarchy.\n\n```typescript\n// dashboard-layout.ts\nconst dashboardRoute = pipe(\n  route(path('dashboard')),\n  loader(async () => ({ stats: await fetchDashboardStats() })),\n  layout(DashboardLayout) // Layout component with <Outlet />\n);\n\n// user-profile.ts\nconst userRoute = pipe(\n  extend(dashboardRoute, path('users'), param('id', z.number())),\n  loader(async ({ params }) => ({ user: await fetchUser(params.id) }))\n);\n\n// In your view for the user route, you can access both sets of data:\nconst dashboardData = router.currentMatch.data; // { stats: ... }\nconst userData = router.currentMatch.child.data; // { user: ... }\n```\n\n### Predictive Preloading\n\nImprove perceived performance by loading a route's code and data *before* the user clicks a link. The `router.peek()` method is perfect for this.\n\n```typescript\n// Preload on hover to make navigation feel instantaneous\nmyLink.addEventListener('mouseenter', () => {\n  router.peek(userRoute, { id: 123 });\n});\n\n// Navigate as usual on click\nmyLink.addEventListener('click', (e) => {\n  e.preventDefault();\n  router.navigate(userRoute, { id: 123 });\n});\n```\n\n### View Transitions\n\nCombi-Router automatically uses the browser's native [View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API) for smooth, app-like page transitions. To enable it, simply add a CSS `view-transition-name` to elements that should animate between pages.\n\n```css\n/* On a list page */\n.product-thumbnail {\n  view-transition-name: product-image-123;\n}\n\n/* On a detail page */\n.product-hero-image {\n  view-transition-name: product-image-123; /* Same name! */\n}\n```\n\nThe router handles the rest. No JavaScript changes are needed.\n\n<br />\n\n## 🧩 Vanilla JS Utilities\n\nCombi-Router is framework-agnostic at its core. To help you integrate it into a vanilla JavaScript project, we provide a set of utility functions. These helpers bridge the gap between the router's state and the DOM, making it easy to create navigable links, render nested views, and react to route changes.\n\n### Link & Navigation Helpers\n\n#### `createLink(router, route, params, options)`\n\nCreates a fully functional `<a>` element that navigates using the router. It automatically sets the `href` and intercepts click events to trigger client-side navigation. Each created link comes with a `destroy` function to clean up its event listeners.\n\n```typescript\nimport { createLink } from '@doeixd/combi-router/utils';\n\nconst { element, destroy } = createLink(\n  router,\n  userRoute,\n  { id: 123 },\n  { children: 'View Profile', className: 'btn' }\n);\ndocument.body.appendChild(element);\n\n// Later, when the element is removed from the DOM:\n// destroy();\n```\n\n#### `createActiveLink(router, route, params, options)`\n\nBuilds on `createLink` to create an `<a>` element that automatically updates its CSS class when its route is active. This is perfect for navigation menus.\n\n- `activeClassName`: The CSS class to apply when the link is active.\n- `exact`: If `true`, the class is applied only on an exact route match. If `false` (default), it's also applied for any active child routes.\n\n```typescript\nimport { createActiveLink } from '@doeixd/combi-router/utils';\n\nconst { element } = createActiveLink(router, dashboardRoute, {}, {\n  children: 'Dashboard',\n  className: 'nav-link',\n  activeClassName: 'font-bold' // Applied on /dashboard, /dashboard/users, etc.\n});\ndocument.querySelector('nav').appendChild(element);\n```\n\n#### `attachNavigator(element, router, route, params)`\n\nMakes any existing HTML element navigable. This is useful for turning buttons, divs, or other non-anchor elements into type-safe navigation triggers.\n\n```typescript\nimport { attachNavigator } from '@doeixd/combi-router/utils';\n\nconst myButton = document.getElementById('home-button');\nconst { destroy } = attachNavigator(myButton, router, homeRoute, {});\n```\n\n### Conditional Rendering\n\n#### `createOutlet(router, parentRoute, container, viewMap)`\n\nProvides a declarative \"outlet\" for nested routing, similar to `<Outlet>` in React Router or `<router-view>` in Vue. It listens for route changes and renders the correct child view into a specified container element.\n\n- `parentRoute`: The route of the component that *contains* the outlet.\n- `container`: The DOM element where child views will be rendered.\n- `viewMap`: An object mapping `Route.id` to an `ElementFactory` function `(match) => Node`.\n\n```typescript\n// In your dashboard layout component\nimport { createOutlet } from '@doeixd/combi-router/utils';\nimport { dashboardRoute, usersRoute, settingsRoute } from './routes';\nimport { UserListPage, SettingsPage } from './views';\n\nconst outletContainer = document.querySelector('#outlet');\ncreateOutlet(router, dashboardRoute, outletContainer, {\n  [usersRoute.id]: (match) => new UserListPage(match.data), // Pass data to the view\n  [settingsRoute.id]: () => new SettingsPage(),\n});\n```\n\n#### `createMatcher(router)`\n\nCreates a fluent, type-safe conditional tool that reacts to route changes. It's a powerful way to implement declarative logic that isn't tied directly to rendering.\n\n```typescript\nimport { createMatcher } from '@doeixd/combi-router/utils';\n\n// Update the document title based on the active route\ncreateMatcher(router)\n  .when(homeRoute, () => {\n    document.title = 'My App | Home';\n  })\n  .when(userRoute, (match) => {\n    document.title = `Profile for User ${match.params.id}`;\n  })\n  .otherwise(() => {\n    document.title = 'My App';\n  });\n```\n\n### State Management\n\n#### `createRouterStore(router)`\n\nCreates a minimal, framework-agnostic reactive store for the router's state (`currentMatch`, `isNavigating`, `isFetching`). This is useful for integrating with UI libraries or building your own reactive logic in vanilla JS.\n\n```typescript\nimport { createRouterStore } from '@doeixd/combi-router/utils';\n\nconst store = createRouterStore(router);\n\nconst unsubscribe = store.subscribe(() => {\n  const { isNavigating } = store.getSnapshot();\n  // Show a global loading indicator while navigating\n  document.body.style.cursor = isNavigating ? 'wait' : 'default';\n});\n\n// To clean up:\n// unsubscribe();\n```\n\n<br />\n\n## 🎨 Web Components\n\nFor even simpler integration, Combi-Router provides ready-to-use Web Components that handle routing declaratively in your HTML:\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n    <script type=\"module\">\n        // Import standalone components (no setup required!)\n        import '@doeixd/combi-router/components-standalone';\n    </script>\n</head>\n<body>\n    <!-- Define your routes declaratively -->\n    <view-area match=\"/users/:id\" view-id=\"user-detail\"></view-area>\n    <view-area match=\"/about\" view-id=\"about-page\"></view-area>\n\n    <!-- Define your templates with automatic head management -->\n    <template is=\"view-template\" view-id=\"user-detail\">\n        <!-- Head automatically discovered and linked to view-area -->\n        <view-head \n            title=\"User Profile\"\n            title-template=\"My App | %s\"\n            description=\"View user profile and details\"\n            og-title=\"User Profile\"\n            og-description=\"Comprehensive user profile page\"\n            og-type=\"profile\">\n        </view-head>\n        \n        <h1>User Details</h1>\n        <p>User ID: <span class=\"user-id\"></span></p>\n    </template>\n\n    <template is=\"view-template\" view-id=\"about-page\">\n        <!-- Each template can have its own head configuration -->\n        <view-head \n            title=\"About Us\"\n            description=\"Learn more about our company and mission\"\n            keywords=\"about, company, mission, team\"\n            canonical=\"https://myapp.com/about\"\n            og-title=\"About Our Company\"\n            og-description=\"Discover our story and values\">\n        </view-head>\n        \n        <h1>About</h1>\n        <p>This is the about page.</p>\n    </template>\n\n    <!-- Navigation works automatically -->\n    <nav>\n        <a href=\"/users/123\">User 123</a>\n        <a href=\"/about\">About</a>\n    </nav>\n</body>\n</html>\n```\n\n### Advanced Example with Nested Routes\n\n```html\n<!-- Nested route structure -->\n<view-area match=\"/dashboard\" view-id=\"dashboard\"></view-area>\n<view-area match=\"/dashboard/users\" view-id=\"users-list\"></view-area>\n<view-area match=\"/dashboard/users/:id\" view-id=\"user-detail\"></view-area>\n\n<!-- Templates with automatic head discovery -->\n<template is=\"view-template\" view-id=\"dashboard\">\n    <!-- Parent template head - automatically merges with child heads -->\n    <view-head \n        title=\"Dashboard\"\n        title-template=\"Admin | %s\"\n        description=\"Admin dashboard overview\">\n    </view-head>\n    \n    <h1>Dashboard</h1>\n    <nav>\n        <a href=\"/dashboard/users\">Users</a>\n        <a href=\"/dashboard/analytics\">Analytics</a>\n    </nav>\n    <main class=\"dashboard-content\"></main>\n</template>\n\n<template is=\"view-template\" view-id=\"users-list\">\n    <!-- Child template head - merges with parent -->\n    <view-head \n        title=\"Users\"\n        description=\"Manage users and permissions\"\n        robots=\"noindex\">\n    </view-head>\n    \n    <h2>Users</h2>\n    <div class=\"users-grid\"></div>\n</template>\n\n<!-- External template with dynamic head loading -->\n<template is=\"view-template\" view-id=\"user-detail\" src=\"/views/user-detail.html\"></template>\n\n<!-- You can still use manual linking for external head configs -->\n<view-head head-id=\"external-head\" src=\"/head-configs/user-detail.js\"></view-head>\n<view-area match=\"/special/:id\" view-id=\"special-view\" head-id=\"external-head\"></view-area>\n```\n\n### Key Benefits\n\n- **Zero JavaScript Configuration**: Just import and use\n- **Declarative Routing**: Define routes in HTML attributes\n- **Automatic Navigation**: Links work out of the box\n- **SEO-Ready**: Built-in head management with Open Graph and Twitter Cards\n- **Automatic Head Discovery**: Place `view-head` inside templates - no manual linking needed\n- **Nested Head Management**: Head tags merge hierarchically for complex layouts\n- **Dynamic Content**: Load head configurations from external modules\n- **Flexible Linking**: Choose automatic discovery or manual `head-id` linking\n- **Progressive Enhancement**: Works with or without JavaScript\n- **Dynamic Route Management**: Add/remove routes programmatically when needed\n\n[Learn more →](docs/COMPONENTS.md)\n\n<br />\n\n## ⚙️ Configuration & API\n\n## 🧰 Composable Layer Architecture\n\nCombi-Router now features a revolutionary **layer-based composition system** using our custom `makeLayered` implementation, enabling true user extensibility while maintaining backwards compatibility.\n\n### Why Layers?\n\nTraditional routers force you to choose between their built-in features or build everything from scratch. With layers, you can:\n\n- **Mix and match** built-in features exactly as needed\n- **Create custom layers** for your specific business logic  \n- **Compose layers conditionally** based on environment or feature flags\n- **Build orchestrated systems** where layers can call each other's methods\n- **Maintain type safety** with full TypeScript inference across all layers\n\n### Basic Layer Composition\n\n```typescript\nimport { \n  createLayeredRouter, \n  createCoreNavigationLayer,\n  withPerformance, \n  withScrollRestoration \n} from '@doeixd/combi-router';\n\n// Compose exactly the router you need\nconst router = createLayeredRouter(routes)\n  (createCoreNavigationLayer())           // Base navigation\n  (withPerformance({ prefetchOnHover: true }))  // Performance optimizations\n  (withScrollRestoration({ strategy: 'smooth' })) // Scroll management\n  ();\n\n// All layer methods are now available\nrouter.navigate('/user/123');\nrouter.prefetchRoute('about');\nrouter.saveScrollPosition();\n```\n\n### Custom Layer Creation\n\nCreate your own layers for analytics, authentication, or any business logic:\n\n```typescript\nconst withAnalytics = (config: { trackingId: string }) => (self: any) => {\n  // Register lifecycle hooks\n  if ('_registerLifecycleHook' in self) {\n    self._registerLifecycleHook('onNavigationStart', (context: any) => {\n      console.log(`[Analytics] Navigation started: ${context.to?.path}`);\n    });\n\n    self._registerLifecycleHook('onNavigationComplete', (match: any) => {\n      console.log(`[Analytics] Page view: ${match.path}`);\n    });\n  }\n\n  return {\n    trackEvent:","readmeFilename":"README.md"}