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.

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).

One important aspect of a localized frontend application is the ability to have localized URLs. This is especially important for SEO and user experience to adapt to the needs and languages of specific markets or regions. Uniform supports localized routes by using locale nodes in the project map for resolving the locale and locale-specific path segments to localize each node.

When a route is resolved with the Uniform Route API, it will match all possible routes for the given path, including localized routes for the requested locale. If a node has no localized path segment for the requested locale, the fallback path segment of the node will be used.

If the requested route is able to resolve a matching locale on the attached composition, then the composition is returned in the requested locale. If the composition does not have a matching locale enabled then a "404 Not Found" response is returned. If one or more locales are passed to the API request, the API will return the composition in the first locale that matches the requested locale(s).


Localized project map nodes act more like an alias for a specific locale. If a composition is found for a requested locale is only determined by the enabled locales on the composition itself or when the API request for the composition is specifying locale fallbacks.

Localizing or removing the localization of a project map node will not affect if a composition is available for the requested locale.

If a route contains the fallback path segment of a localized node it will automatically redirect to localized path segment of that node.

For example if you have a project map node /products with a localized path segment /produkte for the German de-DE locale, and a request is made to /de-DE/products, the route API will return a redirect result to /de-DE/produkte automatically.

This ensures that you can safely start with non-localized routes and add localized routes later without breaking existing URLs.

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 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 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.


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.

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.

To configure a dynamic route, navigate to Experience > 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.

The screen for configuring a node

Node configuration options

NameA 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 segmentSelect Static, Dynamic, or Locale. This field is pre-populated from the name field but can be any slug-like string. Locale nodes are a version of dynamic nodes that are tied to locales configured in Canvas settings.
LocalizationsClick the Edit localizations to localize the node. This is only available if the path segment is set to Static.
Refer to the localized routes guide for more information on how to use and resolve localized routes.
Attached compositionSelect New, Existing, or None.\ New: means a new composition will be created and attached to the new node. By default the new composition will have the same name as the node and its slug is set to the path segment of the node. This can be changed later when editing the composition.
Existing Attach an existing composition to the node. You can either select from the list provided or search for the desired composition. None: 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 placeholder 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). Another use case for a placeholder node is when you want to represent a URL that is managed by a different system but you want to make it available in the project map for linking purposes.
Allowed query stringsIf 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.
LocationYou will choose the location for the node within the tree, whether you create a new composition or placeholder.

Create a composition for dynamic routes to manage all pages rendered for dynamic routes with a single composition.