Tanstack Start

Setup Hanzo Docs on Tanstack Start.

Getting Started

Before continuing, make sure to configure:

  • Tailwind CSS 4.
  • Hanzo Docs MDX: follow the and create essential files like lib/source.ts.

Installation

npm i @hanzo/docs
pnpm add @hanzo/docs
yarn add @hanzo/docs
bun add @hanzo/docs

Styles

Add the following to your Tailwind CSS file:

styles/app.css
@import 'tailwindcss';
@import '@hanzo/docs/ui/css/neutral.css';
@import '@hanzo/docs/ui/css/preset.css';

Create Pages

Create the following routes:

import type { BaseLayoutProps } from '@hanzo/docs/ui/layouts/shared';

export function baseOptions(): BaseLayoutProps {
  return {
    nav: {
      title: 'Tanstack Start',
    },
  };
}
import { createFileRoute, notFound } from '@tanstack/react-router';
import { DocsLayout } from '@hanzo/docs-base-ui/layouts/docs';
import { createServerFn } from '@tanstack/react-start';
import { source } from '@/lib/source';
import browserCollections from '@hanzo/docs-mdx:collections/browser';
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from '@hanzo/docs-base-ui/layouts/docs/page';
import defaultMdxComponents from '@hanzo/docs-base-ui/mdx';
import { baseOptions } from '@/lib/layout.shared';
import { useHanzoDocsLoader } from '@hanzo/docs-core/source/client';
import { Suspense } from 'react';

export const Route = createFileRoute('/docs/$')({
  component: Page,
  loader: async ({ params }) => {
    const slugs = params._splat?.split('/') ?? [];
    const data = await serverLoader({ data: slugs });
    await clientLoader.preload(data.path);
    return data;
  },
});

const serverLoader = createServerFn({
  method: 'GET',
})
  .inputValidator((slugs: string[]) => slugs)
  .handler(async ({ data: slugs }) => {
    const page = source.getPage(slugs);
    if (!page) throw notFound();

    return {
      path: page.path,
      pageTree: await source.serializePageTree(source.getPageTree()),
    };
  });

const clientLoader = browserCollections.docs.createClientLoader({
  component(
    { toc, frontmatter, default: MDX },
    // you can define props for the component
    props: {
      className?: string;
    },
  ) {
    return (
      <DocsPage toc={toc} {...props}>
        <DocsTitle>{frontmatter.title}</DocsTitle>
        <DocsDescription>{frontmatter.description}</DocsDescription>
        <DocsBody>
          <MDX
            components={{
              ...defaultMdxComponents,
            }}
          />
        </DocsBody>
      </DocsPage>
    );
  },
});

function Page() {
  const data = useHanzoDocsLoader(Route.useLoaderData());

  return (
    <DocsLayout {...baseOptions()} tree={data.pageTree}>
      <Suspense>
        {clientLoader.useContent(data.path, {
          className: '',
        })}
      </Suspense>
    </DocsLayout>
  );
}
import { createFileRoute } from '@tanstack/react-router';
import { source } from '@/lib/source';
import { createFromSource } from '@hanzo/docs/core/search/server';

const server = createFromSource(source, {
  // https://docs.orama.com/docs/orama-js/supported-languages
  language: 'english',
});

export const Route = createFileRoute('/api/search')({
  server: {
    handlers: {
      GET: async ({ request }) => server.GET(request),
    },
  },
});

Wrap your entire app under Hanzo Docs providers:

__root.tsx
import { createRootRoute, HeadContent, Outlet, Scripts } from '@tanstack/react-router';
import * as React from 'react';
import { RootProvider } from '@hanzo/docs/ui/provider/tanstack';

export const Route = createRootRoute({
  component: RootComponent,
});

function RootComponent() {
  return (
    <RootDocument>
      <Outlet />
    </RootDocument>
  );
}

function RootDocument({ children }: { children: React.ReactNode }) {
  return (
    <html suppressHydrationWarning>
      <head>
        <HeadContent />
      </head>
      <body className="flex flex-col min-h-screen">
        <RootProvider>{children}</RootProvider>
        <Scripts />
      </body>
    </html>
  );
}

Done

You can start writing documents at content/docs:

content/docs/index.mdx
---
title: Hello World
---

I love Hanzo Docs
How is this guide?