diff --git a/e2e/react-router/compiled-matcher/.gitignore b/e2e/react-router/compiled-matcher/.gitignore
new file mode 100644
index 0000000000..4d2da67b50
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/.gitignore
@@ -0,0 +1,11 @@
+node_modules
+.DS_Store
+dist
+dist-hash
+dist-ssr
+*.local
+
+/test-results/
+/playwright-report/
+/blob-report/
+/playwright/.cache/
diff --git a/e2e/react-router/compiled-matcher/index.html b/e2e/react-router/compiled-matcher/index.html
new file mode 100644
index 0000000000..21e30f1695
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/index.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.tsx"></script>
+  </body>
+</html>
diff --git a/e2e/react-router/compiled-matcher/package.json b/e2e/react-router/compiled-matcher/package.json
new file mode 100644
index 0000000000..766f04cb60
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/package.json
@@ -0,0 +1,36 @@
+{
+  "name": "tanstack-router-e2e-react-compiled-matcher",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "dev": "vite --port 3000",
+    "dev:e2e": "vite",
+    "build": "vite build && tsc --noEmit",
+    "build:fresh": "rm -rf .tanstack && rm ./src/routeTree.gen.ts && pnpm i && vite build",
+    "serve": "vite preview",
+    "start": "vite",
+    "test:e2e": "rm -rf port*.txt; playwright test --project=chromium"
+  },
+  "dependencies": {
+    "@tanstack/react-router": "workspace:^",
+    "@tanstack/react-router-devtools": "workspace:^",
+    "@tanstack/router-plugin": "workspace:^",
+    "@tanstack/zod-adapter": "workspace:^",
+    "react": "^19.0.0",
+    "react-dom": "^19.0.0",
+    "redaxios": "^0.5.1",
+    "postcss": "^8.5.1",
+    "autoprefixer": "^10.4.20",
+    "tailwindcss": "^3.4.17",
+    "zod": "^3.24.2"
+  },
+  "devDependencies": {
+    "@playwright/test": "^1.50.1",
+    "@tanstack/router-e2e-utils": "workspace:^",
+    "@types/react": "^19.0.8",
+    "@types/react-dom": "^19.0.3",
+    "@vitejs/plugin-react": "^4.3.4",
+    "combinate": "^1.1.11",
+    "vite": "^6.3.5"
+  }
+}
diff --git a/e2e/react-router/compiled-matcher/playwright.config.ts b/e2e/react-router/compiled-matcher/playwright.config.ts
new file mode 100644
index 0000000000..4dc2271f01
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/playwright.config.ts
@@ -0,0 +1,41 @@
+import { defineConfig, devices } from '@playwright/test'
+import {
+  getDummyServerPort,
+  getTestServerPort,
+} from '@tanstack/router-e2e-utils'
+import packageJson from './package.json' with { type: 'json' }
+
+const PORT = await getTestServerPort(packageJson.name)
+const EXTERNAL_PORT = await getDummyServerPort(packageJson.name)
+const baseURL = `http://localhost:${PORT}`
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+  testDir: './tests',
+  workers: 1,
+
+  reporter: [['line']],
+
+  globalSetup: './tests/setup/global.setup.ts',
+  globalTeardown: './tests/setup/global.teardown.ts',
+
+  use: {
+    /* Base URL to use in actions like `await page.goto('/')`. */
+    baseURL,
+  },
+
+  webServer: {
+    command: `VITE_NODE_ENV="test" VITE_SERVER_PORT=${PORT} VITE_EXTERNAL_PORT=${EXTERNAL_PORT} pnpm build && VITE_SERVER_PORT=${PORT} pnpm serve --port ${PORT}`,
+    url: baseURL,
+    reuseExistingServer: !process.env.CI,
+    stdout: 'pipe',
+  },
+
+  projects: [
+    {
+      name: 'chromium',
+      use: { ...devices['Desktop Chrome'] },
+    },
+  ],
+})
diff --git a/e2e/react-router/compiled-matcher/postcss.config.mjs b/e2e/react-router/compiled-matcher/postcss.config.mjs
new file mode 100644
index 0000000000..2e7af2b7f1
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/postcss.config.mjs
@@ -0,0 +1,6 @@
+export default {
+  plugins: {
+    tailwindcss: {},
+    autoprefixer: {},
+  },
+}
diff --git a/e2e/react-router/compiled-matcher/src/main.tsx b/e2e/react-router/compiled-matcher/src/main.tsx
new file mode 100644
index 0000000000..3dc73ddd51
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/main.tsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import { RouterProvider, createRouter } from '@tanstack/react-router'
+import { routeTree } from './routeTree.gen'
+import './styles.css'
+
+// Set up a Router instance
+const router = createRouter({
+  routeTree,
+  defaultPreload: 'intent',
+  defaultStaleTime: 5000,
+  scrollRestoration: true,
+})
+
+// Register things for typesafety
+declare module '@tanstack/react-router' {
+  interface Register {
+    router: typeof router
+  }
+}
+
+const rootElement = document.getElementById('app')!
+
+if (!rootElement.innerHTML) {
+  const root = ReactDOM.createRoot(rootElement)
+  root.render(<RouterProvider router={router} />)
+}
diff --git a/e2e/react-router/compiled-matcher/src/routeTree.gen.ts b/e2e/react-router/compiled-matcher/src/routeTree.gen.ts
new file mode 100644
index 0000000000..4dd627fae3
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routeTree.gen.ts
@@ -0,0 +1,899 @@
+/* eslint-disable */
+
+// @ts-nocheck
+
+// noinspection JSUnusedGlobalSymbols
+
+// This file was automatically generated by TanStack Router.
+// You should NOT make any changes in this file as it will be overwritten.
+// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
+
+import { Route as rootRouteImport } from './routes/__root'
+import { Route as OneRouteImport } from './routes/one'
+import { Route as AboutRouteImport } from './routes/about'
+import { Route as IndexRouteImport } from './routes/index'
+import { Route as BIndexRouteImport } from './routes/b/index'
+import { Route as AIndexRouteImport } from './routes/a/index'
+import { Route as UsersIdRouteImport } from './routes/users/$id'
+import { Route as PostsChar123SlugChar125RouteImport } from './routes/posts/{-$slug}'
+import { Route as OneTwoRouteImport } from './routes/one/two'
+import { Route as ImagesThumb_Char123Char125RouteImport } from './routes/images/thumb_{$}'
+import { Route as FooBarRouteImport } from './routes/foo/$bar'
+import { Route as FilesSplatRouteImport } from './routes/files/$'
+import { Route as BeepBoopRouteImport } from './routes/beep/boop'
+import { Route as BChar123SlugChar125RouteImport } from './routes/b/{-$slug}'
+import { Route as BUserChar123idChar125RouteImport } from './routes/b/user-{$id}'
+import { Route as BIdRouteImport } from './routes/b/$id'
+import { Route as BSplatRouteImport } from './routes/b/$'
+import { Route as ApiUserChar123idChar125RouteImport } from './routes/api/user-{$id}'
+import { Route as AChar123SlugChar125RouteImport } from './routes/a/{-$slug}'
+import { Route as AUserChar123idChar125RouteImport } from './routes/a/user-{$id}'
+import { Route as AIdRouteImport } from './routes/a/$id'
+import { Route as ASplatRouteImport } from './routes/a/$'
+import { Route as UsersProfileIndexRouteImport } from './routes/users/profile/index'
+import { Route as FooBarIndexRouteImport } from './routes/foo/$bar.index'
+import { Route as BProfileIndexRouteImport } from './routes/b/profile/index'
+import { Route as AProfileIndexRouteImport } from './routes/a/profile/index'
+import { Route as UsersProfileSettingsRouteImport } from './routes/users/profile/settings'
+import { Route as LogsChar123Char125TxtRouteImport } from './routes/logs/{$}.txt'
+import { Route as FooChar123BarChar125QuxRouteImport } from './routes/foo/{-$bar}/qux'
+import { Route as FooBarIdRouteImport } from './routes/foo/bar/$id'
+import { Route as FooIdBarRouteImport } from './routes/foo/$id/bar'
+import { Route as CacheTemp_Char123Char125LogRouteImport } from './routes/cache/temp_{$}.log'
+import { Route as BProfileSettingsRouteImport } from './routes/b/profile/settings'
+import { Route as AProfileSettingsRouteImport } from './routes/a/profile/settings'
+import { Route as IdFooBarRouteImport } from './routes/$id/foo/bar'
+import { Route as IdBarFooRouteImport } from './routes/$id/bar/foo'
+import { Route as ZYXIndexRouteImport } from './routes/z/y/x/index'
+import { Route as ZYXWRouteImport } from './routes/z/y/x/w'
+import { Route as ZYXVRouteImport } from './routes/z/y/x/v'
+import { Route as ZYXURouteImport } from './routes/z/y/x/u'
+import { Route as ABCDEFRouteImport } from './routes/a/b/c/d/e/f'
+
+const OneRoute = OneRouteImport.update({
+  id: '/one',
+  path: '/one',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const AboutRoute = AboutRouteImport.update({
+  id: '/about',
+  path: '/about',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const IndexRoute = IndexRouteImport.update({
+  id: '/',
+  path: '/',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const BIndexRoute = BIndexRouteImport.update({
+  id: '/b/',
+  path: '/b/',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const AIndexRoute = AIndexRouteImport.update({
+  id: '/a/',
+  path: '/a/',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const UsersIdRoute = UsersIdRouteImport.update({
+  id: '/users/$id',
+  path: '/users/$id',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const PostsChar123SlugChar125Route = PostsChar123SlugChar125RouteImport.update({
+  id: '/posts/{-$slug}',
+  path: '/posts/{-$slug}',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const OneTwoRoute = OneTwoRouteImport.update({
+  id: '/two',
+  path: '/two',
+  getParentRoute: () => OneRoute,
+} as any)
+const ImagesThumb_Char123Char125Route =
+  ImagesThumb_Char123Char125RouteImport.update({
+    id: '/images/thumb_{$}',
+    path: '/images/thumb_{$}',
+    getParentRoute: () => rootRouteImport,
+  } as any)
+const FooBarRoute = FooBarRouteImport.update({
+  id: '/foo/$bar',
+  path: '/foo/$bar',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const FilesSplatRoute = FilesSplatRouteImport.update({
+  id: '/files/$',
+  path: '/files/$',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const BeepBoopRoute = BeepBoopRouteImport.update({
+  id: '/beep/boop',
+  path: '/beep/boop',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const BChar123SlugChar125Route = BChar123SlugChar125RouteImport.update({
+  id: '/b/{-$slug}',
+  path: '/b/{-$slug}',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const BUserChar123idChar125Route = BUserChar123idChar125RouteImport.update({
+  id: '/b/user-{$id}',
+  path: '/b/user-{$id}',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const BIdRoute = BIdRouteImport.update({
+  id: '/b/$id',
+  path: '/b/$id',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const BSplatRoute = BSplatRouteImport.update({
+  id: '/b/$',
+  path: '/b/$',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const ApiUserChar123idChar125Route = ApiUserChar123idChar125RouteImport.update({
+  id: '/api/user-{$id}',
+  path: '/api/user-{$id}',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const AChar123SlugChar125Route = AChar123SlugChar125RouteImport.update({
+  id: '/a/{-$slug}',
+  path: '/a/{-$slug}',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const AUserChar123idChar125Route = AUserChar123idChar125RouteImport.update({
+  id: '/a/user-{$id}',
+  path: '/a/user-{$id}',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const AIdRoute = AIdRouteImport.update({
+  id: '/a/$id',
+  path: '/a/$id',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const ASplatRoute = ASplatRouteImport.update({
+  id: '/a/$',
+  path: '/a/$',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const UsersProfileIndexRoute = UsersProfileIndexRouteImport.update({
+  id: '/users/profile/',
+  path: '/users/profile/',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const FooBarIndexRoute = FooBarIndexRouteImport.update({
+  id: '/',
+  path: '/',
+  getParentRoute: () => FooBarRoute,
+} as any)
+const BProfileIndexRoute = BProfileIndexRouteImport.update({
+  id: '/b/profile/',
+  path: '/b/profile/',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const AProfileIndexRoute = AProfileIndexRouteImport.update({
+  id: '/a/profile/',
+  path: '/a/profile/',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const UsersProfileSettingsRoute = UsersProfileSettingsRouteImport.update({
+  id: '/users/profile/settings',
+  path: '/users/profile/settings',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const LogsChar123Char125TxtRoute = LogsChar123Char125TxtRouteImport.update({
+  id: '/logs/{$}/txt',
+  path: '/logs/{$}/txt',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const FooChar123BarChar125QuxRoute = FooChar123BarChar125QuxRouteImport.update({
+  id: '/foo/{-$bar}/qux',
+  path: '/foo/{-$bar}/qux',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const FooBarIdRoute = FooBarIdRouteImport.update({
+  id: '/foo/bar/$id',
+  path: '/foo/bar/$id',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const FooIdBarRoute = FooIdBarRouteImport.update({
+  id: '/foo/$id/bar',
+  path: '/foo/$id/bar',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const CacheTemp_Char123Char125LogRoute =
+  CacheTemp_Char123Char125LogRouteImport.update({
+    id: '/cache/temp_{$}/log',
+    path: '/cache/temp_{$}/log',
+    getParentRoute: () => rootRouteImport,
+  } as any)
+const BProfileSettingsRoute = BProfileSettingsRouteImport.update({
+  id: '/b/profile/settings',
+  path: '/b/profile/settings',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const AProfileSettingsRoute = AProfileSettingsRouteImport.update({
+  id: '/a/profile/settings',
+  path: '/a/profile/settings',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const IdFooBarRoute = IdFooBarRouteImport.update({
+  id: '/$id/foo/bar',
+  path: '/$id/foo/bar',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const IdBarFooRoute = IdBarFooRouteImport.update({
+  id: '/$id/bar/foo',
+  path: '/$id/bar/foo',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const ZYXIndexRoute = ZYXIndexRouteImport.update({
+  id: '/z/y/x/',
+  path: '/z/y/x/',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const ZYXWRoute = ZYXWRouteImport.update({
+  id: '/z/y/x/w',
+  path: '/z/y/x/w',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const ZYXVRoute = ZYXVRouteImport.update({
+  id: '/z/y/x/v',
+  path: '/z/y/x/v',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const ZYXURoute = ZYXURouteImport.update({
+  id: '/z/y/x/u',
+  path: '/z/y/x/u',
+  getParentRoute: () => rootRouteImport,
+} as any)
+const ABCDEFRoute = ABCDEFRouteImport.update({
+  id: '/a/b/c/d/e/f',
+  path: '/a/b/c/d/e/f',
+  getParentRoute: () => rootRouteImport,
+} as any)
+
+export interface FileRoutesByFullPath {
+  '/': typeof IndexRoute
+  '/about': typeof AboutRoute
+  '/one': typeof OneRouteWithChildren
+  '/a/$': typeof ASplatRoute
+  '/a/$id': typeof AIdRoute
+  '/a/user-{$id}': typeof AUserChar123idChar125Route
+  '/a/{-$slug}': typeof AChar123SlugChar125Route
+  '/api/user-{$id}': typeof ApiUserChar123idChar125Route
+  '/b/$': typeof BSplatRoute
+  '/b/$id': typeof BIdRoute
+  '/b/user-{$id}': typeof BUserChar123idChar125Route
+  '/b/{-$slug}': typeof BChar123SlugChar125Route
+  '/beep/boop': typeof BeepBoopRoute
+  '/files/$': typeof FilesSplatRoute
+  '/foo/$bar': typeof FooBarRouteWithChildren
+  '/images/thumb_{$}': typeof ImagesThumb_Char123Char125Route
+  '/one/two': typeof OneTwoRoute
+  '/posts/{-$slug}': typeof PostsChar123SlugChar125Route
+  '/users/$id': typeof UsersIdRoute
+  '/a': typeof AIndexRoute
+  '/b': typeof BIndexRoute
+  '/$id/bar/foo': typeof IdBarFooRoute
+  '/$id/foo/bar': typeof IdFooBarRoute
+  '/a/profile/settings': typeof AProfileSettingsRoute
+  '/b/profile/settings': typeof BProfileSettingsRoute
+  '/cache/temp_{$}/log': typeof CacheTemp_Char123Char125LogRoute
+  '/foo/$id/bar': typeof FooIdBarRoute
+  '/foo/bar/$id': typeof FooBarIdRoute
+  '/foo/{-$bar}/qux': typeof FooChar123BarChar125QuxRoute
+  '/logs/{$}/txt': typeof LogsChar123Char125TxtRoute
+  '/users/profile/settings': typeof UsersProfileSettingsRoute
+  '/a/profile': typeof AProfileIndexRoute
+  '/b/profile': typeof BProfileIndexRoute
+  '/foo/$bar/': typeof FooBarIndexRoute
+  '/users/profile': typeof UsersProfileIndexRoute
+  '/z/y/x/u': typeof ZYXURoute
+  '/z/y/x/v': typeof ZYXVRoute
+  '/z/y/x/w': typeof ZYXWRoute
+  '/z/y/x': typeof ZYXIndexRoute
+  '/a/b/c/d/e/f': typeof ABCDEFRoute
+}
+export interface FileRoutesByTo {
+  '/': typeof IndexRoute
+  '/about': typeof AboutRoute
+  '/one': typeof OneRouteWithChildren
+  '/a/$': typeof ASplatRoute
+  '/a/$id': typeof AIdRoute
+  '/a/user-{$id}': typeof AUserChar123idChar125Route
+  '/a/{-$slug}': typeof AChar123SlugChar125Route
+  '/api/user-{$id}': typeof ApiUserChar123idChar125Route
+  '/b/$': typeof BSplatRoute
+  '/b/$id': typeof BIdRoute
+  '/b/user-{$id}': typeof BUserChar123idChar125Route
+  '/b/{-$slug}': typeof BChar123SlugChar125Route
+  '/beep/boop': typeof BeepBoopRoute
+  '/files/$': typeof FilesSplatRoute
+  '/images/thumb_{$}': typeof ImagesThumb_Char123Char125Route
+  '/one/two': typeof OneTwoRoute
+  '/posts/{-$slug}': typeof PostsChar123SlugChar125Route
+  '/users/$id': typeof UsersIdRoute
+  '/a': typeof AIndexRoute
+  '/b': typeof BIndexRoute
+  '/$id/bar/foo': typeof IdBarFooRoute
+  '/$id/foo/bar': typeof IdFooBarRoute
+  '/a/profile/settings': typeof AProfileSettingsRoute
+  '/b/profile/settings': typeof BProfileSettingsRoute
+  '/cache/temp_{$}/log': typeof CacheTemp_Char123Char125LogRoute
+  '/foo/$id/bar': typeof FooIdBarRoute
+  '/foo/bar/$id': typeof FooBarIdRoute
+  '/foo/{-$bar}/qux': typeof FooChar123BarChar125QuxRoute
+  '/logs/{$}/txt': typeof LogsChar123Char125TxtRoute
+  '/users/profile/settings': typeof UsersProfileSettingsRoute
+  '/a/profile': typeof AProfileIndexRoute
+  '/b/profile': typeof BProfileIndexRoute
+  '/foo/$bar': typeof FooBarIndexRoute
+  '/users/profile': typeof UsersProfileIndexRoute
+  '/z/y/x/u': typeof ZYXURoute
+  '/z/y/x/v': typeof ZYXVRoute
+  '/z/y/x/w': typeof ZYXWRoute
+  '/z/y/x': typeof ZYXIndexRoute
+  '/a/b/c/d/e/f': typeof ABCDEFRoute
+}
+export interface FileRoutesById {
+  __root__: typeof rootRouteImport
+  '/': typeof IndexRoute
+  '/about': typeof AboutRoute
+  '/one': typeof OneRouteWithChildren
+  '/a/$': typeof ASplatRoute
+  '/a/$id': typeof AIdRoute
+  '/a/user-{$id}': typeof AUserChar123idChar125Route
+  '/a/{-$slug}': typeof AChar123SlugChar125Route
+  '/api/user-{$id}': typeof ApiUserChar123idChar125Route
+  '/b/$': typeof BSplatRoute
+  '/b/$id': typeof BIdRoute
+  '/b/user-{$id}': typeof BUserChar123idChar125Route
+  '/b/{-$slug}': typeof BChar123SlugChar125Route
+  '/beep/boop': typeof BeepBoopRoute
+  '/files/$': typeof FilesSplatRoute
+  '/foo/$bar': typeof FooBarRouteWithChildren
+  '/images/thumb_{$}': typeof ImagesThumb_Char123Char125Route
+  '/one/two': typeof OneTwoRoute
+  '/posts/{-$slug}': typeof PostsChar123SlugChar125Route
+  '/users/$id': typeof UsersIdRoute
+  '/a/': typeof AIndexRoute
+  '/b/': typeof BIndexRoute
+  '/$id/bar/foo': typeof IdBarFooRoute
+  '/$id/foo/bar': typeof IdFooBarRoute
+  '/a/profile/settings': typeof AProfileSettingsRoute
+  '/b/profile/settings': typeof BProfileSettingsRoute
+  '/cache/temp_{$}/log': typeof CacheTemp_Char123Char125LogRoute
+  '/foo/$id/bar': typeof FooIdBarRoute
+  '/foo/bar/$id': typeof FooBarIdRoute
+  '/foo/{-$bar}/qux': typeof FooChar123BarChar125QuxRoute
+  '/logs/{$}/txt': typeof LogsChar123Char125TxtRoute
+  '/users/profile/settings': typeof UsersProfileSettingsRoute
+  '/a/profile/': typeof AProfileIndexRoute
+  '/b/profile/': typeof BProfileIndexRoute
+  '/foo/$bar/': typeof FooBarIndexRoute
+  '/users/profile/': typeof UsersProfileIndexRoute
+  '/z/y/x/u': typeof ZYXURoute
+  '/z/y/x/v': typeof ZYXVRoute
+  '/z/y/x/w': typeof ZYXWRoute
+  '/z/y/x/': typeof ZYXIndexRoute
+  '/a/b/c/d/e/f': typeof ABCDEFRoute
+}
+export interface FileRouteTypes {
+  fileRoutesByFullPath: FileRoutesByFullPath
+  fullPaths:
+    | '/'
+    | '/about'
+    | '/one'
+    | '/a/$'
+    | '/a/$id'
+    | '/a/user-{$id}'
+    | '/a/{-$slug}'
+    | '/api/user-{$id}'
+    | '/b/$'
+    | '/b/$id'
+    | '/b/user-{$id}'
+    | '/b/{-$slug}'
+    | '/beep/boop'
+    | '/files/$'
+    | '/foo/$bar'
+    | '/images/thumb_{$}'
+    | '/one/two'
+    | '/posts/{-$slug}'
+    | '/users/$id'
+    | '/a'
+    | '/b'
+    | '/$id/bar/foo'
+    | '/$id/foo/bar'
+    | '/a/profile/settings'
+    | '/b/profile/settings'
+    | '/cache/temp_{$}/log'
+    | '/foo/$id/bar'
+    | '/foo/bar/$id'
+    | '/foo/{-$bar}/qux'
+    | '/logs/{$}/txt'
+    | '/users/profile/settings'
+    | '/a/profile'
+    | '/b/profile'
+    | '/foo/$bar/'
+    | '/users/profile'
+    | '/z/y/x/u'
+    | '/z/y/x/v'
+    | '/z/y/x/w'
+    | '/z/y/x'
+    | '/a/b/c/d/e/f'
+  fileRoutesByTo: FileRoutesByTo
+  to:
+    | '/'
+    | '/about'
+    | '/one'
+    | '/a/$'
+    | '/a/$id'
+    | '/a/user-{$id}'
+    | '/a/{-$slug}'
+    | '/api/user-{$id}'
+    | '/b/$'
+    | '/b/$id'
+    | '/b/user-{$id}'
+    | '/b/{-$slug}'
+    | '/beep/boop'
+    | '/files/$'
+    | '/images/thumb_{$}'
+    | '/one/two'
+    | '/posts/{-$slug}'
+    | '/users/$id'
+    | '/a'
+    | '/b'
+    | '/$id/bar/foo'
+    | '/$id/foo/bar'
+    | '/a/profile/settings'
+    | '/b/profile/settings'
+    | '/cache/temp_{$}/log'
+    | '/foo/$id/bar'
+    | '/foo/bar/$id'
+    | '/foo/{-$bar}/qux'
+    | '/logs/{$}/txt'
+    | '/users/profile/settings'
+    | '/a/profile'
+    | '/b/profile'
+    | '/foo/$bar'
+    | '/users/profile'
+    | '/z/y/x/u'
+    | '/z/y/x/v'
+    | '/z/y/x/w'
+    | '/z/y/x'
+    | '/a/b/c/d/e/f'
+  id:
+    | '__root__'
+    | '/'
+    | '/about'
+    | '/one'
+    | '/a/$'
+    | '/a/$id'
+    | '/a/user-{$id}'
+    | '/a/{-$slug}'
+    | '/api/user-{$id}'
+    | '/b/$'
+    | '/b/$id'
+    | '/b/user-{$id}'
+    | '/b/{-$slug}'
+    | '/beep/boop'
+    | '/files/$'
+    | '/foo/$bar'
+    | '/images/thumb_{$}'
+    | '/one/two'
+    | '/posts/{-$slug}'
+    | '/users/$id'
+    | '/a/'
+    | '/b/'
+    | '/$id/bar/foo'
+    | '/$id/foo/bar'
+    | '/a/profile/settings'
+    | '/b/profile/settings'
+    | '/cache/temp_{$}/log'
+    | '/foo/$id/bar'
+    | '/foo/bar/$id'
+    | '/foo/{-$bar}/qux'
+    | '/logs/{$}/txt'
+    | '/users/profile/settings'
+    | '/a/profile/'
+    | '/b/profile/'
+    | '/foo/$bar/'
+    | '/users/profile/'
+    | '/z/y/x/u'
+    | '/z/y/x/v'
+    | '/z/y/x/w'
+    | '/z/y/x/'
+    | '/a/b/c/d/e/f'
+  fileRoutesById: FileRoutesById
+}
+export interface RootRouteChildren {
+  IndexRoute: typeof IndexRoute
+  AboutRoute: typeof AboutRoute
+  OneRoute: typeof OneRouteWithChildren
+  ASplatRoute: typeof ASplatRoute
+  AIdRoute: typeof AIdRoute
+  AUserChar123idChar125Route: typeof AUserChar123idChar125Route
+  AChar123SlugChar125Route: typeof AChar123SlugChar125Route
+  ApiUserChar123idChar125Route: typeof ApiUserChar123idChar125Route
+  BSplatRoute: typeof BSplatRoute
+  BIdRoute: typeof BIdRoute
+  BUserChar123idChar125Route: typeof BUserChar123idChar125Route
+  BChar123SlugChar125Route: typeof BChar123SlugChar125Route
+  BeepBoopRoute: typeof BeepBoopRoute
+  FilesSplatRoute: typeof FilesSplatRoute
+  FooBarRoute: typeof FooBarRouteWithChildren
+  ImagesThumb_Char123Char125Route: typeof ImagesThumb_Char123Char125Route
+  PostsChar123SlugChar125Route: typeof PostsChar123SlugChar125Route
+  UsersIdRoute: typeof UsersIdRoute
+  AIndexRoute: typeof AIndexRoute
+  BIndexRoute: typeof BIndexRoute
+  IdBarFooRoute: typeof IdBarFooRoute
+  IdFooBarRoute: typeof IdFooBarRoute
+  AProfileSettingsRoute: typeof AProfileSettingsRoute
+  BProfileSettingsRoute: typeof BProfileSettingsRoute
+  CacheTemp_Char123Char125LogRoute: typeof CacheTemp_Char123Char125LogRoute
+  FooIdBarRoute: typeof FooIdBarRoute
+  FooBarIdRoute: typeof FooBarIdRoute
+  FooChar123BarChar125QuxRoute: typeof FooChar123BarChar125QuxRoute
+  LogsChar123Char125TxtRoute: typeof LogsChar123Char125TxtRoute
+  UsersProfileSettingsRoute: typeof UsersProfileSettingsRoute
+  AProfileIndexRoute: typeof AProfileIndexRoute
+  BProfileIndexRoute: typeof BProfileIndexRoute
+  UsersProfileIndexRoute: typeof UsersProfileIndexRoute
+  ZYXURoute: typeof ZYXURoute
+  ZYXVRoute: typeof ZYXVRoute
+  ZYXWRoute: typeof ZYXWRoute
+  ZYXIndexRoute: typeof ZYXIndexRoute
+  ABCDEFRoute: typeof ABCDEFRoute
+}
+
+declare module '@tanstack/react-router' {
+  interface FileRoutesByPath {
+    '/one': {
+      id: '/one'
+      path: '/one'
+      fullPath: '/one'
+      preLoaderRoute: typeof OneRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/about': {
+      id: '/about'
+      path: '/about'
+      fullPath: '/about'
+      preLoaderRoute: typeof AboutRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/': {
+      id: '/'
+      path: '/'
+      fullPath: '/'
+      preLoaderRoute: typeof IndexRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/b/': {
+      id: '/b/'
+      path: '/b'
+      fullPath: '/b'
+      preLoaderRoute: typeof BIndexRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/': {
+      id: '/a/'
+      path: '/a'
+      fullPath: '/a'
+      preLoaderRoute: typeof AIndexRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/users/$id': {
+      id: '/users/$id'
+      path: '/users/$id'
+      fullPath: '/users/$id'
+      preLoaderRoute: typeof UsersIdRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/posts/{-$slug}': {
+      id: '/posts/{-$slug}'
+      path: '/posts/{-$slug}'
+      fullPath: '/posts/{-$slug}'
+      preLoaderRoute: typeof PostsChar123SlugChar125RouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/one/two': {
+      id: '/one/two'
+      path: '/two'
+      fullPath: '/one/two'
+      preLoaderRoute: typeof OneTwoRouteImport
+      parentRoute: typeof OneRoute
+    }
+    '/images/thumb_{$}': {
+      id: '/images/thumb_{$}'
+      path: '/images/thumb_{$}'
+      fullPath: '/images/thumb_{$}'
+      preLoaderRoute: typeof ImagesThumb_Char123Char125RouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/foo/$bar': {
+      id: '/foo/$bar'
+      path: '/foo/$bar'
+      fullPath: '/foo/$bar'
+      preLoaderRoute: typeof FooBarRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/files/$': {
+      id: '/files/$'
+      path: '/files/$'
+      fullPath: '/files/$'
+      preLoaderRoute: typeof FilesSplatRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/beep/boop': {
+      id: '/beep/boop'
+      path: '/beep/boop'
+      fullPath: '/beep/boop'
+      preLoaderRoute: typeof BeepBoopRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/b/{-$slug}': {
+      id: '/b/{-$slug}'
+      path: '/b/{-$slug}'
+      fullPath: '/b/{-$slug}'
+      preLoaderRoute: typeof BChar123SlugChar125RouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/b/user-{$id}': {
+      id: '/b/user-{$id}'
+      path: '/b/user-{$id}'
+      fullPath: '/b/user-{$id}'
+      preLoaderRoute: typeof BUserChar123idChar125RouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/b/$id': {
+      id: '/b/$id'
+      path: '/b/$id'
+      fullPath: '/b/$id'
+      preLoaderRoute: typeof BIdRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/b/$': {
+      id: '/b/$'
+      path: '/b/$'
+      fullPath: '/b/$'
+      preLoaderRoute: typeof BSplatRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/api/user-{$id}': {
+      id: '/api/user-{$id}'
+      path: '/api/user-{$id}'
+      fullPath: '/api/user-{$id}'
+      preLoaderRoute: typeof ApiUserChar123idChar125RouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/{-$slug}': {
+      id: '/a/{-$slug}'
+      path: '/a/{-$slug}'
+      fullPath: '/a/{-$slug}'
+      preLoaderRoute: typeof AChar123SlugChar125RouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/user-{$id}': {
+      id: '/a/user-{$id}'
+      path: '/a/user-{$id}'
+      fullPath: '/a/user-{$id}'
+      preLoaderRoute: typeof AUserChar123idChar125RouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/$id': {
+      id: '/a/$id'
+      path: '/a/$id'
+      fullPath: '/a/$id'
+      preLoaderRoute: typeof AIdRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/$': {
+      id: '/a/$'
+      path: '/a/$'
+      fullPath: '/a/$'
+      preLoaderRoute: typeof ASplatRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/users/profile/': {
+      id: '/users/profile/'
+      path: '/users/profile'
+      fullPath: '/users/profile'
+      preLoaderRoute: typeof UsersProfileIndexRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/foo/$bar/': {
+      id: '/foo/$bar/'
+      path: '/'
+      fullPath: '/foo/$bar/'
+      preLoaderRoute: typeof FooBarIndexRouteImport
+      parentRoute: typeof FooBarRoute
+    }
+    '/b/profile/': {
+      id: '/b/profile/'
+      path: '/b/profile'
+      fullPath: '/b/profile'
+      preLoaderRoute: typeof BProfileIndexRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/profile/': {
+      id: '/a/profile/'
+      path: '/a/profile'
+      fullPath: '/a/profile'
+      preLoaderRoute: typeof AProfileIndexRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/users/profile/settings': {
+      id: '/users/profile/settings'
+      path: '/users/profile/settings'
+      fullPath: '/users/profile/settings'
+      preLoaderRoute: typeof UsersProfileSettingsRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/logs/{$}/txt': {
+      id: '/logs/{$}/txt'
+      path: '/logs/{$}/txt'
+      fullPath: '/logs/{$}/txt'
+      preLoaderRoute: typeof LogsChar123Char125TxtRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/foo/{-$bar}/qux': {
+      id: '/foo/{-$bar}/qux'
+      path: '/foo/{-$bar}/qux'
+      fullPath: '/foo/{-$bar}/qux'
+      preLoaderRoute: typeof FooChar123BarChar125QuxRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/foo/bar/$id': {
+      id: '/foo/bar/$id'
+      path: '/foo/bar/$id'
+      fullPath: '/foo/bar/$id'
+      preLoaderRoute: typeof FooBarIdRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/foo/$id/bar': {
+      id: '/foo/$id/bar'
+      path: '/foo/$id/bar'
+      fullPath: '/foo/$id/bar'
+      preLoaderRoute: typeof FooIdBarRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/cache/temp_{$}/log': {
+      id: '/cache/temp_{$}/log'
+      path: '/cache/temp_{$}/log'
+      fullPath: '/cache/temp_{$}/log'
+      preLoaderRoute: typeof CacheTemp_Char123Char125LogRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/b/profile/settings': {
+      id: '/b/profile/settings'
+      path: '/b/profile/settings'
+      fullPath: '/b/profile/settings'
+      preLoaderRoute: typeof BProfileSettingsRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/profile/settings': {
+      id: '/a/profile/settings'
+      path: '/a/profile/settings'
+      fullPath: '/a/profile/settings'
+      preLoaderRoute: typeof AProfileSettingsRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/$id/foo/bar': {
+      id: '/$id/foo/bar'
+      path: '/$id/foo/bar'
+      fullPath: '/$id/foo/bar'
+      preLoaderRoute: typeof IdFooBarRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/$id/bar/foo': {
+      id: '/$id/bar/foo'
+      path: '/$id/bar/foo'
+      fullPath: '/$id/bar/foo'
+      preLoaderRoute: typeof IdBarFooRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/z/y/x/': {
+      id: '/z/y/x/'
+      path: '/z/y/x'
+      fullPath: '/z/y/x'
+      preLoaderRoute: typeof ZYXIndexRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/z/y/x/w': {
+      id: '/z/y/x/w'
+      path: '/z/y/x/w'
+      fullPath: '/z/y/x/w'
+      preLoaderRoute: typeof ZYXWRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/z/y/x/v': {
+      id: '/z/y/x/v'
+      path: '/z/y/x/v'
+      fullPath: '/z/y/x/v'
+      preLoaderRoute: typeof ZYXVRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/z/y/x/u': {
+      id: '/z/y/x/u'
+      path: '/z/y/x/u'
+      fullPath: '/z/y/x/u'
+      preLoaderRoute: typeof ZYXURouteImport
+      parentRoute: typeof rootRouteImport
+    }
+    '/a/b/c/d/e/f': {
+      id: '/a/b/c/d/e/f'
+      path: '/a/b/c/d/e/f'
+      fullPath: '/a/b/c/d/e/f'
+      preLoaderRoute: typeof ABCDEFRouteImport
+      parentRoute: typeof rootRouteImport
+    }
+  }
+}
+
+interface OneRouteChildren {
+  OneTwoRoute: typeof OneTwoRoute
+}
+
+const OneRouteChildren: OneRouteChildren = {
+  OneTwoRoute: OneTwoRoute,
+}
+
+const OneRouteWithChildren = OneRoute._addFileChildren(OneRouteChildren)
+
+interface FooBarRouteChildren {
+  FooBarIndexRoute: typeof FooBarIndexRoute
+}
+
+const FooBarRouteChildren: FooBarRouteChildren = {
+  FooBarIndexRoute: FooBarIndexRoute,
+}
+
+const FooBarRouteWithChildren =
+  FooBarRoute._addFileChildren(FooBarRouteChildren)
+
+const rootRouteChildren: RootRouteChildren = {
+  IndexRoute: IndexRoute,
+  AboutRoute: AboutRoute,
+  OneRoute: OneRouteWithChildren,
+  ASplatRoute: ASplatRoute,
+  AIdRoute: AIdRoute,
+  AUserChar123idChar125Route: AUserChar123idChar125Route,
+  AChar123SlugChar125Route: AChar123SlugChar125Route,
+  ApiUserChar123idChar125Route: ApiUserChar123idChar125Route,
+  BSplatRoute: BSplatRoute,
+  BIdRoute: BIdRoute,
+  BUserChar123idChar125Route: BUserChar123idChar125Route,
+  BChar123SlugChar125Route: BChar123SlugChar125Route,
+  BeepBoopRoute: BeepBoopRoute,
+  FilesSplatRoute: FilesSplatRoute,
+  FooBarRoute: FooBarRouteWithChildren,
+  ImagesThumb_Char123Char125Route: ImagesThumb_Char123Char125Route,
+  PostsChar123SlugChar125Route: PostsChar123SlugChar125Route,
+  UsersIdRoute: UsersIdRoute,
+  AIndexRoute: AIndexRoute,
+  BIndexRoute: BIndexRoute,
+  IdBarFooRoute: IdBarFooRoute,
+  IdFooBarRoute: IdFooBarRoute,
+  AProfileSettingsRoute: AProfileSettingsRoute,
+  BProfileSettingsRoute: BProfileSettingsRoute,
+  CacheTemp_Char123Char125LogRoute: CacheTemp_Char123Char125LogRoute,
+  FooIdBarRoute: FooIdBarRoute,
+  FooBarIdRoute: FooBarIdRoute,
+  FooChar123BarChar125QuxRoute: FooChar123BarChar125QuxRoute,
+  LogsChar123Char125TxtRoute: LogsChar123Char125TxtRoute,
+  UsersProfileSettingsRoute: UsersProfileSettingsRoute,
+  AProfileIndexRoute: AProfileIndexRoute,
+  BProfileIndexRoute: BProfileIndexRoute,
+  UsersProfileIndexRoute: UsersProfileIndexRoute,
+  ZYXURoute: ZYXURoute,
+  ZYXVRoute: ZYXVRoute,
+  ZYXWRoute: ZYXWRoute,
+  ZYXIndexRoute: ZYXIndexRoute,
+  ABCDEFRoute: ABCDEFRoute,
+}
+export const routeTree = rootRouteImport
+  ._addFileChildren(rootRouteChildren)
+  ._addFileTypes<FileRouteTypes>()
diff --git a/e2e/react-router/compiled-matcher/src/routes/$id/bar/foo.tsx b/e2e/react-router/compiled-matcher/src/routes/$id/bar/foo.tsx
new file mode 100644
index 0000000000..d297530468
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/$id/bar/foo.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/$id/bar/foo')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/$id/bar/foo"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/$id/foo/bar.tsx b/e2e/react-router/compiled-matcher/src/routes/$id/foo/bar.tsx
new file mode 100644
index 0000000000..47af8bdfe9
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/$id/foo/bar.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/$id/foo/bar')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/$id/foo/bar"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/__root.tsx b/e2e/react-router/compiled-matcher/src/routes/__root.tsx
new file mode 100644
index 0000000000..3b0a92c604
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/__root.tsx
@@ -0,0 +1,46 @@
+import {
+  HeadContent,
+  Link,
+  Outlet,
+  createRootRoute,
+  useRouter,
+} from '@tanstack/react-router'
+import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
+
+export const Route = createRootRoute({
+  component: RootComponent,
+  notFoundComponent: () => {
+    return (
+      <div>
+        <p>This is the notFoundComponent configured on root route</p>
+        <Link to="/">Start Over</Link>
+      </div>
+    )
+  },
+})
+
+function RootComponent() {
+  const router = useRouter()
+  return (
+    <>
+      <HeadContent />
+      <div className="flex flex-col gap-2 p-2 text-lg border-b">
+        {Object.keys(router.routesByPath).map((to) => (
+          <Link
+            to={to}
+            activeProps={{
+              className: 'font-bold',
+            }}
+            activeOptions={{ exact: true }}
+          >
+            {to}
+          </Link>
+        ))}
+      </div>
+      <hr />
+      <Outlet />
+      {/* Start rendering router matches */}
+      <TanStackRouterDevtools position="bottom-right" />
+    </>
+  )
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/$.tsx b/e2e/react-router/compiled-matcher/src/routes/a/$.tsx
new file mode 100644
index 0000000000..c1efe777e3
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/$.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/$')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/a/$"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/$id.tsx b/e2e/react-router/compiled-matcher/src/routes/a/$id.tsx
new file mode 100644
index 0000000000..563909e296
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/$id.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/$id')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/a/$id"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/b/c/d/e/f.tsx b/e2e/react-router/compiled-matcher/src/routes/a/b/c/d/e/f.tsx
new file mode 100644
index 0000000000..e6cb4db25e
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/b/c/d/e/f.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/b/c/d/e/f')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/a/b/c/d/e/f"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/index.tsx b/e2e/react-router/compiled-matcher/src/routes/a/index.tsx
new file mode 100644
index 0000000000..9f3aaa404e
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/a/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/profile/index.tsx b/e2e/react-router/compiled-matcher/src/routes/a/profile/index.tsx
new file mode 100644
index 0000000000..5d67db2e70
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/profile/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/profile/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/a/profile/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/profile/settings.tsx b/e2e/react-router/compiled-matcher/src/routes/a/profile/settings.tsx
new file mode 100644
index 0000000000..517b4219fe
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/profile/settings.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/profile/settings')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/a/profile/settings"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/user-{$id}.tsx b/e2e/react-router/compiled-matcher/src/routes/a/user-{$id}.tsx
new file mode 100644
index 0000000000..d8b6f32fc1
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/user-{$id}.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/user-{$id}')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/a/user-{$id}"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/a/{-$slug}.tsx b/e2e/react-router/compiled-matcher/src/routes/a/{-$slug}.tsx
new file mode 100644
index 0000000000..8ce00b261f
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/a/{-$slug}.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/a/{-$slug}')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/a/{-$slug}"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/about.tsx b/e2e/react-router/compiled-matcher/src/routes/about.tsx
new file mode 100644
index 0000000000..1e6c7068e0
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/about.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/about')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/about"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/api/user-{$id}.tsx b/e2e/react-router/compiled-matcher/src/routes/api/user-{$id}.tsx
new file mode 100644
index 0000000000..85578d5791
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/api/user-{$id}.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/api/user-{$id}')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/api/user-{$id}"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/b/$.tsx b/e2e/react-router/compiled-matcher/src/routes/b/$.tsx
new file mode 100644
index 0000000000..1d36026704
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/b/$.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/b/$')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/b/$"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/b/$id.tsx b/e2e/react-router/compiled-matcher/src/routes/b/$id.tsx
new file mode 100644
index 0000000000..004b382eae
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/b/$id.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/b/$id')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/b/$id"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/b/index.tsx b/e2e/react-router/compiled-matcher/src/routes/b/index.tsx
new file mode 100644
index 0000000000..dc87544419
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/b/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/b/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/b/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/b/profile/index.tsx b/e2e/react-router/compiled-matcher/src/routes/b/profile/index.tsx
new file mode 100644
index 0000000000..5f32f2d4ee
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/b/profile/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/b/profile/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/b/profile/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/b/profile/settings.tsx b/e2e/react-router/compiled-matcher/src/routes/b/profile/settings.tsx
new file mode 100644
index 0000000000..eeec76d78a
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/b/profile/settings.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/b/profile/settings')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/b/profile/settings"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/b/user-{$id}.tsx b/e2e/react-router/compiled-matcher/src/routes/b/user-{$id}.tsx
new file mode 100644
index 0000000000..afd075f350
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/b/user-{$id}.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/b/user-{$id}')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/b/user-{$id}"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/b/{-$slug}.tsx b/e2e/react-router/compiled-matcher/src/routes/b/{-$slug}.tsx
new file mode 100644
index 0000000000..d03dcbe537
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/b/{-$slug}.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/b/{-$slug}')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/b/{-$slug}"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/beep/boop.tsx b/e2e/react-router/compiled-matcher/src/routes/beep/boop.tsx
new file mode 100644
index 0000000000..2d0115db44
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/beep/boop.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/beep/boop')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/beep/boop"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/cache/temp_{$}.log.tsx b/e2e/react-router/compiled-matcher/src/routes/cache/temp_{$}.log.tsx
new file mode 100644
index 0000000000..2c0abaaf80
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/cache/temp_{$}.log.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/cache/temp_{$}/log')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/cache/temp_{$}.log"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/files/$.tsx b/e2e/react-router/compiled-matcher/src/routes/files/$.tsx
new file mode 100644
index 0000000000..0c4ab5c1a0
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/files/$.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/files/$')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/files/$"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/foo/$bar.index.tsx b/e2e/react-router/compiled-matcher/src/routes/foo/$bar.index.tsx
new file mode 100644
index 0000000000..a55255222b
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/foo/$bar.index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/foo/$bar/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/foo/$bar/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/foo/$bar.tsx b/e2e/react-router/compiled-matcher/src/routes/foo/$bar.tsx
new file mode 100644
index 0000000000..b83a197ac7
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/foo/$bar.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/foo/$bar')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/foo/$bar"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/foo/$id/bar.tsx b/e2e/react-router/compiled-matcher/src/routes/foo/$id/bar.tsx
new file mode 100644
index 0000000000..025eb7a2bf
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/foo/$id/bar.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/foo/$id/bar')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/foo/$id/bar"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/foo/bar/$id.tsx b/e2e/react-router/compiled-matcher/src/routes/foo/bar/$id.tsx
new file mode 100644
index 0000000000..e06fb3ff6b
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/foo/bar/$id.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/foo/bar/$id')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/foo/bar/$id"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/foo/{-$bar}/qux.tsx b/e2e/react-router/compiled-matcher/src/routes/foo/{-$bar}/qux.tsx
new file mode 100644
index 0000000000..37af5c5075
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/foo/{-$bar}/qux.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/foo/{-$bar}/qux')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/foo/{-$bar}/qux"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/images/thumb_{$}.tsx b/e2e/react-router/compiled-matcher/src/routes/images/thumb_{$}.tsx
new file mode 100644
index 0000000000..e81725cb16
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/images/thumb_{$}.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/images/thumb_{$}')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/images/thumb_{$}"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/index.tsx b/e2e/react-router/compiled-matcher/src/routes/index.tsx
new file mode 100644
index 0000000000..d58928d9ed
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/logs/{$}.txt.tsx b/e2e/react-router/compiled-matcher/src/routes/logs/{$}.txt.tsx
new file mode 100644
index 0000000000..456bceb948
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/logs/{$}.txt.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/logs/{$}/txt')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/logs/{$}.txt"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/one.tsx b/e2e/react-router/compiled-matcher/src/routes/one.tsx
new file mode 100644
index 0000000000..8334d30aa2
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/one.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/one')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/one"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/one/two.tsx b/e2e/react-router/compiled-matcher/src/routes/one/two.tsx
new file mode 100644
index 0000000000..8fe6c5615b
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/one/two.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/one/two')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/one/two"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/posts/{-$slug}.tsx b/e2e/react-router/compiled-matcher/src/routes/posts/{-$slug}.tsx
new file mode 100644
index 0000000000..c494586b52
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/posts/{-$slug}.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/posts/{-$slug}')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>{'Hello "/posts/{-$slug}"!'}</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/users/$id.tsx b/e2e/react-router/compiled-matcher/src/routes/users/$id.tsx
new file mode 100644
index 0000000000..99635ef89a
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/users/$id.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/users/$id')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/users/$id"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/users/profile/index.tsx b/e2e/react-router/compiled-matcher/src/routes/users/profile/index.tsx
new file mode 100644
index 0000000000..b042f0e5c9
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/users/profile/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/users/profile/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/users/profile/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/users/profile/settings.tsx b/e2e/react-router/compiled-matcher/src/routes/users/profile/settings.tsx
new file mode 100644
index 0000000000..d0eece68ae
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/users/profile/settings.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/users/profile/settings')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/users/profile/settings"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/z/y/x/index.tsx b/e2e/react-router/compiled-matcher/src/routes/z/y/x/index.tsx
new file mode 100644
index 0000000000..fb49b8aeae
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/z/y/x/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/z/y/x/')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/z/y/x/"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/z/y/x/u.tsx b/e2e/react-router/compiled-matcher/src/routes/z/y/x/u.tsx
new file mode 100644
index 0000000000..20afb916ca
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/z/y/x/u.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/z/y/x/u')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/z/y/x/u"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/z/y/x/v.tsx b/e2e/react-router/compiled-matcher/src/routes/z/y/x/v.tsx
new file mode 100644
index 0000000000..a19ed76a28
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/z/y/x/v.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/z/y/x/v')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/z/y/x/v"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/routes/z/y/x/w.tsx b/e2e/react-router/compiled-matcher/src/routes/z/y/x/w.tsx
new file mode 100644
index 0000000000..e6f0273945
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/routes/z/y/x/w.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/z/y/x/w')({
+  component: RouteComponent,
+})
+
+function RouteComponent() {
+  return <div>Hello "/z/y/x/w"!</div>
+}
diff --git a/e2e/react-router/compiled-matcher/src/styles.css b/e2e/react-router/compiled-matcher/src/styles.css
new file mode 100644
index 0000000000..0b8e317099
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/src/styles.css
@@ -0,0 +1,13 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+html {
+  color-scheme: light dark;
+}
+* {
+  @apply border-gray-200 dark:border-gray-800;
+}
+body {
+  @apply bg-gray-50 text-gray-950 dark:bg-gray-900 dark:text-gray-200;
+}
diff --git a/e2e/react-router/compiled-matcher/tailwind.config.mjs b/e2e/react-router/compiled-matcher/tailwind.config.mjs
new file mode 100644
index 0000000000..4986094b9d
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/tailwind.config.mjs
@@ -0,0 +1,4 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+  content: ['./src/**/*.{js,jsx,ts,tsx}', './index.html'],
+}
diff --git a/e2e/react-router/compiled-matcher/tests/app.spec.ts b/e2e/react-router/compiled-matcher/tests/app.spec.ts
new file mode 100644
index 0000000000..285474fb48
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/tests/app.spec.ts
@@ -0,0 +1,38 @@
+import { expect, test } from '@playwright/test'
+
+test.beforeEach(async ({ page }) => {
+  await page.goto('/')
+})
+
+test('exact path matching', async ({ page }) => {
+  const links = [
+    { url: '', route: '/' },
+    { url: '/', route: '/' },
+    { url: '/users/profile/settings', route: '/users/profile/settings' },
+    // { url: '/foo/123', route: '/foo/$bar/' },
+    // { url: '/FOO/123', route: '/foo/$bar/' },
+    // { url: '/foo/123/', route: '/foo/$bar/' },
+    { url: '/b/123', route: '/b/$id' },
+    { url: '/foo/qux', route: '/foo/{-$bar}/qux' },
+    { url: '/foo/123/qux', route: '/foo/{-$bar}/qux' },
+    { url: '/a/user-123', route: '/a/user-{$id}' },
+    { url: '/a/123', route: '/a/$id' },
+    { url: '/a/123/more', route: '/a/$' },
+    { url: '/files', route: '/files/$' },
+    { url: '/files/hello-world.txt', route: '/files/$' },
+    { url: '/something/foo/bar', route: '/$id/foo/bar' },
+    { url: '/files/deep/nested/file.json', route: '/files/$' },
+    { url: '/files/', route: '/files/$' },
+    { url: '/images/thumb_200x300.jpg', route: '/images/thumb_{$}' },
+    { url: '/logs/2020/01/01/error.txt', route: '/logs/{$}.txt' },
+    { url: '/cache/temp_user456.log', route: '/cache/temp_{$}.log' },
+    { url: '/a/b/c/d/e', route: '/a/$' },
+  ]
+  for (const link of links) {
+    await test.step(`nav to '${link.url}'`, async () => {
+      console.log(`nav to '${link.url}'`)
+      await page.goto(link.url)
+      await expect(page.getByText(`Hello "${link.route}"!`)).toBeVisible()
+    })
+  }
+})
diff --git a/e2e/react-router/compiled-matcher/tests/setup/global.setup.ts b/e2e/react-router/compiled-matcher/tests/setup/global.setup.ts
new file mode 100644
index 0000000000..3593d10ab9
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/tests/setup/global.setup.ts
@@ -0,0 +1,6 @@
+import { e2eStartDummyServer } from '@tanstack/router-e2e-utils'
+import packageJson from '../../package.json' with { type: 'json' }
+
+export default async function setup() {
+  await e2eStartDummyServer(packageJson.name)
+}
diff --git a/e2e/react-router/compiled-matcher/tests/setup/global.teardown.ts b/e2e/react-router/compiled-matcher/tests/setup/global.teardown.ts
new file mode 100644
index 0000000000..62fd79911c
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/tests/setup/global.teardown.ts
@@ -0,0 +1,6 @@
+import { e2eStopDummyServer } from '@tanstack/router-e2e-utils'
+import packageJson from '../../package.json' with { type: 'json' }
+
+export default async function teardown() {
+  await e2eStopDummyServer(packageJson.name)
+}
diff --git a/e2e/react-router/compiled-matcher/tsconfig.json b/e2e/react-router/compiled-matcher/tsconfig.json
new file mode 100644
index 0000000000..82cf0bcd2c
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/tsconfig.json
@@ -0,0 +1,15 @@
+{
+  "compilerOptions": {
+    "strict": true,
+    "esModuleInterop": true,
+    "jsx": "react-jsx",
+    "target": "ESNext",
+    "moduleResolution": "Bundler",
+    "module": "ESNext",
+    "skipLibCheck": true,
+    "resolveJsonModule": true,
+    "allowJs": true,
+    "types": ["vite/client"]
+  },
+  "exclude": ["node_modules", "dist"]
+}
diff --git a/e2e/react-router/compiled-matcher/vite.config.js b/e2e/react-router/compiled-matcher/vite.config.js
new file mode 100644
index 0000000000..ab615485ae
--- /dev/null
+++ b/e2e/react-router/compiled-matcher/vite.config.js
@@ -0,0 +1,11 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+import { tanstackRouter } from '@tanstack/router-plugin/vite'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+  plugins: [
+    tanstackRouter({ target: 'react', autoCodeSplitting: true }),
+    react(),
+  ],
+})
diff --git a/packages/router-core/package.json b/packages/router-core/package.json
index c1ca570c79..f827a08d25 100644
--- a/packages/router-core/package.json
+++ b/packages/router-core/package.json
@@ -30,6 +30,7 @@
     "test:types:ts59": "tsc",
     "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .",
     "test:unit": "vitest",
+    "test:perf": "vitest bench",
     "test:unit:dev": "pnpm run test:unit --watch",
     "build": "vite build"
   },
diff --git a/packages/router-core/src/compile-matcher.ts b/packages/router-core/src/compile-matcher.ts
new file mode 100644
index 0000000000..9d2d4d58e6
--- /dev/null
+++ b/packages/router-core/src/compile-matcher.ts
@@ -0,0 +1,721 @@
+import {
+  SEGMENT_TYPE_OPTIONAL_PARAM,
+  SEGMENT_TYPE_PARAM,
+  SEGMENT_TYPE_PATHNAME,
+  SEGMENT_TYPE_WILDCARD,
+  parsePathname,
+} from './path'
+import type { LRUCache } from './lru-cache'
+import type { Segment } from './path'
+import type { processRouteTree } from './router'
+
+export type CompiledMatcher = (
+  parser: typeof parsePathname,
+  from: string,
+  fuzzy?: boolean,
+  cache?: LRUCache<string, ReadonlyArray<Segment>>,
+) => readonly [path: string, params: Record<string, string>] | undefined
+
+/**
+ * Compiles a sorted list of routes (as returned by `processRouteTree().flatRoutes`)
+ * into a matcher function.
+ *
+ * Run-time use (requires eval permissions):
+ * ```ts
+ * const fn = compileMatcher(processRouteTree({ routeTree }).flatRoutes)
+ * const matcher = new Function('parsePathname', 'from', 'fuzzy', 'cache', fn) as CompiledMatcher
+ * ```
+ *
+ * Build-time use:
+ * ```ts
+ * const fn = compileMatcher(processRouteTree({ routeTree }).flatRoutes)
+ * sourceCode += `const matcher = (parsePathname, from, fuzzy, cache) => { ${fn} }`
+ * ```
+ */
+export function compileMatcher(
+  flatRoutes: ReturnType<typeof processRouteTree>['flatRoutes'],
+) {
+  const parsedRoutes = flatRoutes.map((route) => ({
+    path: route.fullPath,
+    segments: parsePathname(route.fullPath),
+  }))
+
+  const all = toConditions(
+    prepareOptionalParams(prepareIndexRoutes(parsedRoutes)),
+  )
+
+  // We start by building a flat tree with all routes as leaf nodes, children of the same root node.
+  const tree: RootNode = { type: 'root', children: [] }
+
+  const children: Array<LeafNode> = []
+  for (const { conditions, path, segments } of all) {
+    children.push({
+      type: 'leaf',
+      route: { path, segments },
+      parent: tree,
+      conditions,
+    })
+  }
+  tree.children = removeUnreachable(children)
+
+  expandTree(tree)
+  contractTree(tree)
+
+  let fn = ''
+  fn += printHead(all)
+  fn += printTree(tree)
+
+  return fn
+}
+
+type ParsedRoute = {
+  path: string
+  segments: ReturnType<typeof parsePathname>
+}
+
+// we duplicate routes that end in a static `/`, so they're also matched if that final `/` is not present
+function prepareIndexRoutes(
+  parsedRoutes: Array<ParsedRoute>,
+): Array<ParsedRoute> {
+  const result: Array<ParsedRoute> = []
+  for (const route of parsedRoutes) {
+    result.push(route)
+    const last = route.segments.at(-1)!
+    if (
+      route.segments.length > 1 &&
+      last.type === SEGMENT_TYPE_PATHNAME &&
+      last.value === '/'
+    ) {
+      const clone: ParsedRoute = {
+        ...route,
+        segments: route.segments.slice(0, -1),
+      }
+      result.push(clone)
+    }
+  }
+  return result
+}
+
+// we replace routes w/ optional params, with
+// - 1 version where it's a regular param
+// - 1 version where it's removed entirely
+function prepareOptionalParams(
+  parsedRoutes: Array<ParsedRoute>,
+): Array<ParsedRoute> {
+  const result: Array<ParsedRoute> = []
+  for (const route of parsedRoutes) {
+    const index = route.segments.findIndex(
+      (s) => s.type === SEGMENT_TYPE_OPTIONAL_PARAM,
+    )
+    if (index === -1) {
+      result.push(route)
+      continue
+    }
+    // for every optional param in the route, we need to push a version of the route without it, and a version of the route with it as a regular param
+    // example:
+    // /foo/{-$bar}/qux => [/foo/qux, /foo/$bar/qux]
+    // /a/{-$b}/c/{-$d} => [/a/c, /a/c/$d, /a/$b/c, /a/$b/c/$d]
+    const withRegular: ParsedRoute = {
+      ...route,
+      segments: route.segments.map((s, i) =>
+        i === index ? { ...s, type: SEGMENT_TYPE_PARAM } : s,
+      ),
+    }
+    const withoutOptional: ParsedRoute = {
+      ...route,
+      segments: route.segments.filter((_, i) => i !== index),
+    }
+    const chunk = prepareOptionalParams([withRegular, withoutOptional])
+    result.push(...chunk)
+  }
+  return result
+}
+
+type Condition =
+  | { key: string; type: 'static'; index: number; value: string; caseSensitive: boolean }
+  | { key: string; type: 'length'; direction: 'eq' | 'gte'; value: number }
+  | { key: string; type: 'startsWith'; index: number; value: string; caseSensitive: boolean }
+  | { key: string; type: 'endsWith'; index: number; value: string; caseSensitive: boolean }
+  | { key: string; type: 'globalEndsWith'; value: string; caseSensitive: boolean }
+
+// each segment of a route can have zero or more conditions that need to be met for the route to match
+function toConditions(routes: Array<ParsedRoute>) {
+  return routes.map((route) => {
+    const conditions: Array<Condition> = []
+
+    let hasWildcard = false
+    let minLength = 0
+    for (let i = 0; i < route.segments.length; i++) {
+      const segment = route.segments[i]!
+      if (segment.type === SEGMENT_TYPE_PATHNAME) {
+        minLength += 1
+        if (i === 0 && segment.value === '/') continue // skip leading slash
+        // @ts-expect-error -- not typed yet, i don't know how I'm gonna get this value here
+        const caseSensitive = route.caseSensitive ?? false
+        const value = caseSensitive ? segment.value : segment.value.toLowerCase()
+        conditions.push({
+          type: 'static',
+          index: i,
+          value,
+          caseSensitive,
+          key: `static_${caseSensitive}_${i}_${value}`,
+        })
+        continue
+      }
+      if (segment.type === SEGMENT_TYPE_PARAM) {
+        minLength += 1
+        // @ts-expect-error -- not typed yet, i don't know how I'm gonna get this value here
+        const caseSensitive = route.caseSensitive ?? false
+        if (segment.prefixSegment) {
+          const value = caseSensitive ? segment.prefixSegment : segment.prefixSegment.toLowerCase()
+          conditions.push({
+            type: 'startsWith',
+            index: i,
+            value,
+            caseSensitive,
+            key: `startsWith_${caseSensitive}_${i}_${value}`,
+          })
+        }
+        if (segment.suffixSegment) {
+          const value = caseSensitive ? segment.suffixSegment : segment.suffixSegment.toLowerCase()
+          conditions.push({
+            type: 'endsWith',
+            index: i,
+            value,
+            caseSensitive,
+            key: `endsWith_${caseSensitive}_${i}_${value}`,
+          })
+        }
+        continue
+      }
+      if (segment.type === SEGMENT_TYPE_WILDCARD) {
+        hasWildcard = true
+        // @ts-expect-error -- not typed yet, i don't know how I'm gonna get this value here
+        const caseSensitive = route.caseSensitive ?? false
+        if (segment.prefixSegment) {
+          const value = caseSensitive ? segment.prefixSegment : segment.prefixSegment.toLowerCase()
+          conditions.push({
+            type: 'startsWith',
+            index: i,
+            value,
+            caseSensitive,
+            key: `startsWith_${caseSensitive}_${i}_${value}`,
+          })
+        }
+        if (segment.suffixSegment) {
+          const value = caseSensitive ? segment.suffixSegment : segment.suffixSegment.toLowerCase()
+          conditions.push({
+            type: 'globalEndsWith',
+            value,
+            caseSensitive,
+            key: `globalEndsWith_${caseSensitive}_${i}_${value}`,
+          })
+        }
+        if (segment.suffixSegment || segment.prefixSegment) {
+          minLength += 1
+        }
+        continue
+      }
+      throw new Error(`Unhandled segment type: ${segment.type}`)
+    }
+
+    if (hasWildcard) {
+      conditions.push({
+        type: 'length',
+        direction: 'gte',
+        value: minLength,
+        key: `length_gte_${minLength}`,
+      })
+    } else {
+      conditions.push({
+        type: 'length',
+        direction: 'eq',
+        value: minLength,
+        key: `length_eq_${minLength}`,
+      })
+    }
+
+    return {
+      ...route,
+      conditions,
+    }
+  })
+}
+
+type LeafNode = {
+  type: 'leaf'
+  conditions: Array<Condition>
+  route: ParsedRoute
+  parent: BranchNode | RootNode
+}
+type RootNode = { type: 'root'; children: Array<LeafNode | BranchNode> }
+type BranchNode = {
+  type: 'branch'
+  conditions: Array<Condition>
+  children: Array<LeafNode | BranchNode>
+  parent: BranchNode | RootNode
+}
+
+/**
+ * Recursively expand each node of the tree until there is only one child left
+ *
+ * For each child node in a parent node, we try to find subsequent siblings that would share the same condition to be matched.
+ * If we find any, we group them together into a new branch node that replaces the original child node and the grouped siblings in the parent node.
+ *
+ * We repeat the process in each newly created branch node until there is only one child left in each branch node.
+ *
+ * This turns
+ * ```
+ * if (a && b && c && d) return route1;
+ * if (a && b && e && f) return route2;
+ * ```
+ * into
+ * ```
+ * if (a && b) {
+ *   if (c) { if (d) return route1; }
+ *   if (e) { if (f) return route2; }
+ * }
+ * ```
+ *
+ */
+function expandTree(tree: RootNode) {
+  const stack: Array<RootNode | BranchNode> = [tree]
+  while (stack.length > 0) {
+    const node = stack.shift()!
+    if (node.children.length <= 1) continue
+
+    const resolved = new Set<BranchNode | LeafNode>()
+    for (let i = 0; i < node.children.length; i++) {
+      const child = node.children[i]!
+      if (resolved.has(child)) continue
+
+      // segment-based conditions should try to group as many children as possible
+      const bestSegment = findBestSegmentCondition(
+        node,
+        i,
+        node.children.length - i - 1,
+      )
+      // length-based conditions should try to group as few children as possible
+      const bestLength = findBestLengthCondition(node, i, 0)
+
+      if (bestSegment.score === Infinity && bestLength.score === Infinity) {
+        // no grouping possible, just add the child as is
+        resolved.add(child)
+        continue
+      }
+
+      const selected =
+        bestSegment.score < bestLength.score ? bestSegment : bestLength
+      const condition = selected.condition!
+      const newNode: BranchNode = {
+        type: 'branch',
+        conditions: [condition],
+        children: selected.candidates,
+        parent: node,
+      }
+      node.children.splice(i, selected.candidates.length, newNode)
+      stack.push(newNode)
+      resolved.add(newNode)
+      for (const c of selected.candidates) {
+        c.conditions = c.conditions.filter((sc) => sc.key !== condition.key)
+      }
+
+      // find all conditions that are shared by all candidates, and lift them to the new node
+      for (const condition of newNode.children[0]!.conditions) {
+        if (
+          newNode.children.every((c) =>
+            c.conditions.some((sc) => sc.key === condition.key),
+          )
+        ) {
+          newNode.conditions.push(condition)
+        }
+      }
+      for (let i = 1; i < newNode.conditions.length; i++) {
+        const condition = newNode.conditions[i]!
+        for (const c of newNode.children) {
+          c.conditions = c.conditions.filter((sc) => sc.key !== condition.key)
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Recursively shorten branches that have a single child into a leaf node.
+ *
+ * For each branch node in the tree, if it has only one child, we can replace the branch node with that child node,
+ * and merge the conditions of the branch node into the child node.
+ *
+ * This turns
+ * `if (a) { if (b) { return route } }`
+ * into
+ * `if (a && b) { return route }`
+ */
+function contractTree(tree: RootNode) {
+  const stack = tree.children.filter((c) => c.type === 'branch')
+  while (stack.length > 0) {
+    const node = stack.pop()!
+    if (node.children.length === 1) {
+      const child = node.children[0]!
+      node.parent.children.splice(node.parent.children.indexOf(node), 1, child)
+      child.parent = node.parent
+      child.conditions = [...node.conditions, ...child.conditions]
+
+      // reduce length-based conditions into a single condition
+      const lengthConditions = child.conditions.filter(
+        (c) => c.type === 'length',
+      )
+      if (lengthConditions.some((c) => c.direction === 'eq')) {
+        for (const c of lengthConditions) {
+          if (c.direction === 'gte') {
+            child.conditions = child.conditions.filter((sc) => sc.key !== c.key)
+          }
+        }
+      } else if (lengthConditions.length > 0) {
+        const minLength = Math.min(...lengthConditions.map((c) => c.value))
+        child.conditions = child.conditions.filter((c) => c.type !== 'length')
+        child.conditions.push({
+          type: 'length',
+          direction: 'eq',
+          value: minLength,
+          key: `length_eq_${minLength}`,
+        })
+      }
+    }
+    for (const child of node.children) {
+      if (child.type === 'branch') {
+        stack.push(child)
+      }
+    }
+  }
+}
+
+/**
+ * Remove leaves that are not reachable due to the conditions a previous leaf sibling.
+ * 
+ * This turns
+ * ```
+ * if (a) return route1;
+ * if (a && b) return route2;
+ * ```
+ * into
+ * ```
+ * if (a) return route1;
+ * ```
+ */
+function removeUnreachable(nodes: Array<LeafNode>) {
+  loop: for (let i = 0; i < nodes.length; i++) {
+    const candidate = nodes[i]!
+
+    // look through all previous siblings
+    for (let j = 0; j < i; j++) {
+      const sibling = nodes[j]!
+      // if every condition the sibling requires is also present in the candidate,
+      // then that means the candidate is unreachable
+      const candidateIsUnreachable = sibling.conditions.every((c) => {
+        if (c.type === 'length' && c.direction === 'gte') {
+          return candidate.conditions.some((sc) => sc.key === c.key || (sc.type === 'length' && sc.direction === 'eq' && sc.value >= c.value))
+        }
+        // TODO: we could add other "covering" cases like the one above here,
+        // such as the sibling having a `startsWith` condition and the candidate having a static condition that starts with the same value (taking case sensitivity into account)
+        return candidate.conditions.some((sc) => sc.key === c.key)
+      })
+      if (candidateIsUnreachable) {
+        nodes.splice(i, 1)
+        i -= 1
+        continue loop
+      }
+    }
+  }
+  return nodes
+}
+
+function printTree(node: RootNode | BranchNode | LeafNode) {
+  let str = ''
+  if (node.type === 'root') {
+    for (const child of node.children) {
+      str += printTree(child)
+    }
+    return str
+  }
+  if (node.conditions.length) {
+    str += 'if ('
+    str += printConditions(node)
+    str += ')'
+  }
+  if (node.type === 'branch') {
+    if (node.conditions.length && node.children.length) str += `{`
+    for (const child of node.children) {
+      str += printTree(child)
+    }
+    if (node.conditions.length && node.children.length) str += `}`
+  } else {
+    str += printRoute(node.route)
+  }
+  return str
+}
+
+function printConditions(node: BranchNode | LeafNode) {
+  const conditions = node.conditions
+  const lengths = conditions.filter((c) => c.type === 'length')
+  const segment = conditions.filter((c) => c.type !== 'length')
+  const results: Array<string> = []
+  if (lengths.length > 1) {
+    const exact = lengths.find((c) => c.direction === 'eq')
+    if (exact) {
+      results.push(printCondition(exact))
+    } else {
+      results.push(printCondition(lengths[0]!))
+    }
+  } else if (lengths.length === 1) {
+    results.push(printCondition(lengths[0]!))
+  }
+  const [minLength] = findLengthAtNode(node)
+  for (const c of segment) {
+    results.push(printCondition(c, minLength))
+  }
+  return results.join(' && ')
+}
+
+function printCondition(condition: Condition, minLength: number = 0) {
+  switch (condition.type) {
+    case 'static':
+      if (condition.caseSensitive) {
+        return `s${condition.index} === '${condition.value}'`
+      } else {
+        return `sc${condition.index} === '${condition.value}'`
+      }
+    case 'length':
+      if (condition.direction === 'eq') {
+        return `length(${condition.value})`
+      } else if (condition.direction === 'gte') {
+        return `l >= ${condition.value}`
+      }
+      break
+    case 'startsWith':
+      if (condition.caseSensitive) {
+        return `s${condition.index}.startsWith('${condition.value}')`
+      } else if (minLength > condition.index) {
+        return `sc${condition.index}.startsWith('${condition.value}')`
+      } else {
+        return `sc${condition.index}?.startsWith('${condition.value}')`
+      }
+    case 'endsWith':
+      if (condition.caseSensitive) {
+        return `s${condition.index}.endsWith('${condition.value}')`
+      } else if (minLength > condition.index) {
+        return `sc${condition.index}.endsWith('${condition.value}')`
+      } else {
+        return `sc${condition.index}?.endsWith('${condition.value}')`
+      }
+    case 'globalEndsWith':
+      if (condition.caseSensitive) {
+        return `last.endsWith('${condition.value}')`
+      } else {
+        return `last.toLowerCase().endsWith('${condition.value}')`
+      }
+  }
+  throw new Error(`Unhandled condition type: ${condition.type}`)
+}
+
+function printRoute(route: ParsedRoute) {
+  const length = route.segments.length
+  /**
+   * return [
+   *   route.path,
+   *   { foo: s2, bar: s4 }
+   * ]
+   */
+  let result = `{`
+  let hasWildcard = false
+  for (let i = 0; i < route.segments.length; i++) {
+    const segment = route.segments[i]!
+    if (segment.type === SEGMENT_TYPE_PARAM) {
+      const name = segment.value.replace(/^\$/, '')
+      const value = `s${i}`
+      if (segment.prefixSegment && segment.suffixSegment) {
+        result += `${name}: ${value}.slice(${segment.prefixSegment.length}, -${segment.suffixSegment.length}), `
+      } else if (segment.prefixSegment) {
+        result += `${name}: ${value}.slice(${segment.prefixSegment.length}), `
+      } else if (segment.suffixSegment) {
+        result += `${name}: ${value}.slice(0, -${segment.suffixSegment.length}), `
+      } else {
+        result += `${name}: ${value}, `
+      }
+    } else if (segment.type === SEGMENT_TYPE_WILDCARD) {
+      hasWildcard = true
+      const value = `s.slice(${i}).join('/')`
+      if (segment.prefixSegment && segment.suffixSegment) {
+        result += `_splat: ${value}.slice(${segment.prefixSegment.length}, -${segment.suffixSegment.length}), `
+        result += `'*': ${value}.slice(${segment.prefixSegment.length}, -${segment.suffixSegment.length}), `
+      } else if (segment.prefixSegment) {
+        result += `_splat: ${value}.slice(${segment.prefixSegment.length}), `
+        result += `'*': ${value}.slice(${segment.prefixSegment.length}), `
+      } else if (segment.suffixSegment) {
+        result += `_splat: ${value}.slice(0, -${segment.suffixSegment.length}), `
+        result += `'*': ${value}.slice(0, -${segment.suffixSegment.length}), `
+      } else {
+        result += `_splat: ${value}, `
+        result += `'*': ${value}, `
+      }
+      break
+    }
+  }
+  result += `}`
+  return hasWildcard
+    ? `return ['${route.path}', ${result}];`
+    : `return ['${route.path}', params(${result}, ${length})];`
+}
+
+function printHead(
+  routes: Array<ParsedRoute & { conditions: Array<Condition> }>,
+) {
+  let head =
+    'const s = parsePathname(from[0] === "/" ? from : "/" + from, cache).map((s) => s.value);'
+  head += 'const l = s.length;'
+
+  // the `length()` function does exact match by default, but greater-than-or-equal match if `fuzzy` is true
+  head += 'const length = fuzzy ? (n) => l >= n : (n) => l === n;'
+
+  // the `params()` function returns the params object, and if `fuzzy` is true, it also adds a `**` property with the remaining segments
+  head +=
+    "const params = fuzzy ? (p, n) => { if (n && l > n) p['**'] = s.slice(n).join('/'); return p } : (p) => p;"
+
+  // extract all segments from the input
+  // const [, s1, s2, s3] = s;
+  const max = routes.reduce((max, r) => Math.max(max, r.segments.length), 0)
+  if (max > 0)
+    head += `const [,${Array.from({ length: max - 1 }, (_, i) => `s${i + 1}`).join(', ')}] = s;`
+
+  // add toLowerCase version of each segment that is needed in a case-insensitive match
+  // const sc1 = s1?.toLowerCase();
+  const caseInsensitiveSegments = new Set<number>()
+  for (const route of routes) {
+    for (const condition of route.conditions) {
+      if ((condition.type === 'static' || condition.type === 'endsWith' || condition.type === 'startsWith') && !condition.caseSensitive) {
+        caseInsensitiveSegments.add(condition.index)
+      }
+    }
+  }
+  for (const index of caseInsensitiveSegments) {
+    head += `const sc${index} = s${index}?.toLowerCase();`
+  }
+
+  // wildcard with a suffix requires accessing the last segment, whithout knowing its index
+  const hasWildcardWithSuffix = routes.some((route) => route.conditions.some((c) => c.type === 'globalEndsWith'))
+  if (hasWildcardWithSuffix) {
+    head += 'const last = s[l - 1];'
+  }
+
+  return head
+}
+
+function findBestSegmentCondition(
+  node: RootNode | BranchNode,
+  i: number,
+  target: number,
+) {
+  const child = node.children[i]!
+  let bestCondition: Condition | undefined
+  let bestMatchScore = Infinity
+  let bestCandidates = [child]
+  for (const c of child.conditions) {
+    const candidates = [child]
+    for (let j = i + 1; j < node.children.length; j++) {
+      const sibling = node.children[j]!
+      if (sibling.conditions.some((sc) => sc.key === c.key)) {
+        candidates.push(sibling)
+      } else {
+        break
+      }
+    }
+    const score = Math.abs(candidates.length - target)
+    if (score < bestMatchScore) {
+      bestMatchScore = score
+      bestCondition = c
+      bestCandidates = candidates
+    }
+  }
+
+  return {
+    score: bestMatchScore,
+    condition: bestCondition,
+    candidates: bestCandidates,
+  }
+}
+
+function findBestLengthCondition(
+  node: RootNode | BranchNode,
+  i: number,
+  target: number,
+) {
+  const child = node.children[i]!
+  const childLengthCondition = child.conditions.find((c) => c.type === 'length')
+  if (!childLengthCondition) {
+    return { score: Infinity, condition: undefined, candidates: [child] }
+  }
+  const [currentMinLength, lengthKind] = findLengthAtNode(node)
+  if (lengthKind === 'exact' || currentMinLength >= childLengthCondition.value) {
+    return { score: Infinity, condition: undefined, candidates: [child] }
+  }
+  let bestMatchScore = Infinity
+  let bestLength: number | undefined
+  let bestCandidates = [child]
+  let bestExact = false
+  for (let l = currentMinLength + 1; l <= childLengthCondition.value; l++) {
+    const candidates = [child]
+    let exact =
+      childLengthCondition.direction === 'eq' &&
+      l === childLengthCondition.value
+    for (let j = i + 1; j < node.children.length; j++) {
+      const sibling = node.children[j]!
+      const lengthCondition = sibling.conditions.find(
+        (c) => c.type === 'length',
+      )
+      if (!lengthCondition) break
+      if (lengthCondition.value < l) break
+      candidates.push(sibling)
+      exact &&=
+        lengthCondition.direction === 'eq' && lengthCondition.value === l
+    }
+    const score = Math.abs(candidates.length - target)
+    if (score < bestMatchScore) {
+      bestMatchScore = score
+      bestLength = l
+      bestCandidates = candidates
+      bestExact = exact
+    }
+  }
+  const condition: Condition = {
+    type: 'length',
+    direction: bestExact ? 'eq' : 'gte',
+    value: bestLength!,
+    key: `length_${bestExact ? 'eq' : 'gte'}_${bestLength}`,
+  }
+  return { score: bestMatchScore, condition, candidates: bestCandidates }
+}
+
+function findLengthAtNode(
+  node: RootNode | BranchNode | LeafNode,
+) {
+  if (node.type === 'root') return [1, 'min'] as const
+  let currentMinLength = 1
+  let exactLength = false
+  let n = node
+  do {
+    const lengthCondition = n.conditions.find((c) => c.type === 'length')
+    if (!lengthCondition) continue
+    if (lengthCondition.direction === 'eq') {
+      exactLength = true
+      break
+    }
+    if (lengthCondition.direction === 'gte') {
+      currentMinLength = lengthCondition.value
+      break
+    }
+  } while (n.parent.type === 'branch' && (n = n.parent))
+  return [
+    currentMinLength,
+    exactLength ? 'exact' : 'min',
+  ] as const
+}
\ No newline at end of file
diff --git a/packages/router-core/src/index.ts b/packages/router-core/src/index.ts
index ca34da1722..050af54a25 100644
--- a/packages/router-core/src/index.ts
+++ b/packages/router-core/src/index.ts
@@ -107,7 +107,12 @@ export {
   matchByPath,
 } from './path'
 export type { Segment } from './path'
+
+export { compileMatcher } from './compile-matcher'
+export type { CompiledMatcher } from './compile-matcher'
+
 export { encode, decode } from './qss'
+
 export { rootRouteId } from './root'
 export type { RootRouteId } from './root'
 
diff --git a/packages/router-core/tests/compile-matcher.bench.ts b/packages/router-core/tests/compile-matcher.bench.ts
new file mode 100644
index 0000000000..b80a194cc4
--- /dev/null
+++ b/packages/router-core/tests/compile-matcher.bench.ts
@@ -0,0 +1,221 @@
+import { bench, describe } from 'vitest'
+import {
+  joinPaths,
+  matchPathname,
+  parsePathname,
+  processRouteTree,
+} from '../src'
+import { createLRUCache } from '../src/lru-cache'
+import { compileMatcher } from '../src/compile-matcher'
+import type { CompiledMatcher } from '../src/compile-matcher'
+import type { ParsePathnameCache } from '../src/path'
+
+interface TestRoute {
+  id: string
+  isRoot?: boolean
+  path?: string
+  fullPath: string
+  rank?: number
+  parentRoute?: TestRoute
+  children?: Array<TestRoute>
+  options?: {
+    caseSensitive?: boolean
+  }
+}
+
+type PathOrChildren = string | [string, Array<PathOrChildren>]
+
+function createRoute(
+  pathOrChildren: Array<PathOrChildren>,
+  parentPath: string,
+): Array<TestRoute> {
+  return pathOrChildren.map((route) => {
+    if (Array.isArray(route)) {
+      const fullPath = joinPaths([parentPath, route[0]])
+      const children = createRoute(route[1], fullPath)
+      const r = {
+        id: fullPath,
+        path: route[0],
+        fullPath,
+        children: children,
+      }
+      children.forEach((child) => {
+        child.parentRoute = r
+      })
+
+      return r
+    }
+
+    const fullPath = joinPaths([parentPath, route])
+
+    return {
+      id: fullPath,
+      path: route,
+      fullPath,
+    }
+  })
+}
+
+function createRouteTree(pathOrChildren: Array<PathOrChildren>): TestRoute {
+  return {
+    id: '__root__',
+    fullPath: '',
+    isRoot: true,
+    path: undefined,
+    children: createRoute(pathOrChildren, ''),
+  }
+}
+
+const routeTree = createRouteTree([
+  '/',
+  '/users/profile/settings', // static-deep (longest static path)
+  '/users/profile', // static-medium (medium static path)
+  '/api/user-{$id}', // param-with-prefix (param with prefix has higher score)
+  '/users/$id', // param-simple (plain param)
+  '/posts/{-$slug}', // optional-param (optional param ranks lower than regular param)
+  '/files/$', // wildcard (lowest priority)
+  '/about', // static-shallow (shorter static path)
+  '/a/profile/settings',
+  '/a/profile',
+  '/a/user-{$id}',
+  '/a/$id',
+  '/a/{-$slug}',
+  '/a/$',
+  '/a',
+  '/b/profile/settings',
+  '/b/profile',
+  '/b/user-{$id}',
+  '/b/$id',
+  '/b/{-$slug}',
+  '/b/$',
+  '/b',
+  '/foo/bar/$id',
+  '/foo/$id/bar',
+  '/foo/$bar',
+  '/foo/$bar/',
+  '/foo/{-$bar}/qux',
+  '/$id/bar/foo',
+  '/$id/foo/bar',
+  '/a/b/c/d/e/f',
+  '/beep/boop',
+  '/compiled/two',
+  '/compiled',
+  '/z/y/x/w',
+  '/z/y/x/v',
+  '/z/y/x/u',
+  '/z/y/x',
+  '/images/thumb_{$}', // wildcard with prefix
+  '/logs/{$}.txt', // wildcard with suffix
+  '/cache/temp_{$}.log', // wildcard with prefix and suffix
+  '/momomo/{-$one}/$two'
+])
+const result = processRouteTree({ routeTree })
+
+const compiled = (() => {
+  const cache: ParsePathnameCache = createLRUCache(1000)
+  const fn = compileMatcher(result.flatRoutes)
+  const buildMatcher = new Function(
+    'parsePathname',
+    'from',
+    'fuzzy',
+    'cache',
+    fn,
+  ) as CompiledMatcher
+  const wrappedMatcher = (from: string) => {
+    return buildMatcher(parsePathname, from, false, cache)
+  }
+  return wrappedMatcher
+})()
+
+const original = (() => {
+  const cache: ParsePathnameCache = createLRUCache(1000)
+
+  const wrappedMatcher = (from: string) => {
+    const match = result.flatRoutes.find((r) =>
+      matchPathname('/', from, { to: r.fullPath }, cache),
+    )
+    return match
+  }
+  return wrappedMatcher
+})()
+
+const testCases = [
+  '',
+  '/',
+  '/users/profile/settings',
+  '/foo/123',
+  '/foo/123/',
+  '/b/123',
+  '/foo/qux',
+  '/foo/123/qux',
+  '/foo/qux',
+  '/a/user-123',
+  '/a/123',
+  '/a/123/more',
+  '/files',
+  '/files/hello-world.txt',
+  '/something/foo/bar',
+  '/files/deep/nested/file.json',
+  '/files/',
+  '/images/thumb_200x300.jpg',
+  '/logs/error.txt',
+  '/cache/temp_user456.log',
+  '/a/b/c/d/e',
+  '/momomo/1111/2222',
+  '/momomo/2222',
+]
+
+describe('build.bench needle in a haystack', () => {
+  bench(
+    'original',
+    () => {
+      for (const from of testCases) {
+        original(from)
+      }
+    },
+    { warmupIterations: 10 },
+  )
+  bench(
+    'compiled',
+    () => {
+      for (const from of testCases) {
+        compiled(from)
+      }
+    },
+    { warmupIterations: 10 },
+  )
+})
+
+/**
+ * Sometimes in the app, we already know the path we want to match against.
+ * The compiled matcher does not support this.
+ * This benchmark tests the performance of the compiled matcher looking through ALL routes
+ * vs. the original matcher comparing against a single path.
+ */
+describe('build.bench single match', () => {
+  const solutions = testCases.map((from) => original(from)?.fullPath)
+
+  const cache: ParsePathnameCache = createLRUCache(1000)
+  const originalSingle = (from: string, to: string) => matchPathname('/', from, { to }, cache)
+
+  bench(
+    'original (single)',
+    () => {
+      for (let i = 0; i < testCases.length; i++) {
+        const from = testCases[i]!
+        const match = solutions[i]!
+        originalSingle(from, match)
+      }
+    },
+    { warmupIterations: 10 },
+  )
+  bench(
+    'compiled',
+    () => {
+      for (const from of testCases) {
+        compiled(from)
+      }
+    },
+    { warmupIterations: 10 },
+  )
+})
diff --git a/packages/router-core/tests/compile-matcher.test.ts b/packages/router-core/tests/compile-matcher.test.ts
new file mode 100644
index 0000000000..ebb8de388d
--- /dev/null
+++ b/packages/router-core/tests/compile-matcher.test.ts
@@ -0,0 +1,391 @@
+import { describe, expect, it, test } from 'vitest'
+import { format } from 'prettier'
+import {
+  joinPaths,
+  matchPathname,
+  parsePathname,
+  processRouteTree,
+} from '../src'
+import { compileMatcher } from '../src/compile-matcher'
+import type { CompiledMatcher } from '../src/compile-matcher'
+
+interface TestRoute {
+  id: string
+  isRoot?: boolean
+  path?: string
+  fullPath: string
+  rank?: number
+  parentRoute?: TestRoute
+  children?: Array<TestRoute>
+  options?: {
+    caseSensitive?: boolean
+  }
+}
+
+type PathOrChildren = string | [string, Array<PathOrChildren>]
+
+function createRoute(
+  pathOrChildren: Array<PathOrChildren>,
+  parentPath: string,
+): Array<TestRoute> {
+  return pathOrChildren.map((route) => {
+    if (Array.isArray(route)) {
+      const fullPath = joinPaths([parentPath, route[0]])
+      const children = createRoute(route[1], fullPath)
+      const r = {
+        id: fullPath,
+        path: route[0],
+        fullPath,
+        children: children,
+      }
+      children.forEach((child) => {
+        child.parentRoute = r
+      })
+
+      return r
+    }
+
+    const fullPath = joinPaths([parentPath, route])
+
+    return {
+      id: fullPath,
+      path: route,
+      fullPath,
+    }
+  })
+}
+
+function createRouteTree(pathOrChildren: Array<PathOrChildren>): TestRoute {
+  return {
+    id: '__root__',
+    fullPath: '',
+    isRoot: true,
+    path: undefined,
+    children: createRoute(pathOrChildren, ''),
+  }
+}
+
+const routeTree = createRouteTree([
+  '/',
+  '/users/profile/settings', // static-deep (longest static path)
+  '/users/profile', // static-medium (medium static path)
+  '/api/user-{$id}', // param-with-prefix (param with prefix has higher score)
+  '/users/$id', // param-simple (plain param)
+  '/posts/{-$slug}', // optional-param (optional param ranks lower than regular param)
+  '/files/$', // wildcard (lowest priority)
+  '/about', // static-shallow (shorter static path)
+  '/a/profile/settings',
+  '/a/profile',
+  '/a/user-{$id}',
+  '/a/$id',
+  '/a/{-$slug}',
+  '/a/$',
+  '/a',
+  '/b/profile/settings',
+  '/b/profile',
+  '/b/user-{$id}',
+  '/b/$id',
+  '/b/{-$slug}',
+  '/b/$',
+  '/b',
+  '/foo/bar/$id',
+  '/foo/$id/bar',
+  '/foo/$bar',
+  '/foo/$bar/',
+  '/foo/{-$bar}/qux',
+  '/$id/bar/foo',
+  '/$id/foo/bar',
+  '/a/b/c/d/e/f',
+  '/beep/boop',
+  '/one/two',
+  '/one',
+  '/z/y/x/w',
+  '/z/y/x/v',
+  '/z/y/x/u',
+  '/z/y/x',
+  '/images/thumb_{$}', // wildcard with prefix
+  '/logs/{$}.txt', // wildcard with suffix
+  '/cache/temp_{$}.log', // wildcard with prefix and suffix,
+  '/momomo/{-$one}/$two'
+])
+
+// required keys on a `route` object for `processRouteTree` to correctly generate `flatRoutes`
+// - id
+// - children
+// - isRoot
+// - path
+// - fullPath
+
+const result = processRouteTree({ routeTree })
+
+function originalMatcher(
+  from: string,
+  fuzzy?: boolean,
+): readonly [string, Record<string, string>] | undefined {
+  let match
+  for (const route of result.flatRoutes) {
+    const result = matchPathname('/', from, { to: route.fullPath, fuzzy })
+    if (result) {
+      match = [route.fullPath, result] as const
+      break
+    }
+  }
+  return match
+}
+
+describe('work in progress', () => {
+  it('is ordered', () => {
+    expect(result.flatRoutes.map((r) => r.id)).toMatchInlineSnapshot(`
+      [
+        "/a/b/c/d/e/f",
+        "/z/y/x/u",
+        "/z/y/x/v",
+        "/z/y/x/w",
+        "/a/profile/settings",
+        "/b/profile/settings",
+        "/users/profile/settings",
+        "/z/y/x",
+        "/foo/bar/$id",
+        "/a/profile",
+        "/b/profile",
+        "/beep/boop",
+        "/one/two",
+        "/users/profile",
+        "/foo/$id/bar",
+        "/foo/{-$bar}/qux",
+        "/a/user-{$id}",
+        "/api/user-{$id}",
+        "/b/user-{$id}",
+        "/foo/$bar/",
+        "/a/$id",
+        "/b/$id",
+        "/foo/$bar",
+        "/users/$id",
+        "/momomo/{-$one}/$two",
+        "/a/{-$slug}",
+        "/b/{-$slug}",
+        "/posts/{-$slug}",
+        "/cache/temp_{$}.log",
+        "/images/thumb_{$}",
+        "/logs/{$}.txt",
+        "/a/$",
+        "/b/$",
+        "/files/$",
+        "/a",
+        "/about",
+        "/b",
+        "/one",
+        "/",
+        "/$id/bar/foo",
+        "/$id/foo/bar",
+      ]
+    `)
+  })
+
+  const fn = compileMatcher(result.flatRoutes)
+
+  it('generates a matching function', async () => {
+    expect(await format(fn, { parser: 'typescript' })).toMatchInlineSnapshot(`
+      "const s = parsePathname(from[0] === "/" ? from : "/" + from, cache).map(
+        (s) => s.value,
+      );
+      const l = s.length;
+      const length = fuzzy ? (n) => l >= n : (n) => l === n;
+      const params = fuzzy
+        ? (p, n) => {
+            if (n && l > n) p["**"] = s.slice(n).join("/");
+            return p;
+          }
+        : (p) => p;
+      const [, s1, s2, s3, s4, s5, s6] = s;
+      const sc1 = s1?.toLowerCase();
+      const sc2 = s2?.toLowerCase();
+      const sc3 = s3?.toLowerCase();
+      const sc4 = s4?.toLowerCase();
+      const sc5 = s5?.toLowerCase();
+      const sc6 = s6?.toLowerCase();
+      const last = s[l - 1];
+      if (
+        length(7) &&
+        sc1 === "a" &&
+        sc2 === "b" &&
+        sc3 === "c" &&
+        sc4 === "d" &&
+        sc5 === "e" &&
+        sc6 === "f"
+      )
+        return ["/a/b/c/d/e/f", params({}, 7)];
+      if (length(5) && sc1 === "z" && sc2 === "y" && sc3 === "x") {
+        if (sc4 === "u") return ["/z/y/x/u", params({}, 5)];
+        if (sc4 === "v") return ["/z/y/x/v", params({}, 5)];
+        if (sc4 === "w") return ["/z/y/x/w", params({}, 5)];
+      }
+      if (length(4)) {
+        if (sc2 === "profile" && sc3 === "settings") {
+          if (sc1 === "a") return ["/a/profile/settings", params({}, 4)];
+          if (sc1 === "b") return ["/b/profile/settings", params({}, 4)];
+          if (sc1 === "users") return ["/users/profile/settings", params({}, 4)];
+        }
+        if (sc1 === "z" && sc2 === "y" && sc3 === "x")
+          return ["/z/y/x", params({}, 4)];
+        if (sc1 === "foo" && sc2 === "bar")
+          return ["/foo/bar/$id", params({ id: s3 }, 4)];
+      }
+      if (l >= 3) {
+        if (length(3)) {
+          if (sc2 === "profile") {
+            if (sc1 === "a") return ["/a/profile", params({}, 3)];
+            if (sc1 === "b") return ["/b/profile", params({}, 3)];
+          }
+          if (sc1 === "beep" && sc2 === "boop") return ["/beep/boop", params({}, 3)];
+          if (sc1 === "one" && sc2 === "two") return ["/one/two", params({}, 3)];
+          if (sc1 === "users" && sc2 === "profile")
+            return ["/users/profile", params({}, 3)];
+        }
+        if (length(4) && sc1 === "foo") {
+          if (sc3 === "bar") return ["/foo/$id/bar", params({ id: s2 }, 4)];
+          if (sc3 === "qux") return ["/foo/{-$bar}/qux", params({ bar: s2 }, 4)];
+        }
+        if (length(3)) {
+          if (sc1 === "foo" && sc2 === "qux")
+            return ["/foo/{-$bar}/qux", params({}, 3)];
+          if (sc1 === "a" && sc2?.startsWith("user-"))
+            return ["/a/user-{$id}", params({ id: s2.slice(5) }, 3)];
+          if (sc1 === "api" && sc2?.startsWith("user-"))
+            return ["/api/user-{$id}", params({ id: s2.slice(5) }, 3)];
+          if (sc1 === "b" && sc2?.startsWith("user-"))
+            return ["/b/user-{$id}", params({ id: s2.slice(5) }, 3)];
+        }
+        if (length(4) && sc1 === "foo" && sc3 === "/")
+          return ["/foo/$bar/", params({ bar: s2 }, 4)];
+        if (length(3)) {
+          if (sc1 === "foo") return ["/foo/$bar/", params({ bar: s2 }, 3)];
+          if (sc1 === "a") return ["/a/$id", params({ id: s2 }, 3)];
+          if (sc1 === "b") return ["/b/$id", params({ id: s2 }, 3)];
+          if (sc1 === "users") return ["/users/$id", params({ id: s2 }, 3)];
+        }
+        if (length(4) && sc1 === "momomo")
+          return ["/momomo/{-$one}/$two", params({ one: s2, two: s3 }, 4)];
+        if (length(3) && sc1 === "momomo")
+          return ["/momomo/{-$one}/$two", params({ two: s2 }, 3)];
+      }
+      if (l >= 2) {
+        if (length(2)) {
+          if (sc1 === "a") return ["/a/{-$slug}", params({}, 2)];
+          if (sc1 === "b") return ["/b/{-$slug}", params({}, 2)];
+        }
+        if (length(3) && sc1 === "posts")
+          return ["/posts/{-$slug}", params({ slug: s2 }, 3)];
+        if (length(2) && sc1 === "posts") return ["/posts/{-$slug}", params({}, 2)];
+        if (l >= 3) {
+          if (
+            sc1 === "cache" &&
+            sc2.startsWith("temp_") &&
+            last.toLowerCase().endsWith(".log")
+          )
+            return [
+              "/cache/temp_{$}.log",
+              {
+                _splat: s.slice(2).join("/").slice(5, -4),
+                "*": s.slice(2).join("/").slice(5, -4),
+              },
+            ];
+          if (sc1 === "images" && sc2.startsWith("thumb_"))
+            return [
+              "/images/thumb_{$}",
+              {
+                _splat: s.slice(2).join("/").slice(6),
+                "*": s.slice(2).join("/").slice(6),
+              },
+            ];
+          if (sc1 === "logs" && last.toLowerCase().endsWith(".txt"))
+            return [
+              "/logs/{$}.txt",
+              {
+                _splat: s.slice(2).join("/").slice(0, -4),
+                "*": s.slice(2).join("/").slice(0, -4),
+              },
+            ];
+        }
+        if (sc1 === "a")
+          return [
+            "/a/$",
+            { _splat: s.slice(2).join("/"), "*": s.slice(2).join("/") },
+          ];
+        if (sc1 === "b")
+          return [
+            "/b/$",
+            { _splat: s.slice(2).join("/"), "*": s.slice(2).join("/") },
+          ];
+        if (sc1 === "files")
+          return [
+            "/files/$",
+            { _splat: s.slice(2).join("/"), "*": s.slice(2).join("/") },
+          ];
+        if (length(2) && sc1 === "about") return ["/about", params({}, 2)];
+        if (length(2) && sc1 === "one") return ["/one", params({}, 2)];
+      }
+      if (length(1)) return ["/", params({}, 1)];
+      if (length(4) && sc2 === "bar" && sc3 === "foo")
+        return ["/$id/bar/foo", params({ id: s1 }, 4)];
+      if (length(4) && sc2 === "foo" && sc3 === "bar")
+        return ["/$id/foo/bar", params({ id: s1 }, 4)];
+      "
+    `)
+  })
+
+  const buildMatcher = new Function(
+    'parsePathname',
+    'from',
+    'fuzzy',
+    'cache',
+    fn,
+  ) as CompiledMatcher
+
+  test.each([
+    '',
+    '/',
+    '/users/profile/settings',
+    '/foo/123',
+    '/FOO/123',
+    '/foo/123/',
+    '/b/123',
+    '/foo/qux',
+    '/foo/123/qux',
+    '/a/user-123',
+    '/a/123',
+    '/a/123/more',
+    '/files',
+    '/files/hello-world.txt',
+    '/something/foo/bar',
+    '/files/deep/nested/file.json',
+    '/files/',
+    '/images/thumb_200x300.jpg',
+    '/logs/2020/01/01/error.txt',
+    '/cache/temp_user456.log',
+    '/a/b/c/d/e',
+    '/momomo/1111/2222',
+    '/momomo/2222',
+  ])('matching %s', (s) => {
+    const originalMatch = originalMatcher(s)
+    const buildMatch = buildMatcher(parsePathname, s)
+    console.log(
+      `matching: ${s}, originalMatch: ${originalMatch?.[0]}, buildMatch: ${buildMatch?.[0]}`,
+    )
+    expect(buildMatch).toEqual(originalMatch)
+  })
+
+  test.each([
+    '/users/profile/settings/hello',
+    '/a/b/c/d/e/f/g',
+    '/foo/bar/baz',
+    '/foo/bar/baz/qux',
+  ])('fuzzy matching %s', (s) => {
+    const originalMatch = originalMatcher(s, true)
+    const buildMatch = buildMatcher(parsePathname, s, true)
+    console.log(
+      `fuzzy matching: ${s}, originalMatch: ${originalMatch?.[0]}, buildMatch: ${buildMatch?.[0]} ${JSON.stringify(buildMatch?.[1])}`,
+    )
+    expect(buildMatch).toEqual(originalMatch)
+  })
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f72812ba0b..1b6d76b581 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -626,6 +626,64 @@ importers:
         specifier: 6.3.5
         version: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)
 
+  e2e/react-router/compiled-matcher:
+    dependencies:
+      '@tanstack/react-router':
+        specifier: workspace:*
+        version: link:../../../packages/react-router
+      '@tanstack/react-router-devtools':
+        specifier: workspace:^
+        version: link:../../../packages/react-router-devtools
+      '@tanstack/router-plugin':
+        specifier: workspace:*
+        version: link:../../../packages/router-plugin
+      '@tanstack/zod-adapter':
+        specifier: workspace:*
+        version: link:../../../packages/zod-adapter
+      autoprefixer:
+        specifier: ^10.4.20
+        version: 10.4.20(postcss@8.5.3)
+      postcss:
+        specifier: ^8.5.1
+        version: 8.5.3
+      react:
+        specifier: ^19.0.0
+        version: 19.0.0
+      react-dom:
+        specifier: ^19.0.0
+        version: 19.0.0(react@19.0.0)
+      redaxios:
+        specifier: ^0.5.1
+        version: 0.5.1
+      tailwindcss:
+        specifier: ^3.4.17
+        version: 3.4.17
+      zod:
+        specifier: ^3.24.2
+        version: 3.25.57
+    devDependencies:
+      '@playwright/test':
+        specifier: ^1.52.0
+        version: 1.52.0
+      '@tanstack/router-e2e-utils':
+        specifier: workspace:^
+        version: link:../../e2e-utils
+      '@types/react':
+        specifier: ^19.0.8
+        version: 19.0.8
+      '@types/react-dom':
+        specifier: ^19.0.3
+        version: 19.0.3(@types/react@19.0.8)
+      '@vitejs/plugin-react':
+        specifier: ^4.3.4
+        version: 4.6.0(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0))
+      combinate:
+        specifier: ^1.1.11
+        version: 1.1.11
+      vite:
+        specifier: 6.3.5
+        version: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)
+
   e2e/react-router/generator-cli-only:
     dependencies:
       '@tanstack/react-router':
