Dynamic Routes

[…slug].astro

---
import type { Block } from "@wp-block-tools/styles";
import { getRootClasses } from "@wp-block-tools/styles";
import BlockRenderer from "../components/BlockRenderer.astro";
import Welcome from "../components/Welcome.astro";
import Layout from "../layouts/Layout.astro";

type PageNode = {
uri: string;
};

type ResolvedPageNode = {
blocks?: Block[];
seo?: {
title?: string | null;
metaDesc?: string | null;
} | null;
};

type StaticPathsResponse = {
cssVariables?: string | null;
pages?: {
nodes?: PageNode[];
} | null;
};

type Props = {
blocks: Block[];
cssVariables?: string | null;
seoTitle?: string | null;
seoMetaDesc?: string | null;
};

export async function getStaticPaths() {
const fetchGraphql = async <T,>(
query: string,
variables?: Record<string, unknown>,
) => {
const response = await fetch(`${import.meta.env.WP_GRAPHQL_URL}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
variables,
}),
});

const { data } = (await response.json()) as { data?: T };
return data;
};

const normalizeSlug = (uri: string) => {
if (uri === "/") {
return undefined;
}

return uri.replace(/^\/+|\/+$/g, "");
};

const staticPathsData = await fetchGraphql<StaticPathsResponse>(`
query AllPages {
cssVariables
pages(first: 10000) {
nodes {
uri
}
}
}
`);

const cssVariables = staticPathsData?.cssVariables ?? null;
const pages = staticPathsData?.pages?.nodes ?? [];

return Promise.all(
pages.map(async (page: PageNode) => {
const pageData = await fetchGraphql<{
nodeByUri?: ResolvedPageNode | null;
}>(
`
query PageByUri($uri: String!) {
nodeByUri(uri: $uri) {
... on Page {
blocks
seo {
title
metaDesc
}
}
}
}
`,
{ uri: page.uri },
);

const resolvedPage = pageData?.nodeByUri;

return {
params: {
slug: normalizeSlug(page.uri),
},
props: {
blocks: resolvedPage?.blocks ?? [],
cssVariables,
seoTitle: resolvedPage?.seo?.title ?? null,
seoMetaDesc: resolvedPage?.seo?.metaDesc ?? null,
},
};
}),
);
}

const { blocks, cssVariables, seoTitle, seoMetaDesc } = Astro.props as Props;
const rootClasses = getRootClasses();
---

<Layout
cssVariables={cssVariables}
seoTitle={seoTitle}
seoMetaDesc={seoMetaDesc}
>
<Welcome />
<div class={rootClasses}>
<BlockRenderer blocks={blocks} />
</div>
</Layout>
Was this page helpful?