TanStack Start
Edit on GitHubDocs pages and an API reference with server functions.
TanStack Start loaders also run in the browser during client navigation. Anything that reads files has to go through a server function.
Docs pages
src/routes/docs/$.tsx
import { createFileRoute, notFound } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { isMdxNotFound } from "@ariadocs/mdx";
import { MdxClient } from "@ariadocs/mdx/client";
import { docs } from "../../docs";
const getPage = createServerFn({ method: "GET" })
.inputValidator((slug: string) => slug)
.handler(async ({ data: slug }) => {
try {
const { serialized, frontmatter } = await docs.serialize<{ title: string }>({ slug });
return { serialized, frontmatter };
} catch (error) {
if (isMdxNotFound(error)) throw notFound();
throw error;
}
});
export const Route = createFileRoute("/docs/$")({
loader: ({ params }) => getPage({ data: params._splat ?? "" }),
component: DocsPage,
});
function DocsPage() {
const { serialized, frontmatter } = Route.useLoaderData();
return (
<article>
<h1>{frontmatter.title}</h1>
<MdxClient serialized={serialized} />
</article>
);
}
API reference
src/routes/reference/$operation.tsx
import { createFileRoute } from "@tanstack/react-router";
import { createServerFn } from "@tanstack/react-start";
import { OpenAPI } from "@ariadocs/components";
import { openapi } from "../../openapi";
const getSpec = createServerFn({ method: "GET" }).handler(() => openapi.parse());
export const Route = createFileRoute("/reference/$operation")({
loader: () => getSpec(),
component: ReferencePage,
});
function ReferencePage() {
const api = Route.useLoaderData();
const { operation } = Route.useParams();
return (
<OpenAPI.Root api={api} operationBaseHref="/reference">
<OpenAPI.Operation id={operation} headingLevel={1} />
</OpenAPI.Root>
);
}
openapi.parse() caches its result, so the spec is read once per server process.