Sure, I hope this works for you:
import {
ComponentRenderData,
PageMeta,
PlasmicComponent,
PlasmicRootProvider,
extractPlasmicQueryData,
} from "@plasmicapp/loader-nextjs";
import {
generateAllPaths,
getActiveVariation,
rewriteWithoutTraits,
} from "@plasmicapp/loader-nextjs/edge";
import { GetStaticPaths, GetStaticProps } from "next";
import Error from "next/error";
import { useRouter } from "next/router";
import domains, {
DomainConfig,
getConfigForDomainName,
} from "@/config/domains";
import IGNORED_PATHS from "@/config/ignoredPaths";
import REVALIDATE from "@/config/revalidate";
import usePageViewEvent from "@/hooks/usePageViewEvent";
import PLASMIC from "plasmic-init";
interface CatchallPageProps {
plasmicData?: ComponentRenderData;
queryCache?: Record<string, any>;
variation?: Record<string, string>;
projectId: string;
}
const NOT_FOUND = {
props: {} as CatchallPageProps,
notFound: true,
revalidate: REVALIDATE,
};
const filterPage = (page: PageMeta, config: DomainConfig) =>
page.projectId === config.plasmic.id && !IGNORED_PATHS.includes(page.path);
const mapPageToStaticPathObjects = (page: PageMeta, domainName: string) =>
// This generates all possible variant paths for a given page, e.g. for a/b tests
// @ts-expect-error - There is a bug in the types for `@plasmicapp/loader-nextjs/edge`
generateAllPaths(page.path).map((path: string) => ({
params: { catchall: path.slice(1).split("/"), domainName },
}));
/**
* Use fetchPages() to fetch list of pages that have been created in Plasmic
*/
export const getStaticPaths: GetStaticPaths = async () => {
const pages = await PLASMIC.fetchPages();
return {
paths: Object.entries(domains).flatMap(([domainName, config]) =>
pages
.filter((page) => filterPage(page, config))
.flatMap((page) => mapPageToStaticPathObjects(page, domainName)),
),
fallback: "blocking",
};
};
/**
* For each page, pre-fetch the data we need to render it
*/
export const getStaticProps: GetStaticProps<CatchallPageProps> = async (
context,
) => {
const { catchall, domainName } = context.params ?? {};
const domainConfig = getConfigForDomainName(domainName as string);
if (!domainConfig) {
return NOT_FOUND;
}
// Convert the catchall param into a path string
const rawPlasmicPath =
typeof catchall === "string"
? catchall
: Array.isArray(catchall)
? `/${catchall.join("/")}`
: "/";
// Parse the path, and extract the traits.
// @ts-expect-error - There is a bug in the types for `@plasmicapp/loader-nextjs/edge`
const { path: plasmicPath, traits } = rewriteWithoutTraits(rawPlasmicPath);
// Ignore paths that we don't want to render (e.g. error pages created inside Plasmic)
if (IGNORED_PATHS.includes(plasmicPath)) {
return NOT_FOUND;
}
const plasmicData = await PLASMIC.maybeFetchComponentData({
name: plasmicPath,
projectId: domainConfig.settings.plasmic.id,
});
if (!plasmicData) {
// No data found in Plasmic for this path
return NOT_FOUND;
}
// Choose the variation of the page to use from Plasmic based on the traits
// @ts-expect-error - There is a bug in the types for `@plasmicapp/loader-nextjs/edge`
const variation = getActiveVariation({
splits: PLASMIC.getActiveSplits(),
traits,
path: plasmicPath,
});
const pageMeta = plasmicData.entryCompMetas[0];
// Cache the necessary data fetched for the page.
const queryCache = await extractPlasmicQueryData(
<PlasmicRootProvider
loader={PLASMIC}
prefetchedData={plasmicData}
pageParams={pageMeta.params}
variation={variation}
skipFonts
>
<PlasmicComponent
component={pageMeta.displayName}
projectId={domainConfig.settings.plasmic.id}
/>
</PlasmicRootProvider>,
);
// Pass the data in as props.
return {
props: {
plasmicData,
queryCache,
variation,
projectId: domainConfig.settings.plasmic.id,
},
// Using incremental static regeneration, will invalidate this page
// after 60s (no deploy webhooks needed)
revalidate: REVALIDATE,
};
};
const CatchallPage = (props: CatchallPageProps) => {
const { plasmicData, queryCache, variation, projectId } = props;
const router = useRouter();
usePageViewEvent();
if (!plasmicData || plasmicData.entryCompMetas.length === 0) {
return <Error statusCode={404} />;
}
const pageMeta = plasmicData.entryCompMetas[0];
return (
// Pass in the data fetched in getStaticProps as prefetchedData
<PlasmicRootProvider
loader={PLASMIC}
prefetchedData={plasmicData}
prefetchedQueryData={queryCache}
variation={variation}
pageParams={pageMeta.params}
pageQuery={router.query}
skipFonts
>
<PlasmicComponent
component={pageMeta.displayName}
projectId={projectId}
/>
</PlasmicRootProvider>
);
};
export default CatchallPage;