はじめに
ライブラリやプロダクトのドキュメントサイト、どうやって作っていますか?「Next.jsで自作すると、サイドバーや検索、ダークモードまで全部自分で実装することになって大変」「かといって専用ツールを導入すると、Reactコンポーネントを自由に埋め込めなくてもどかしい」——そんなジレンマを抱えている方は多いのではないでしょうか。
そこで登場するのがNextraです。Markdownファイルを置くだけで、検索・サイドバー・ダークモード完備の美しいドキュメントサイトが立ち上がります。しかも中身は素のNext.jsなので、Reactの力をそのまま使えるのです。Nextra自身のドキュメントはもちろん、SWRやTurboなど有名プロジェクトのサイトでも採用されている実績あるフレームワークです。
Nextraとは
Nextraは、Next.jsとMDXをベースにした静的サイト生成フレームワークです。GitHubで約14,000スターを獲得しており、Vercelのエンジニアとして知られるShu Ding氏を中心に開発されています。最新のメジャーバージョンであるNextra 4では、Next.jsのApp Routerに全面対応し、React Server ComponentsやTurbopackといったモダンな仕組みの上で動作します。
主な特徴
- Markdown / MDXファースト -
.mdや.mdxファイルを置くだけでページになります。MDXならMarkdownの中にReactコンポーネントを直接埋め込めます - フルスタックなドキュメントテーマ - サイドバー、目次、パンくず、ダークモード、i18n対応までビルトイン。
nextra-theme-docsのほか、ブログ向けのnextra-theme-blogも用意されています - ゼロコンフィグの全文検索 - Pagefindによるビルド時インデックスで、サーバー不要の高速な全文検索が使えます
- 自動最適化 - Markdown内のリンクや画像はNext.jsの
Link/Imageコンポーネントへ自動変換され、レイアウトシフトのない快適なナビゲーションを実現します - Shikiによる構文ハイライト - VS Codeと同じエンジンでビルド時にハイライトするため、ランタイムの負荷がありません
インストール
Next.jsのプロジェクトに、Nextra本体とdocsテーマを追加します。
# npm
npm i next react react-dom nextra nextra-theme-docs
# pnpm
pnpm add next react react-dom nextra nextra-theme-docs
# yarn
yarn add next react react-dom nextra nextra-theme-docs
package.jsonには通常のNext.jsと同じスクリプトを設定します。
{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}
基本的な使い方
Nextra 4はApp Routerベースなので、最初に少しだけ足場を組みます。必要なファイルは4つです。
my-docs/
├── app/
│ ├── layout.jsx # ルートレイアウト
│ └── [[...mdxPath]]/
│ └── page.jsx # 全MDXページを受けるキャッチオールルート
├── content/ # ここにMarkdownを置いていく
│ ├── index.mdx
│ └── getting-started.mdx
├── mdx-components.js
└── next.config.mjs
1. next.config.mjs
Nextraのプラグインを噛ませるだけです。
import nextra from 'nextra'
const withNextra = nextra({
// ここにNextraのオプションを記述できます
})
export default withNextra({
// 通常のNext.js設定はこちら
})
2. app/layout.jsx
docsテーマのレイアウトコンポーネントを組み込みます。ナビバーのロゴやフッターもここで指定します。
import { Footer, Layout, Navbar } from 'nextra-theme-docs'
import { Head } from 'nextra/components'
import { getPageMap } from 'nextra/page-map'
import 'nextra-theme-docs/style.css'
export const metadata = {
title: 'My Docs'
}
export default async function RootLayout({ children }) {
return (
<html lang="ja" dir="ltr" suppressHydrationWarning>
<Head />
<body>
<Layout
navbar={<Navbar logo={<b>My Docs</b>} />}
pageMap={await getPageMap()}
footer={<Footer>MIT © My Project.</Footer>}
>
{children}
</Layout>
</body>
</html>
)
}
3. mdx-components.js
MDXの各要素をどのコンポーネントで描画するかを定義します。テーマのデフォルトをそのまま使いつつ、必要に応じて上書きできます。
import { useMDXComponents as getDocsMDXComponents } from 'nextra-theme-docs'
const docsComponents = getDocsMDXComponents()
export const useMDXComponents = components => ({
...docsComponents,
...components
})
4. app/[[...mdxPath]]/page.jsx
contentディレクトリのMDXファイルをページとして配信するキャッチオールルートです。ここは公式ドキュメントのコードをそのまま使えます。
import { generateStaticParamsFor, importPage } from 'nextra/pages'
import { useMDXComponents as getMDXComponents } from '../../mdx-components'
export const generateStaticParams = generateStaticParamsFor('mdxPath')
export async function generateMetadata(props) {
const params = await props.params
const { metadata } = await importPage(params.mdxPath)
return metadata
}
const Wrapper = getMDXComponents().wrapper
export default async function Page(props) {
const params = await props.params
const { default: MDXContent, toc, metadata } = await importPage(
params.mdxPath
)
return (
<Wrapper toc={toc} metadata={metadata}>
<MDXContent {...props} params={params} />
</Wrapper>
)
}
足場ができたら、あとはcontent/にMarkdownを置いていくだけです。
# はじめに
私のプロジェクトへようこそ!
## インストール
以下のコマンドでインストールできます。
npm run devで開発サーバーを起動すると、サイドバー付きのドキュメントサイトが表示されます。ファイルを追加すればページとサイドバー項目が自動で増えていく——この手軽さがNextraの真骨頂です。
サイドバーの並び順を制御する
ディレクトリに_meta.jsを置くと、サイドバーの並び順や表示名を制御できます。
export default {
index: 'はじめに',
'getting-started': 'セットアップ',
api: 'APIリファレンス'
}
実践的なユースケース
ビルトインコンポーネントでドキュメントをリッチにする
Nextraには、ドキュメントでよく使うUIコンポーネントが最初から揃っています。MDXファイル内でimportして使うだけです。
import { Callout, Steps, Tabs } from 'nextra/components'
<Callout type="warning">
この機能はv2.0以降でのみ利用できます。
</Callout>
<Steps>
### パッケージをインストールする
### 設定ファイルを作成する
### 開発サーバーを起動する
</Steps>
<Tabs items={['npm', 'pnpm', 'yarn']}>
<Tabs.Tab>`npm i my-package`</Tabs.Tab>
<Tabs.Tab>`pnpm add my-package`</Tabs.Tab>
<Tabs.Tab>`yarn add my-package`</Tabs.Tab>
</Tabs>
注意書きのCallout、手順を示すSteps、パッケージマネージャー別のコマンドを切り替えるTabsなど、「ドキュメントあるある」がコンポーネント一発で書けます。
全文検索を有効にする
Nextra 4の検索はPagefindが担います。ビルド後にインデックスを生成するスクリプトを追加し、ナビバーに検索ボックスを組み込みます。
npm i -D pagefind
{
"scripts": {
"build": "next build",
"postbuild": "pagefind --site .next/server/app --output-path public/_pagefind"
}
}
import { Layout, Navbar } from 'nextra-theme-docs'
import { Search } from 'nextra/components'
// Layoutに検索コンポーネントを渡します
<Layout
navbar={<Navbar logo={<b>My Docs</b>} />}
search={<Search placeholder="ドキュメントを検索..." />}
pageMap={await getPageMap()}
>
{children}
</Layout>
検索サーバーもSaaSも不要で、静的ホスティングのまま日本語も検索できるのは大きな魅力です。
MDXでインタラクティブなドキュメントを作る
MDXの真価は、ドキュメント内にライブデモを埋め込めることです。例えばコンポーネントライブラリのドキュメントなら、説明のすぐ下に動くサンプルを置けます。
import { MyButton } from '../components/my-button'
## ボタンコンポーネント
`variant`プロパティで見た目を切り替えられます。実際に触ってみてください。
<MyButton variant="primary">プライマリボタン</MyButton>
<MyButton variant="outline">アウトラインボタン</MyButton>
静的な説明文と動くデモが同じページに共存する——読み手にとってこれ以上わかりやすいドキュメントはありません。
まとめ
Nextraは「Markdownを書くことに集中したいが、Next.jsの柔軟性も手放したくない」という開発者にぴったりのフレームワークです。最後にポイントを振り返ります。
- Markdown / MDXファイルを
content/に置くだけでページとサイドバーが自動生成される - 検索・ダークモード・目次・i18nなどドキュメントサイトに必要な機能がビルトイン
- Nextra 4はApp Router・RSC・Turbopackに対応したモダンな設計
CalloutやTabsなどのビルトインコンポーネントで表現力の高いドキュメントが書ける- 中身は素のNext.jsなので、独自ページやAPIルートの追加も自由自在
最初の足場さえ組んでしまえば、あとはMarkdownを書き足していくだけです。READMEに収まりきらなくなったプロジェクトがあれば、まずはcontent/index.mdxを1枚置くところから始めてみてください。詳細は公式ドキュメントで確認できます。