# Fumadocs (Framework Mode, Astro): Sanity
URL: /ja/docs/astro/integrations/content/sanity
Source: https://raw.githubusercontent.com/fuma-nama/fumadocs/refs/heads/main/apps/docs/content/docs/(framework)/[framework]/integrations/content/sanity.ja.mdx

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

## 概要 [#overview]

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

> [Sanity のサンプル](https://github.com/fuma-nama/fumadocs-sanity)は GitHub で公開しています。

## セットアップ [#setup]

このガイドでは、[Sanity](https://sanity.io/docs/getting-started) の公式ドキュメントに従って、すでに設定が完了していることを前提としています。

### データ型 [step] [#data-types]

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

```npm
npx @fumadocs/cli add sanity/base
```

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

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

```ts tab="schemaTypes/index.ts"
import { docsType, blockContent, callout, card, cards } from '@/lib/sanity/base';

// [!code ++]
export const schemaTypes = [blockContent, callout, card, cards, docsType];
```

```tsx tab="components/sanity.ts"
import {
  PortableText,
  type PortableTextProps,
  type PortableTextReactComponents,
} from '@portabletext/react';
// インストールしたコンポーネント
import { baseBlocks, baseComponents, baseMarks } from './base';

const components: Partial<PortableTextReactComponents> = {
  block: {
    // [!code ++]
    ...baseBlocks,
  },
  marks: {
    // [!code ++]
    ...baseMarks,
  },
  types: {
    // [!code ++]
    ...baseComponents,
  },
};

export function CustomPortableText(props: PortableTextProps) {
  return <PortableText {...props} components={{ ...components, ...props.components }} />;
}
```

### コンテンツローダー [step] [#content-loader]

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

```npm
npm i @fumadocs/sanity
```

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

```ts title="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()` 関数を使ってページをレンダリングします:

```astro tab="src/pages/docs/[...slug].astro"
---
import type { GetStaticPaths, InferGetStaticPropsType } from 'astro';
import Layout from '@/layouts/Layout.astro';
import { Docs } from '@/components/docs';
import { getSource } from '@/lib/source';

export const prerender = true;

export const getStaticPaths = (async () => {
  const source = await getSource();
  return source.getPages().map((page) => ({
    params: { slug: decodeURI(page.slugs.join('/')) || undefined },
    props: { page },
  }));
}) satisfies GetStaticPaths;

type Props = InferGetStaticPropsType<typeof getStaticPaths>;

const { page } = Astro.props;
const source = await getSource();
const pageTree = await source.serializePageTree(source.getPageTree());
const { title, description, _toc, body } = await page.data.load();
---

<Layout title={page.data.title}>
  <Docs
    client:load
    pathname={Astro.url.pathname}
    params={Astro.params}
    tree={pageTree}
    title={title}
    description={description}
    toc={_toc}
    body={body}
  />
</Layout>
```

```tsx tab="src/components/docs.tsx"
import { type SerializedPageTree, 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 type { PortableTextBlock, PortableTextProps } from '@portabletext/react';
import { Provider, type ProviderProps } from '@/components/provider';
import { CustomPortableText } from '@/components/sanity';

export interface DocsProps extends ProviderProps {
  tree: SerializedPageTree;
  title?: string;
  description?: string;
  toc: PortableTextBlock[];
  body?: PortableTextProps['value'];
}

export function Docs({ tree, title, description, toc, body, ...props }: DocsProps) {
  const data = useFumadocsLoader({ tree });

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

### 完了 [step] [#done]

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