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:
| Syntax | What it Matches | Example Pattern | Example Match |
|---|---|---|---|
/about | Exact text | /about | /about only |
/:param | One path segment (no slashes) | /users/:id | /users/42 |
/*wildcard | Everything 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:
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:
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:
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:
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) // trueMatcher 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
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')) // falseAdvanced Patterns
RoutePattern can also match protocols, hostnames, ports, and query parameters. See the API reference for the full syntax.
Next Steps
- Tutorial: Working with URL Patterns -- Hands-on examples of matching, generating, and comparing patterns.
- API Reference -- Complete documentation of
RoutePattern, matchers, and specificity functions.