Skip to main content
Version: 3.x

Dynamic Routing

Since version 3.5

This guide explains how you can create dynamic routes for url rewrites in Front-Commerce.

What is dynamic routing?

Dynamic routes are generated based on the data available in your application, allowing for more meaningful and SEO-friendly URLs. For example, instead of a generic URL such as /product/sku-6, you can have a more descriptive URL like /acme-product.html.

Consider a Remix route for your products defined as routes/product.$id.tsx. By leveraging dynamic routes, you can replace generic product URLs with SEO-friendly alternatives.

Generic Route Example

  • URL: /product/sku-6

SEO-Friendly Route Example

  • URL: /acme-product.html

By implementing dynamic routes, you enhance the readability and search engine optimization (SEO) of your URLs, which can improve your site's visibility and user experience.

How to create dynamic routes?

Batching and Prioritizing URL Matchers

When multiple URL matchers are registered without any matcherOptions, it will default the batchOrder and priority to 0. This means that the order in which the URL matchers are registered will determine the order in which they are executed.

Let's say we have the following list of URL Matchers:

A → fast API (cached)
B → no API (static)
C → slow API (not cached)
D → no API (static)

We would ideally want this to first try to run B and D then A and finally C. To achieve this we can set the batchOrder and priority fields in the matcherOptions object.

extension/index.ts
services.DynamicRoutes.registerUrlMatcher("A", () => new UrlMatcherA(), {
batchOrder: 1,
priority: 1,
});

services.DynamicRoutes.registerUrlMatcher("B", () => new UrlMatcherB(), {
batchOrder: 0,
priority: 2,
});

services.DynamicRoutes.registerUrlMatcher("C", () => new UrlMatcherC(), {
batchOrder: 2, // only run if no other batches have matched
priority: 1,
});

services.DynamicRoutes.registerUrlMatcher("D", () => new UrlMatcherD(), {
batchOrder: 0,
priority: 1,
});

This would result in the following order of execution:

# batch 0
D → no API (static)
B → no API (static)

# batch 1
A → fast API (cached)

# batch 2 (only run if no other batches have matched)
C → slow API (not cached)

Extending the type declarations

For TypeScript support of the type field in your handle export, you can extend the DynamicRoutesCompositionList interface from the @front-commerce/types package to include your custom types.

Known Limitations

Matching Catch-All Routes (Splat Routes)

In Remix, you can create a catch-all route that matches any path, for example:

URLMatched Route
/foo/aroutes/foo.$.tsx
/bar/aroutes/bar.$.tsx

However, it's not possible to create a URL Matcher for catch-all routes because the URL will still be matched by Remix. Attempting to match /example to routes/foo.$.tsx using a URL matcher will result in the following error:

Error: Route "routes/foo.$" does not match URL "/example"

Dynamic Route Catch-All Placeholder

To implement CSR for dynamic routes, the application requires specific internal logic in the routes/_main.$.tsx file.

If you have overwritten this route, you will need to manually apply and maintain this logic to ensure proper functionality.