Next.js Pages Router
Edit on GitHubDocs pages and an API reference with getStaticProps.
The Pages Router has no Server Components. You load the data in getStaticProps and render it on the page.
Docs pages
docs.serialize() compiles the MDX at build time. MdxClient renders it.
pages/docs/[[...slug]].tsx
import type { GetStaticPaths, GetStaticProps } from "next";
import { isMdxNotFound, type SerializeResult } from "@ariadocs/mdx";
import { MdxClient } from "@ariadocs/mdx/client";
import { docs } from "@/lib/docs";
type Props = { serialized: SerializeResult; title: string };
export default function Page({ serialized, title }: Props) {
return (
<article>
<h1>{title}</h1>
<MdxClient serialized={serialized} />
</article>
);
}
export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
const slug = ((params?.slug as string[] | undefined) ?? []).join("/");
try {
const { serialized, frontmatter } = await docs.serialize<{ title: string }>({ slug });
return { props: { serialized, title: frontmatter.title } };
} catch (error) {
if (isMdxNotFound(error)) return { notFound: true };
throw error;
}
};
export const getStaticPaths: GetStaticPaths = async () => {
const paths = await docs.getPagePaths();
return {
paths: paths.map((path) => ({ params: { slug: path.split("/").filter(Boolean) } })),
fallback: false,
};
};
Import MdxClient from @ariadocs/mdx/client. The main entry also contains code that reads files, which can't run in the browser.
API reference
The OpenAPI components work on the client too. Pass the parsed spec as a prop.
pages/reference/[operation].tsx
import type { GetStaticPaths, GetStaticProps } from "next";
import type { APISpec } from "@ariadocs/openapi";
import { OpenAPI } from "@ariadocs/components";
import { openapi } from "@/lib/openapi";
type Props = { api: APISpec; operation: string };
export default function Page({ api, operation }: Props) {
return (
<OpenAPI.Root api={api} operationBaseHref="/reference">
<OpenAPI.Operation id={operation} headingLevel={1} />
</OpenAPI.Root>
);
}
export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
const api = await openapi.parse();
// Next.js props must be plain JSON, so drop the `undefined` fields.
return { props: { api: JSON.parse(JSON.stringify(api)), operation: String(params?.operation) } };
};
export const getStaticPaths: GetStaticPaths = async () => {
const paths = await openapi.getPagePaths();
return { paths: paths.map((path) => ({ params: { operation: path.slice(1) } })), fallback: false };
};
Every page gets the whole spec. For a large API, pass only the operation instead and render <OpenAPI.Operation operation={operation} /> without Root. You lose the authorization details, which need the full spec.