Routing
Routing is the process of resolving a requested URL to render the appropriate content for that URL. Once a URL is published it acts as a contract with any visitor that content can be retrieved using it. Therefore it's important to make decisions about what system or URL management approach acts as the source of truth for URLs to confirm that they're consistent and valid.
In Uniform, URLs are primarily generated through a project map and resolved through the route API. The route API enables fetching dynamic and static project map paths, as well as handling redirects with a single endpoint. You can use the route API by using framework-specific helpers, SDK (RouteClient), or by calling the route API directly.
Project map routes#
A project map has a tree of nodes that define the URL structure for your project (often a web page). Use project map routes when Uniform is the primary source of truth for URLs.
By using project maps you can manage, visualize, and resolve URLs for compositions that are managed in Uniform (using composition nodes) or in other systems (using placeholder nodes or dynamic routes).
Choose the project map approach for managing URLs when:
- Uniform Canvas is responsible for defining and resolving most of your URLs
- Your application has nested URLs or views
- Your application has more than a few pages or views
- You want to empower business users to define URL structures
- The URL structure contains dynamic elements such as product IDs
Project map nodes vs composition slugs
When attaching a composition to a project map node the slug field of the composition should not be used to define the URL path of that composition.
Learn more about how to use the project map.
Use these tools to implement routing with project maps:
- Recommended: The route API enables fetching dynamic and static project map paths, as well as handling redirects, with a single endpoint. Uniform provides framework-specific helpers, RouteClient, or the route API.
- The ProjectMapClient and project map API provide management of project map data, as well as querying by static project map paths.
- The CanvasClient can fetch compositions based on static project map paths (dynamic path segments are only supported using the route API).
Using dynamic routes with project map#
Most applications have at least one route where a part is dynamically delegated to a different data source. Common examples might include product detail pages, locale-specific URLs, or news articles. Their paths might be something like /products/123
or /news/2023/05/05/uniform-rocks
.
In this case you don't want to have to register and maintain every possible value within a project map because the list of products may come from another system. To solve this, you can create dynamic path segments (matching /products/*
) and allowed query strings (/search?q=hello&page=2
). You can configure these when editing a project map node.
Dynamic path segments#
Dynamic path segments allow project map to resolve any value for one segment in a URL. Given a dynamic node path such as /:lang/products/:productId
, this would resolve to the :productId
project map node for values such as /en/products/32
and /uk/products/awesome
. Once the route is matched, the specific dynamic values are passed to the composition and resolve to external data.
Allowed query strings#
Allowed query strings enable specific query string values to be collected from the URL and passed to the route API to be made available to external data on compositions. These are useful for tasks such as search queries, pagination of results, and other cases where a path might have more than one value. Note that query strings have a default value which is used when the query parameter isn't passed, which is different from the preview value of a dynamic path segment that only applies when previewing the composition.
tip
Only the route API supports dynamic route resolution (/products/132
-> /products/:productId
). The project map and composition APIs only support the literal path of dynamic routes. Note that the representation of routes for querying uses the colon (:
) prefix, so to fetch /products/*productId
with the project map API one would query for /products/:productId
.
Dynamic route matching#
With dynamic routes it can happen that more than one project map node matches a given input path. For example, the path /products/132
could match both /products/:productId
or /products/132
in a project map. Redirects defined in Uniform could also match a path from a project map node and the redirect.
When multiple possible matches occur
- Redirect matches override project map matches.
- More specific project map or redirect paths win. Meaning, the candidate with the fewest dynamic path segments wins. In the preceding example
/products/132
is an exact match and so it wins. - Matches use the whole path and don't evaluate ancestors. For example, if you add
/products/:productId/specs
to the project map in the example, and request/products/132/specs
, it will match even though product 132 has a custom project map node.
If you are attempting to figure out why a route isn't matching, note that the route API returns the matched route in its response that you can inspect.
Dynamic routes#
To configure a dynamic route, navigate to Content > Project Map and add a node by either clicking the Add node button, the + within your project map, or the ••• within your project map and select an option to add a node. Select Dynamic under "Path segment" to create a dynamic path.
A screen will open with options to configure the new node.

Node configuration options
Field | Value |
---|---|
Name | A human-friendly name for your node. If in the "Node type" settings you specified that a new composition should be created, this value is used as the name of the new composition. This field is required. |
Path segment | Select Static or Dynamic. This field is pre-populated from the name field but can be any slug-like string. |
Node type | Composition: means the node represents a composition. You'll be able to create a new composition right here or select an existing one. Placeholder: means you don't yet have any composition for your node yet and you are only setting up a project structure, or that you are creating a parent node that doesn't have any content and plays role of structural parent in your tree (for example, if you have product page urls like these /products/t-shirt and /products/jeans , but you don't have an actual /products page. However, you need a /products parent node to exist to have a valid site tree). |
Composition | If the "Node type" is set to "Composition," there are options to Create new, which creates a new composition to connect to the node, or Assign existing where you connect an existing composition to the node. You can either select from the list provided or search for the desired composition. |
Allowed query strings | If the "Node type" is set to "Composition," there is an option to add query strings to your path. Select Add query string and enter the field, the default value, and any help text you want to provide authors. Query strings can also be edited or deleted, either from the project map page or from within the composition.![]() Configure a query string |
Location | You will choose the location for the node within the tree, whether you create a new composition or placeholder. |
Create compositions for dynamic routes#
Create a composition for dynamic routes to manage all pages rendered for dynamic routes with a single composition.