Dynamic data-driven pages with code components

Let’s say you already have data-fetching code components, either created by yourself, or from the Plasmic component store (such as components that show CMS or commerce data). You can build dynamic pages using your data-fetching code components with path parameters and query parameters.

Examples include:

  • A blog with one page per post.
  • A storefront with one page per product.

(If you are looking to pass dynamic data into simple static Plasmic designs that don’t use code components, see how to pass overrides to the component API.)

The approach is to take a single page designed in Plasmic, and communicate to it the URL parameters. This essentially uses that page as a template.

Example: statically generated /products/[slug] pages in Next.js or Gatsby

Here’s an example showing how to display a product at /products/[slug], using Next.js or Gatsby dynamic routes.

We’ll assume we’re fetching data using the data-fetching components in the Plasmic CMS.

Let’s say our page includes a Plasmic CMS data-fetching component instance. These components take “Filter field” and “Filter value” props that allow you to fetch specific elements from the CMS. This is specific to the Plasmic CMS data-fetching component—other data-fetching components will have different props.

In Plasmic studio, you can set “Filter field” to “slug” and bind “Filter value” to a dynamic value coming from the URL. To do so, first set the page path to “/products/[slug]” and set “slug” preview parameter to a product slug that exists in your model:

Dynamic page params

Then, set “Filter field” to “slug”, right click “Filter value” in CMS Data Loader props and hit “Use dynamic value”. You should see “Page route params”, which will let you pick the “slug” param that you added to the page path.

Dynamic page params in dynamic value

Code integration

In general, you will need to ensure the data from your framework’s router is passed into PlasmicRootProvider (if using Headless API) or PageParamsProvider (if using codegen).

You can find a complete example project at https://studio.plasmic.app/projects/bY35SmJJgVeJtcuAReMtgz.

If you’re using SSG, you will need to edit getStaticPaths so Next.js knows which pages it needs to generate.

Copy
export const getStaticPaths: GetStaticPaths = async () => {
const pages = await PLASMIC.fetchPages();
const slugs = await getProductSlugs(); // ["sticker", "nice-shirt", ...]
return {
paths: [
...pages.map((page) => ({
params: { catchall: page.path.substring(1).split('/') }
})),
...slugs.map((slug) =>> ({
params: { catchall: ['products', slug] }
})),
],
};
};
export const getStaticProps: GetStaticProps = async (context) => {
// ...
};
export default function Page(props: {
plasmicData?: ComponentRenderData;
queryCache?: Record<string, any>;
}) {
const { plasmicData, queryCache } = props;
const router = useRouter();
if (!plasmicData || plasmicData.entryCompMetas.length === 0) {
return <Error statusCode={404} />;
}
const pageMeta = plasmicData.entryCompMetas[0];
// Pass in the params from your router into pageParams and pageQuery
return (
<PlasmicRootProvider
loader={PLASMIC}
prefetchedData={plasmicData}
prefetchedQueryData={queryCache}
pageParams={pageMeta.params}
pageQuery={router.query}
>
<PlasmicComponent component={pageMeta.displayName} />
</PlasmicRootProvider>
);
}

You can see a complete working example of this approach.

The code above uses the Headless API; if you’re using codegen you would need to tweak your page file in a similar way:

Copy
import { PageParamsProvider } from "@plasmicapp/react-web/lib/host";
...
export const getStaticPaths: GetStaticPaths = async () => {
const slugs = await getProductSlugs(); // ["sticker", "nice-shirt", ...]
return {
paths: slugs.map((slug) =>> ({ params: { slug } })),
};
};
function Product() {
const router = useRouter();
return (
<PageParamsProvider route={router.pathname} params={router.query} query={router.query}>
<PlasmicProduct />
</PageParamsProvider>
);
}
export default Product;

Adding SEO page metadata

To add dynamic SEO metadata—such as a page title and description that vary based on the fetched data—you can’t rely on the page metadata for the time being.

Instead, insert a Head component. This has various props that you can configure from the right sidebar to set the page title and other SEO/page metadata.

This is an invisible component, and must be selected from the outline list. Be sure to insert this somewhere in the outline under whatever data fetching component you’re using—that way, you can set the page title, etc. to a dynamic value that will be able to access the fetched data.

See the opening video for an example of this.

Was this page helpful?

Have feedback on this page? Let us know on our forum.