Recipe: SEO
Developer preview
Goal: Uniform authors set the SEO data of each page. Next.js writes it into the <head> of the page. A sitemap lists the pages of the project map.
You will make these files:
| File | Job |
|---|---|
lib/uniform/getRoute.ts | Resolves the route one time for each request. |
lib/uniform/getUniformMetadata.ts | Changes the composition parameters into a Next.js Metadata object. |
app/uniform/[code]/page.tsx | Adds generateMetadata to the composition route. |
app/sitemap.ts | Makes /sitemap.xml from the project map. |
Prerequisites#
An app with the composition route
app/uniform/[code]/page.tsx. Refer to Add the composition route.The package
@uniformdev/canvas, for the constantCANVAS_PUBLISHED_STATEand the helperisAssetParamValue.These parameters on the composition type of your pages, for example
page:Parameter ID Type metaTitleText metaDescriptionText ogImageAsset The environment variable
NEXT_PUBLIC_SITE_URLwith the public URL of the site, for examplehttps://www.example.com. The code uses it for the canonical URLs and for the sitemap.
Step 1: Resolve the route one time for each request#
generateMetadata and the page both need the route. Wrap the resolver in React cache. Then the two calls in one request share one result:
lib/uniform/getRoute.ts
The function takes the code as a string. React cache compares the arguments by identity, so a new object on each call does not find the cached result.
Step 2: Change the parameters into metadata#
lib/uniform/getUniformMetadata.ts
- Parameters: the composition parameters are in
result.route.compositionApiResponse.composition.parameters. Each parameter has avalue. A parameter isundefinedwhen the author did not fill it in. - Title: the code uses
metaTitle. WhenmetaTitleis empty, it uses the name of the composition. - Open Graph image: an asset parameter contains a list of assets. The code uses the URL of the first asset.
- Canonical URL:
alternates.canonicaladds<link rel="canonical">. The code uses the route path of the page state, without the query string. - Robots:
pageState.compositionStatetells you the state of the content. For draft and editor content, the code addsnoindex, nofollow. Only a browser with the draft mode cookie sees draft content, so this rule is an extra safety step.
Step 3: Add generateMetadata to the composition route#
app/uniform/[code]/page.tsx
paramsis a promise in Next.js 16. Useawaitbefore you readcode.- The resolver result can be a composition, a redirect or no route.
requireCompositionreturns the composition. For a redirect, it callsredirect()orpermanentRedirect(). For no route, it callsnotFound(). Next.js permits these functions ingenerateMetadata. resolveRoutetellsUniformCompositionto use the same cached function. Thus the page andgenerateMetadatause one result.
Step 4: Make a sitemap from the project map#
app/sitemap.ts
- The project map client sends no cache tags. Thus a Uniform webhook does not update the sitemap. The
revalidatecache mode gets the project map again after the interval. - A dynamic node, for example
/products/:slug, is a pattern for many URLs. The sitemap cannot list them from the project map. Add these URLs from your own data source. - The example gets all nodes in one request. For a large project map, use the
limitandoffsetoptions ofgetNodes. - Make sure that the middleware does not process
/sitemap.xml. The matcher in Add the middleware excludessitemap.xmlandrobots.txt.
How it works#
- The middleware writes the route path and the composition state into the code.
generateMetadataresolves the route from the code. Reactcachekeeps the result for the request.- The page renders
UniformComposition, which gets the same result fromgetRoute. - Next.js adds the metadata tags to the
<head>of the page.
The Uniform resolvers also use the Next.js data cache:
- Published content: the Route API request uses
force-cache. The data cache keeps the response until a webhook revalidates its cache tags. Refer to Caching. - Draft content, editor content, and
next dev: the request usesno-cache. Each request goes to Uniform.
Limits#
- Locales and path rewrites: the canonical URL uses
pageState.routePath. IfrewriteRequestPathin the middleware changes the path,routePathis the project map path, not the public URL. Then make the canonical URL from your public URL. - Query strings: the code removes the query string from the canonical URL. If a query string makes a different page, add it again.
- Metadata after the first response: Next.js can send
generateMetadataresults after the first part of the page. For bots that do not run JavaScript, Next.js waits for the metadata. Refer to the Next.js documentation forgenerateMetadata. - Ordinary Next.js routes: for a page that resolves its own route, call
getUniformMetadataonly for a composition result. Refer to Add Uniform regions to Next.js pages.