Rendering
In this section, you learn how to render components and compositions that are defined using Uniform Canvas in your front-end application.
This usually involves these steps:
- Initial project setup for Uniform
- Render compositions and slots
Create API key#
Click the Uniform logo at the top of the page to return to the Uniform team home page.
In the Security section, click API keys.
Create an API key with the following custom permissions:
Uniform Canvas > Compositions > Read PublishedAbout this step
If you already have an API key with these permissions, you can skip this step.
Add the following values to your
.env
file. You collected these values when you created the Uniform API key:Uniform value Environment variable API Key UNIFORM_API_KEY
Project ID UNIFORM_PROJECT_ID
Fetch composition data#
Most modern front-end frameworks like Next.js and Nuxt 3 provide dynamic routing capabilities that are ideal for rendering compositions.
By leveraging dynamic routes, you can create a single file such as /pages/[...path].jsx
that handles composition rendering for any URL path. This pattern provides a clean and maintainable way to serve compositions across your entire application.
It also empowers content editors to independently manage the site structure through project maps in Uniform. Editors can create, modify, and reorganize pages without requiring developer assistance for sitemap changes.
When rendering a composition you will need to resolve the current URL to fetch the corresponding composition data.
Refer to the routing guide for more information on how to implement routing using Uniform.
Routing
Learn about routing approaches with Uniform.
Routing with Next.js
Helper methods to simplify routing with Uniform in Next.js.
Render composition#
Next.js#
To make these instructions easier to follow, a specific example is used.
The example activates Canvas for the following dynamic Next.js page (using the page router and server-side rendering), where the content of the <main>
tag will be rendered with Canvas:
/pages/[...path].jsx
Add the following packages to your app:
@uniformdev/canvas @uniformdev/canvas-react @uniformdev/canvas-nextRender the page with the composition data:
Add the following code which fetches the composition data for the current route using the Uniform Route API and passes the data to the page component as
data
prop which is then passed to theUniformComposition
component./pages/[...path].jsx
import Head from "next/head"; import { withUniformGetServerSideProps } from "@uniformdev/canvas-next/route"; import { UniformComposition, UniformSlot } from "@uniformdev/canvas-react"; // this example is using server-side rendering (SSR) for simplicity export const getServerSideProps = withUniformGetServerSideProps({ handleComposition: async ({ compositionApiResponse }) => { const { composition } = compositionApiResponse || {}; return { props: { title: "Sample app", data: composition }, }; }, }); export default function Page({title, data: composition }) { return ( <UniformComposition data={composition}> <div> <Head> <title>{title}</title> </Head> <main> <UniformSlot name="body" /> </main> </div> </UniformComposition> ); }
Starters and tutorials for Next.js#
Next.js Starter: App Router
Check out the Next.js Starter for App Router on GitHub for a complete example.
Next.js Starter: Page Router
Check out the Next.js Starter for Page Router on GitHub for a complete example.
Next.js tutorial: App Router
A step-by-step tutorial on how to build a Next.js app with App Router with Canvas.
Next.js tutorial: Page Router
A step-by-step tutorial on how to build a Next.js app with Page Router with Canvas.
Nuxt 3#
To make these instructions easier to follow, a specific example is used. The example activates Canvas for the following dynamic page, where the content of the <main>
tag will be rendered with Canvas:
/pages/[...path].vue
Add the following packages to your app:
@uniformdev/canvas @uniformdev/context @uniformdev/canvas-vue @uniformdev/context-vue @uniformdev/uniform-nuxtAdd the Nuxt module to
nuxt.config.ts
:nuxt.config.ts
export default defineNuxtConfig({ modules: ["@uniformdev/uniform-nuxt"], uniform: { projectId: process.env.UNIFORM_PROJECT_ID, readOnlyApiKey: process.env.UNIFORM_API_KEY, }, });Render the page with the composition data:
Update the page component in
/pages/[...path].vue
:/pages/[...path].vue
<script lang="ts" setup> import { DefaultNotImplementedComponent } from '@uniformdev/canvas-vue'; const resolveRenderer = ({ type }) => { // TODO: extend the function to return a component based on the `type` property. return DefaultNotImplementedComponent; }; const title = 'Sample App'; // get the path from the route const route = useRoute(); const path = Array.isArray(route.params.path) ? `/${route.params.path.join("/")}` : `/${route.params.path}`; // fetch the composition const { composition, error } = await useUniformComposition({ projectMapNodePath: path, }); // handle any errors if (error?.value) { console.error("Error fetching composition from Uniform", error.value); } </script> <template> <UniformComposition :data="composition" :resolve-renderer="resolveRenderer"> <div> <Head> <Title>{{ title }}</Title> </Head> <main> <UniformSlot name="body" /> </main> </div> </UniformComposition> </template>
Starters and tutorials for Nuxt 3#
Nuxt 3 Starter
Check out the Nuxt 3 Starter on GitHub for a complete example.
Nuxt 3 tutorial
A step-by-step tutorial on how to build a Nuxt 3 app with Canvas.
Control rendered markup#
During the composition rendering process, Uniform generates markup. By default, the markup is surrounded by a <div>
tag. This tag can cause problems with certain forms of CSS.
This example demonstrates how to prevent this extra markup from being generated.
Render slots#
When a Canvas component has slots, it's expected that the components in the slot will be rendered in the front-end application. Each Canvas component must be mapped to a component type that's compatible with the front-end technology used. You must provide the mapping for Uniform.
This example demonstrates how to define the mapping and assign it to the component that controls the rendering process.
Using component registry#
HeroComponent.jsx
As <UniformSlot />
component doesn't import FE components directly, we need to import them manually here to include them to the bundle and run our registerUniformComponent()
You still need to import canvasComponents.js to include all the components, such as in NextJS _app.js
is the best place for it.
Using component resolver#
info
For more information, see the UniformComposition component reference.
Control rendered Uniform slot markup#
A slot lets you define a list of child components to render inside a <UniformSlot />
component.
By default, an array of children renders inside a minimal container (in case of React, it's React.Fragment
).
React
The final React output will look like this:
React
Sometimes you may want to control how a slot renders its children. For example, the popular slider library Swiper requires you to wrap slides with <SwiperSlide />
component. Each slide should be the immediate child of the parent <Swiper />
component. To achieve this in Uniform you can use the wrapperComponent
prop of the <UniformSlot />
component.
React
info
For more information, see the UniformComposition component reference, and the guide for routing with Next.js.