Skip to main content

Project Map

Digital Experience Composition (DXC) Catalyst Customers Only

This feature is currently only available through our Digital Experience Composition (DXC) Catalyst Customer Success program. If you're interested in joining this program, please reach out to your Uniform contact or email us at

Keep an eye on our social media and What's New page to be the first to know when this feature is generally available.

This section provides information on how to use project maps.

Get all pages from Project Map

The following example demonstrates how to list all compositions that are in a published state using (there some exceptions though).

In this particular example we are using Dynamic Catch All Routes from Next.JS that allows us to render all pages in single place, from Home page, to deep multilevel pages.

// /pages/[[]].js
import { CanvasClient, CANVAS_DRAFT_STATE, CANVAS_PUBLISHED_STATE, } from '@uniformdev/canvas';
import { ProjectMapClient } from '@uniformdev/project-map';
const projectMapClient = new ProjectMapClient({
apiKey: '[!!! UNIFORM API KEY !!!]',
projectId: '[!!! UNIFORM PROJECT ID !!!]',
const canvasClient = new CanvasClient({
apiKey: '[!!! UNIFORM API KEY !!!]',
projectId: '[!!! UNIFORM PROJECT ID !!!]',
export const getStaticPaths = async () => {
const { nodes } = await projectMapClient.getNodes({
projectMapId: '[!!! UNIFORM PROJECT MAP ID !!!]',
return {
paths: nodes?.filter((node) => node.compositionId!).map((node) => node.path) ?? [],
fallback: false,
export async function getStaticProps(context) {
const slug = context?.params?.id;
const slugString = Array.isArray(slug) ? slug.join('/') : slug;
const { preview } = context;
const { composition } = await canvasClient.unstable_getCompositionByNodePath({
projectMapNodePath: slugString ? `\${slugString}` : '/',
process.env.NODE_ENV === "development" || preview
if (!composition) {
return { notFound: true };
return {
props: {
preview: preview,

Generate sitemap.xml

Usually sitemap generation is your web framework task (also more reliable because of dynamic pages exceptions). But you can use Project Map API directly to fetch whole tree (tree or flat structure) data to construct it your self.

Next.js framework provides three ways to achieve it:

  1. Manual static file upload -

  2. Generate via getServerSideProps - This is the only option where you'd need to use Project Map Api

  3. Generate via npm package next-sitemap. Preferred option

Dynamic pages

In a case like a commerce site, you may have thousands of links where some sort of identifier is used in the URL to determine the content to display. Products may be added and removed constantly. It's not practical or realistic to create a project map node for each possible URL.

In addition, the composition used for these URLs may be virtually identical, with the only difference being the data displayed in the components. Again, it is neither practical nor realistic to create a composition for each possible URL.

In cases like this you can use a "dynamic routing" approach similiar static site generators like Next.js and Vue work.


In the future, Uniform's project map will provide support for dynamic routing as a native feature. Stay tuned for details.

  1. In your project map, add a project map node that represents the dynamic part of the URL.


    The node name is not significant, but the path segment value is because it is the value your front-end application will use to determine which content to retrieve.

  2. In your front-end application, retrieve the composition:

    const client = new CanvasClient({
    apiKey: "[!!! YOUR API KEY !!!]",
    projectId: "[!!! YOUR PROJECT ID !!!]",

    const { composition } = await canvasClient.getCompositionByNodePath({
    projectMapId: "[!!! YOUR PROJECT MAP ID !!!]",
    projectMapNodePath: "/products/product-id",
  3. Your front-end application is responsible for determining the value of the path segment (i.e. product-id) in order to retrieve the appropriate data from the relevant content sources.