The following example demonstrates how to list all compositions that are in a published state using the project map client (there are some exceptions).
In this example Uniform uses Dynamic Catch All Routes from Next.js to render all pages in single place, from Home page, to deep multilevel pages.
An example to fetch the compositions to show in a navigation component. The useAsyncData is needed to make sure this data fetching is only made once on the server, without re-fetching on the client.
By using the link parameter on components, editors can set links to other nodes. This ensures valid URLs even when the linked node is moved to another location within the project map. How these links are rendered in the frontend application is up to the developer to decide and implement.
Here is an example of a custom InternalLink component that demonstrates how to render an internal link with the Link parameter using the Next.js Link component and how to handle different link types, including links to project map nodes, URLs, email addresses, and telephone numbers. The LinkParamValue and ProjectMapLinkParamValue types are used to handle the different link types, but most of the time the LinkParamValue type is sufficient. The ProjectMapLinkParamValue type is used when the link is a project map node and you need to access the node id, dynamic input values, or project map id in the component.
/src/components/InternalLink.tsx
import Link from "next/link";
import { LinkParamValue, ProjectMapLinkParamValue } from "@uniformdev/canvas";
export default function InternalLink({
title,
internalLink,
openInNewTab,
}: {
title: string;
internalLink: LinkParamValue | ProjectMapLinkParamValue;
openInNewTab: boolean;
}) {
// If the link is a project map node, we can get the node id, dynamic input values, and project map id
if (internalLink?.type === "projectMapNode") {
const nodeId = internalLink.nodeId;
const dynamicInputValues = internalLink.dynamicInputValues;
const projectMapId = internalLink.projectMapId;
}
// For all links types, we can get the URL or target from the 'path' property
// For example, if no link is set just render an anchor link - change to fit your needs
if (internalLink?.type === "projectMapNode" || internalLink?.type === "url") {
const url = internalLink?.path?.length ? internalLink.path : "#";
// Render link using Next.js Link Component
return (
<Link href={url} target={openInNewTab ? "_blank" : "_self"}>
{title}
</Link>
);
}
// If the link is not a project map node or URL (e.g. a telephone number or email address), we can render a regular anchor link
if (internalLink?.type === "email" || internalLink?.type === "tel") {
return (
<a href={internalLink?.path} target={openInNewTab ? "_blank" : "_self"}>
{title}
</a>
);
}
// Optionally, if the link is not an existing link type, we can throw an error
throw new Error(`Unsupported link type: ${internalLink?.type}`);
}
Here is an example of a custom InternalLink component that demonstrates how to render an internal link with the NuxtLink parameter using the NuxtLink component
/components/InternalLink.vue
<script lang="ts" setup>
import { type ProjectMapLinkParamValue } from '@uniformdev/canvas';
const props = defineProps<{
title: string;
internalLink: ProjectMapLinkParamValue;
openInNewTab: boolean;
}>();
// get the URL from the 'path' property of the link parameter
// if no link is set just render an anchor link - change to fit your needs
const url = internalLink.path?.length ? internalLink.path : "#";
</script>
<template>
<NuxtLink :href="url" :target="openInNewTab ? '_blank' : '_self'">
{{ title }}
</NuxtLink>
</template>
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:
Generate via getServerSideProps - https://nextjs.org/learn/seo/crawling-and-indexing/xml-sitemaps. This is the only option where you'd need to use Project Map API
Preferred option: Generate via npm package next-sitemap.
You can use the Nuxt Sitemap Module to generate a sitemap for your Nuxt app.
The tree-like hierarchical structure of nodes in a project map make it easy to render navigational components using the project map client. Example use cases for navigation could be:
Global navigation: Use project maps to render a main navigation or footer navigation
Local navigation: Show links to sibling or child nodes of a specific node.
Breadcrumb navigation: Show the trail of parent nodes of a specific node (such as Home > Company > About us).
Advanced or custom navigation
If you need to control the structure or display, or need to enrich your navigation with content or personalized links, Uniform recommends you create custom Canvas components that represent your navigation UI. This gives you a high level of flexibility as you can leverage all Canvas capabilities. Use link parameters in your components to connect your links with the project map.
To get the list of the top level project map nodes (for example, for a global navigation), you can use ProjectMapClient.getNodes and set the depth parameter to 1:
const projectMapClient = new ProjectMapClient({
apiKey: "[!!! UNIFORM API KEY !!!]",
projectId: "[!!! UNIFORM PROJECT ID !!!]",
});
const response = await projectMapClient.getNodes({
depth: 1,
});
To get the ancestors of a project map node (for example, for breadcrumb navigation), you can use ProjectMapClient.getNodes and set the includeAncestors parameter to true:
const projectMapClient = new ProjectMapClient({
apiKey: "[!!! UNIFORM API KEY !!!]",
projectId: "[!!! UNIFORM PROJECT ID !!!]",
});
const response = await projectMapClient.getNodes({
path: "/my-category/my-subcategory/my-page",
includeAncestors: true,
});