Skip to content

route-pattern Overview

The route-pattern package is the URL matching engine that powers Remix's router. It parses URL pattern strings like /users/:id into structured objects, matches real URLs against those patterns, extracts parameters, generates URLs from patterns, and compares matches by specificity.

What is a URL Pattern?

A URL (Uniform Resource Locator) is an address like https://example.com/users/42. A URL pattern is a template that describes a set of URLs. For example, the pattern /users/:id matches /users/42, /users/99, and /users/alice -- the :id part is a placeholder that matches any value.

URL patterns have four kinds of segments:

SyntaxWhat it MatchesExample PatternExample Match
/aboutExact text/about/about only
/:paramOne path segment (no slashes)/users/:id/users/42
/*wildcardEverything after this point/files/*path/files/a/b/c.txt
/(:optional)Zero or one segment/users/(:id)/users or /users/42

When to Use This Package

Most of the time, you do not need route-pattern directly -- the fetch-router uses it internally. But it is useful when you need:

  • Low-level pattern matching outside of a router context
  • URL generation from patterns and parameters
  • Specificity comparison to determine which pattern is the best match
  • Custom matchers for specialized routing data structures

Key Features

Type-Safe Parameter Inference

TypeScript automatically extracts the parameter names and types from a pattern string:

ts
import type { Params } from 'remix/route-pattern'

type UserParams = Params<'/users/:id'>
// { id: string }

type PostParams = Params<'/users/:userId/posts/:postId'>
// { userId: string; postId: string }

Pattern Matching

Match a URL against a pattern and extract the dynamic values:

ts
import { RoutePattern } from 'remix/route-pattern'

let pattern = new RoutePattern('/users/:id')
let match = pattern.match(new URL('http://localhost/users/42'))

if (match) {
  console.log(match.params.id) // "42"
}

URL Generation

Build URLs from a pattern and a set of parameters -- no string concatenation needed:

ts
let pattern = new RoutePattern('/users/:id/posts/:postId')
pattern.href({ id: '42', postId: '7' })
// "/users/42/posts/7"

Specificity Ranking

When multiple patterns match the same URL, specificity determines which one wins. A static segment like /users/new is more specific than a dynamic segment like /users/:id:

ts
import { greaterThan } from 'remix/route-pattern/specificity'

let staticMatch = new RoutePattern('/users/new').match(url)
let dynamicMatch = new RoutePattern('/users/:id').match(url)

greaterThan(staticMatch, dynamicMatch) // true

Matcher Data Structures

Two built-in matchers let you store many patterns and efficiently find which ones match a URL:

  • ArrayMatcher -- tests patterns one by one. Good for small route tables.
  • TrieMatcher -- uses a trie (tree) data structure for fast lookups. Better for large route tables.

Quick Example

ts
import { RoutePattern } from 'remix/route-pattern'

// Parse a pattern
let pattern = new RoutePattern('/blog/:year/:slug')

// Match a URL
let match = pattern.match(new URL('http://localhost/blog/2025/hello-remix'))
if (match) {
  console.log(match.params)
  // { year: "2025", slug: "hello-remix" }
}

// Generate a URL
let url = pattern.href({ year: '2025', slug: 'new-post' })
// "/blog/2025/new-post"

// Test without extracting params
pattern.test(new URL('http://localhost/blog/2025/anything')) // true
pattern.test(new URL('http://localhost/other'))               // false

Advanced Patterns

RoutePattern can also match protocols, hostnames, ports, and query parameters. See the API reference for the full syntax.

Next Steps

Released under the MIT License.