コンテンツへスキップ
Fumadocs

Sanity

Sanity 向けの公式インテグレーションです。

概要

Fumadocs は、Sanity CMS のセットアップを簡単にする公式インテグレーションを提供しています。

Sanity のサンプルは GitHub で公開しています。

セットアップ

このガイドでは、Sanity の公式ドキュメントに従って、すでに設定が完了していることを前提としています。

データ型

次のコマンドを実行して、コンテンツタイプを初期化します。

npx @fumadocs/cli add sanity/base

または、npx @fumadocs/cli add を実行して、ほかの Sanity プリセットを一覧から選んでインストールすることもできます。

インストールした型を登録します。

import { docsType, blockContent, callout, card, cards } from '@/lib/sanity/base';

export const schemaTypes = [blockContent, callout, card, cards, docsType];

コンテンツローダー

インテグレーションをインストールします。

npm i @fumadocs/sanity

Sanity クライアントでソースを作成します:

lib/source.ts
import { dynamicLoader } from 'fumadocs-core/source';
import { createSanitySource } from '@fumadocs/sanity';
// Sanity クライアント
import { client } from '@/sanity/lib/client';
// 生成された型
import type { Docs } from '@/sanity/types';

const source = dynamicLoader(
  createSanitySource<Docs>({
    client,
    docType: 'docs',
  }),
  {
    baseUrl: '/docs',
  },
);

export async function getSource() {
  return source.get();
}

次に、getSource() 関数を使ってページをレンダリングします:

src/routes/docs/$.tsx
import { createFileRoute, notFound } from '@tanstack/react-router';
import { createServerFn } from '@tanstack/react-start';
import { useFumadocsLoader } from 'fumadocs-core/source/client';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
import { renderToc } from '@fumadocs/sanity/client';
import { getSource } from '@/lib/source';
import { CustomPortableText } from '@/components/sanity';
import type { PortableTextBlock } from '@portabletext/react';

// サーバー関数の戻り値に対する型レベルのチェックでは Portable Text を検証できないため、
// シリアライズ可能な型として登録します(`@tanstack/router-core` が解決できない場合はインストールしてください)
declare module '@tanstack/router-core' {
  interface SerializableExtensions {
    portableTextBlock: PortableTextBlock;
  }
}

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

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

    const { title, description, _toc, body } = await page.data.load();
    return {
      title,
      description,
      toc: _toc,
      body,
      pageTree: await source.serializePageTree(source.getPageTree()),
    };
  });

function Page() {
  const { title, description, toc, body, pageTree } = useFumadocsLoader(Route.useLoaderData());

  return (
    <DocsLayout tree={pageTree}>
      <DocsPage toc={renderToc({ toc, render: (block) => <CustomPortableText value={block} /> })}>
        <DocsTitle>{title}</DocsTitle>
        <DocsDescription>{description}</DocsDescription>
        <DocsBody>
          <CustomPortableText value={body!} />
        </DocsBody>
      </DocsPage>
    </DocsLayout>
  );
}

完了

Studio エディターで docs タイプのドキュメントを作成すると、docs ルートに表示されるようになります。

How is this guide?

最終更新日