Skip to main content

Rendering Pages in Next.js

With @weaverse/hydrogen, React Router injects context.weaverse into every loader. The App Router has no loader context, so a Next.js route tells Weaverse which page it is rendering, loads that page on the server, and hands the result to a small client component that renders it. This page assumes you have the app-owned server helper and the root provider from the Quickstart.

Route identity

Every page load starts from the route’s identity: The route segment owns these values, so pass them to your server helper rather than deriving them later. The same identity reaches the page load, the section loaders and per-item revalidation, so a section resolves the same data in every path.
Studio’s runtime reads i18n.language when it binds to the page. Always set i18n on the request context, even for a single-market store. See Markets & Translations.

Page types

Each Weaverse page type maps to a route your app owns. The paths are yours; Weaverse only needs the type and handle. If your routes differ from the Shopify convention (Forward serves collections at /shop/:handle), declare them in the theme schema’s routes so Studio can navigate to them. See Studio integration.

A complete route

A page route loads its Shopify data and its Weaverse page in parallel, answers notFound() when either is missing, and renders the page through the client boundary. This is Forward’s product route, trimmed:
loadWeaversePage is an app helper that builds the server client and calls loadPage, returning null when the project is not configured, the request fails, or no page exists. It wraps the getWeaverseServerClient helper from the Quickstart:

No page means 404

loadPage resolves to null when Weaverse holds no page for the route. Answer that with notFound(). Do not substitute a hard-coded composition: a Weaverse project always ships its default templates, so a page renders exactly as the merchant authored it, and an empty template renders empty.
notFound() returns a real 404 only while no loading.tsx wraps the route. A loading.tsx adds a Suspense boundary, and once the streamed shell is sent the response is committed to 200 before your check runs.

Custom pages

Merchants create custom pages at paths your code cannot know ahead of time, so one catch-all route serves all of them. Weaverse resolves a CUSTOM page by its pathname:
Always pass the real pathname (or url) for custom pages. When the request context has neither, the SDK falls back to /, and every custom route silently resolves to the home page.
Because the catch-all sits at the app root, it also receives paths other routes decline (for example an unknown handle on a route with dynamicParams = false). notFound() answers both cases. See Custom Pages for how merchants create them.

The client boundary

WeaverseNextRenderer holds React context and subscribes to a store, so it runs in a Client Component. Keep that boundary in one file: it is the one place that ships the component registry to the browser. The server payload carries the route identity in data.configs.requestInfo. Restore it into the client’s request context; without it Studio has no page to outline and no item to revalidate.
Prefer the project id from the payload over your environment: Studio targets the project the page was loaded with.

Route data or section loaders

Sections get Shopify data in one of two ways. Pick by who decides which resource is shown.

Route data (context)

A template is shared by every resource of its kind, so the product on /products/summer-tee is decided by the URL, not by a merchant’s picker. The route already loads it; pass it down through a React context (dataContext above) and let sections read it.

Section loaders

When the merchant picks the data in Studio (a product list, a collection), the section resolves it itself with a server-side loader, which re-runs when the merchant changes the selection.
A minimal context for route data:

SEO metadata

Map the page’s Weaverse SEO into Next’s Metadata with getWeaverseNextSeoMetadata from @weaverse/next/server:
The helper accepts the loader data, a page, or null (which returns indexable defaults), and its result is assignable to Metadata. Two Studio values are normalized so Next can always render them:
  • Open Graph type product becomes website, because Next throws on product.
  • Twitter card types app and player become summary, because Studio does not collect the extra fields those cards need.
formatWeaverseNextSeoMetadata is the lower-level formatter if you already hold the SEO object. Merchants edit these fields as described in Page SEO.

Custom pages in the sitemap

fetchCustomPages returns every published custom page, paginating for you. It accepts Next cache options:
If a later page of results fails, it returns the pages already fetched instead of throwing, so one API error does not break the sitemap.

Next steps

Data Fetching

Section loaders, caching and revalidation

Studio Integration

Connect Studio, revalidate items, declare theme routes

Markets & Translations

Localized routes and Translation Manager

API Reference

Every export of @weaverse/next