Nextraは、Next.jsのプラグインとして動き、MarkdownとMDXの原稿からドキュメントサイトやブログを組み立てるオープンソースのフレームワークです。2026年11月1日にnpm registryで確認したnextraのlatestは4.6.1(2025年12月4日公開)で、4.x系はApp Router専用になりました。日本語で読める解説はNextra 2〜3時代のpages前提の手順が多く、そのままでは今の版で動きません。この記事では、4.6系での新規作成の手順、Pagefindによる日本語検索、既存のNext.jsサイトの/docs配下に同居させる構成、npmに出ていない修正の扱い、DocusaurusやVitePressとの選び分けまでを、公式ドキュメントとGitHubのソースをもとに整理します。
まとめ:Nextraを選んでよい条件と4.6系で既存のNext.jsサイトに足す結論
結論から書きます。自社の製品サイトや管理画面がすでにNext.jsで動いていて、その同じリポジトリに説明書を足したい。この条件ならNextraが第一候補です。説明書のためだけに別の言語や別のビルド系を持ち込まずに済みます。
見送るのは、製品の版ごとに説明書を出し分けたい場合と、Next.jsを使っていない組織が単体のドキュメントサイトを作る場合です。前者は版管理を標準で持つDocusaurus、後者は設定の少ないVitePressのほうが早く立ち上がります。
版の扱いにも注意が要ります。npmで配布されている最新は4.6.1で、GitHubのmainには4.6.5までの修正が積まれたまま公開されていません。basePathを使うとサイト内検索が動かない不具合の修正もそこに含まれるため、4.6.1ではbasePathを使わず、NextraのcontentDirBasePathでパスを分ける構成を選びます。
Nextraの定義|Next.jsのプラグインとして動くMDXのサイト生成フレームワーク
まず、NextraがNext.jsの何を受け持つのかを押さえます。
next.configに組み込むプラグイン方式とdocs・blogの2つの公式テーマ
公式ドキュメントの冒頭は、NextraをNext.jsの上に載るフレームワークと説明しています。next.config.mjsでnextra()の関数を通すだけで、Next.jsのアプリがMarkdownとMDXのページを扱えるようになる仕組みです。ルーティングや画像、メタデータはNext.jsの機能をそのまま使います。
見た目は、ドキュメント用のnextra-theme-docsとブログ用のnextra-theme-blogの2つの公式テーマから選びます。ドキュメントテーマには上部ナビゲーション、サイドバー、目次、検索窓が入っています。公式サイトのGitHubリポジトリはMITライセンスで、2026年11月1日時点のスター数は約13,900でした。土台のNext.jsとApp Routerの仕組みはNext.jsの16系App Routerで最小アプリを動かす手順で整理しています。
Nextra 4でApp Router専用になった変更と日本語の解説記事の版ずれ
2025年1月13日に出たNextra 4の公式移行ガイドで、構成が大きく変わりました。Pages Routerの対応が外れ、theme.config.jsxは廃止され、設定はapp/layout.jsxでLayoutやNavbarに渡すpropsへ移っています。検索エンジンもFlexSearchからRust製のPagefindに替わりました。同じガイドは、Next.js 15.1.3での計測としてドキュメントテーマの共通JavaScriptが168kBから106kBに減ったと示しています。
検索で上位に出る日本語の解説を5本確かめたところ、4本は2021〜2023年に書かれたpages/とtheme.config前提の手順でした。公式のよくある質問も「Pages Routerで使えるのはNextra 1〜3だけ」と明記しています。記事の手順を試す前に、theme.configという語が出てくるかを見れば、古い版の手順かどうかを見分ける手掛かりになるためです。App Routerのファイル規約はApp Routerのファイル規約とPages Routerとの違いが参考になります。
npm latestの4.6.1とGitHubのmainにある4.6.5の差と版の確かめ方
Nextraを本番で使う前に、配布されている版と開発中の版の差を把握しておきます。
npm registryとCHANGELOGで見えるリリース間隔と未公開の修正
2026年11月1日時点で、npmのnextraとnextra-theme-docsのlatestはどちらも4.6.1です。GitHubのリリース一覧も4.6.1が最新で、4.5.1(2025年9月27日)、4.6.0(10月2日)、4.6.1(12月4日)と続いた後、11か月近く新しい版が出ていません。
一方、mainブランチのpackages/nextra/package.jsonは4.6.5まで上がっています。CHANGELOGには、4.6.2でbasePath配下の検索の修正、4.6.5でgit worktree内のビルドが遅くなる不具合の修正が載っています。後者は、110ファイルのサイトでビルドが約1.8秒から約176秒に延びた不具合として記録されている事例です。CIでworktreeを使う構成なら、ビルド時間の急増に心当たりがないかを確かめます。
basePath配下でPagefind検索が動かない不具合と4.6.1での避け方
CHANGELOGの4.6.2の項によると、Next.jsのbasePath: '/docs'のようにサブパスへ置いたとき、Pagefindが索引ファイルを/から読みに行き、検索が動きませんでした。修正はmainに入っていますが、npmの4.6.1には含まれていません。
4.6.1で避ける方法は、アプリ全体をずらすbasePathを使わず、NextraのcontentDirBasePathで原稿の配信先だけを/docsに寄せることです。既存サイトに同居させる構成(第6章)もこの形で組みます。新しい版がnpmに出たら、CHANGELOGの4.6.2以降を読んでから上げます。
Next.js 16とnextra-theme-docsで新規ドキュメントサイトを作る手順
ここからは手を動かす部分です。例はドキュメントテーマのGet Startedと、リポジトリ内の公式example(examples/docs)に沿って書きます。npmのpeerDependenciesはnextが14以上、reactが18以上で、Node.jsは18以上が条件です。
依存の導入とnext.config.mjs・mdx-components.jsの用意
パッケージを入れ、package.jsonのスクリプト、next.config.mjs、mdx-components.jsの3つを用意します。mdx-componentsファイルの説明は、このファイルを必須としています。
# 依存パッケージ(Next.jsが入っている既存プロジェクトなら後ろの2つだけ)
npm i next react react-dom nextra nextra-theme-docs
npm i -D pagefind
// next.config.mjs
import nextra from 'nextra'
const withNextra = nextra({
// content/ 配下の原稿を /docs 以下で配信する
contentDirBasePath: '/docs'
})
export default withNextra({
reactStrictMode: true
})
// mdx-components.js(プロジェクト直下か src/ に置く)
import { useMDXComponents as getDocsMDXComponents } from 'nextra-theme-docs'
const docsComponents = getDocsMDXComponents()
export const useMDXComponents = components => ({
...docsComponents,
...components
})
Next.js 15.3以降でnext-mdx-import-source-fileが見つからないというエラーが出たら、同じ説明ページのとおりturbopack.resolveAliasにmdx-componentsの実際のパスを書きます。
contentディレクトリとcatch-allルートで既存のMarkdownを並べる構成
原稿の置き方は2通りあります。app/の中にpage.mdxを置く方法と、contentディレクトリにinstall.mdxのような普通の名前で並べる方法です。既存のMarkdownを持ち込むなら後者が向いています。content/への入口として、次のcatch-allルートを1つだけ置きます。
// app/docs/[[...mdxPath]]/page.jsx(公式exampleと同じ内容)
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, sourceCode } = await importPage(params.mdxPath)
return (
<Wrapper toc={toc} metadata={metadata} sourceCode={sourceCode}>
<MDXContent {...props} params={params} />
</Wrapper>
)
}
contentDirBasePathを/docsにしたので、ルートもapp/docs/の下に置きます。sourceCodeを渡しているのは、4.4.0で入った「ページの内容をコピーする」ボタンをcontent/の構成で動かすためで、CHANGELOGに必須と書かれています。
_meta.jsでサイドバーの並び順と日本語の表示名を指定する書き方
サイドバーの順序と表示名は、各フォルダに置く_meta.jsで決めます。何も書かなければファイル名順で、Nextra 4でサイドバーの題名に使われるのは、ページの最初のh1です。日本語の表示名を付けるなら、次のように書きます。
// content/_meta.js(content/ に同じ名前の .mdx がある前提)
export default {
index: 'はじめに',
install: 'インストール手順',
api: 'APIリファレンス',
changelog: {
title: '変更履歴',
theme: { copyPage: false }
}
}
移行ガイドによると、4.xの_metaはサーバー側で読まれ、'use client'は要りません。中身はzodで検証され、3系で使えたnewWindowやtheme.layout: 'raw'は4.xで削除された項目です。古い記事から設定を写す場合は、この2つを消してから試します。
Pagefindで日本語の全文検索を動かすpostbuild設定と静的書き出しの差
検索窓はテーマに入っていますが、索引を作る手順は自分で足します。ここを飛ばすと、検索窓だけがあって何も見つからないサイトになります。
postbuildで索引を作る設定とhtmlのlang属性で決まる日本語の分割
検索の設定ガイドによると、Pagefindはビルド後のHTMLから索引を作ります。package.jsonにpostbuildを足し、生成物の_pagefind/は.gitignoreに入れます。
{
"scripts": {
"dev": "next",
"build": "next build",
"postbuild": "pagefind --site .next/server/app --output-path public/_pagefind",
"start": "next start"
}
}
日本語サイトで気を付けるのはhtml要素のlang属性です。Pagefindの多言語ガイドは、索引を作るときにlang属性で言語を判定し、言語ごとに別の索引を作ると書いています。空白で区切られない日本語の分割はextended版だけの機能ですが、導入ガイドによるとnpm経由で常に入るのはextended版です。公式のレイアウト例はlang="en"なので、写したままにせずlang="ja"へ書き換えます。
output exportで静的に書き出すときの出力先と自動振り分けの制約
Next.jsのサーバーを置かず、ファイルだけをS3やGitHub Pagesに置く場合は、静的書き出しのガイドのとおりoutput: 'export'とimages.unoptimized: trueを指定します。postbuildの出力先もout/_pagefindに変えます。
// next.config.mjs(静的書き出しの場合)
import nextra from 'nextra'
const withNextra = nextra({ contentDirBasePath: '/docs' })
export default withNextra({
output: 'export',
images: { unoptimized: true } // これが無いと書き出せない
})
// package.json の postbuild も出力先を out 側へ変える
// "postbuild": "pagefind --site .next/server/app --output-path out/_pagefind"
代わりに使えなくなる機能への注意も必要です。多言語化のガイドは、ブラウザの言語で振り分けるnextra/localesのproxyが、静的書き出しでは動かないと警告しています。多言語で自動の振り分けが要るなら、Next.jsのサーバーで動かす配信先を選びます。
Turbopackで関数のremarkプラグインを渡せない制約と–webpack指定
Turbopackとの併用ガイドによると、Turbopackではnextra()にJSONで表せる値しか渡せません。mdxOptionsのremarkPluginsやrehypePluginsは関数なので、渡すとdoes not have serializable optionsのエラーで止まります。
Next.js 16ではnext buildもTurbopackが既定です。公式exampleのexamples/docsは、ビルドのスクリプトをnext build --webpackと明示していました。独自のremarkプラグインを使うサイトは、ビルドだけwebpackに固定します。Turbopack側の既定の変化はNext.js 16で既定になったTurbopackの設定と移行判断で扱っています。
既存のNext.jsサイトの/docs配下にNextraを同居させる構成と注意点
Nextraを選ぶ理由が「製品サイトがNext.jsだから」なら、新しいサイトを作るより、動いている製品サイトに説明書を足す形になります。公式のレイアウト例はルートのapp/layout.jsxでサイト全体をNextraのテーマで包むため、そのままでは既存のページまでテーマの見た目に変わります。
Route Groupsで既存サイトとドキュメントのルートレイアウトを分ける
Next.jsのRoute Groupsは、括弧付きのフォルダ名がURLに入らない規約で、用途の1つに複数のルートレイアウトを挙げています。これを使い、既存サイトとドキュメントでhtmlとbodyを出すレイアウトを分けます。
app/
(site)/
layout.jsx ← 既存サイトのルートレイアウト(Nextraを読み込まない)
page.jsx ← トップページ(/)
pricing/page.jsx ← 既存のページ群
(docs)/
layout.jsx ← ドキュメント用のルートレイアウト
docs/[[...mdxPath]]/page.jsx
content/
_meta.js
index.mdx ← /docs
install.mdx ← /docs/install
mdx-components.js
next.config.mjs ← contentDirBasePath: '/docs'
既存のapp/layout.jsxは(site)/layout.jsxへ移します。同じページは、最上位のlayout.jsを置かない場合はトップページ(/)をどちらかのグループに入れること、別グループ同士で同じURLを作らないことを求めています。catch-allルートが1段深くなるので、mdx-componentsのimportに指定するパスは../../../../mdx-componentsです。
getPageMap(‘/docs’)で読み込む範囲を絞るドキュメント側のレイアウト
ドキュメント側のレイアウトでは、サイドバーに出す範囲をgetPageMapの引数で絞ります。ソースのpackages/nextra/src/server/page-map/get.tsは、引数にルートを渡すとその配下だけを返し、例としてgetPageMap('/blog')を挙げています。
// app/(docs)/layout.jsx
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: { template: '%s | 製品ドキュメント' }
}
export default async function DocsLayout({ children }) {
return (
<html lang="ja" dir="ltr" suppressHydrationWarning>
<Head />
<body>
<Layout
navbar={<Navbar logo={<b>製品ドキュメント</b>} />}
footer={<Footer>© Example Inc.</Footer>}
pageMap={await getPageMap('/docs')}
docsRepositoryBase="https://github.com/example/product/tree/main"
>
{children}
</Layout>
</body>
</html>
)
}
nextra-theme-docs/style.cssをこのレイアウトだけで読むことで、既存サイトのCSSとの衝突を/docsの内側に閉じ込めます。この構成は公式exampleとNext.jsの規約を組み合わせたものなので、取り込む前にnext buildとpostbuildを通し、既存ページの見た目と検索の動作を確かめてから本番へ出します。
ルートレイアウトをまたぐ遷移でページ全体が再読み込みになる制約
Route Groupsの説明は、ルートレイアウトが異なるページ間の移動はページ全体の再読み込みになると明記しています。製品サイトのヘッダーから/docsへ移るたびに、クライアント側の遷移ではなくページ全体の読み直しが起きる仕組みです。説明書は入口から入った後、ドキュメント内で行き来する使われ方が中心なので、多くの製品サイトでは許容できます。
許容できないのは、製品の画面と説明書を頻繁に往復させる管理画面のような使い方です。その場合は同居をやめ、docs.example.comのようなサブドメインに独立したNextraのアプリを立てます。リポジトリを分けると依存の更新も独立し、Nextraの版上げで製品側のビルドが止まる事態も避けられます。
Docusaurus・VitePressとの違いと受託開発で採用してよい条件・見送る場面
Markdownから説明書を作るツールは複数あります。差は機能の数より、土台の技術と、版の出し分けへの対応に出ます。
Nextra・Docusaurus・VitePressの土台・版の出し分け・検索方式比較
| ツール | 土台 | 版の出し分け | 標準の検索 |
|---|---|---|---|
| Nextra 4.6系 | Next.js(App Router) | 公式ガイドに章が無い | Pagefind(postbuildで索引) |
| Docusaurus | React・独自のビルド | 標準機能で対応 | 別途の導入が必要 |
| VitePress | Vue 3・Vite | 標準機能には無い | ローカル検索あり |
Nextraの強みは、既存のNext.jsアプリのルーティングやコンポーネントをそのまま説明書の中で使える点です。Docusaurusの版管理と翻訳の仕組みはDocusaurusの構築手順とバージョン管理・多言語・検索の設定で、VitePressはVitePressの作り方と1.6系・2.0版の選び方で扱っています。API仕様書が中心で、ホスティングまで外に任せたいならMintlifyでAPIドキュメントを公開する手順と料金も候補になります。
Nextraを採用してよい条件と別のツールを選ぶべき3つの場面
採用してよいのは、製品やサービスのフロントエンドがすでにNext.jsで、説明書を同じリポジトリで保守したい場合です。原稿の中で自社のReactコンポーネントを動かせるので、APIの試し打ち画面や料金の計算表を説明書に埋め込めます。
別のツールを選ぶ場面は3つあります。第一に、利用者ごとに異なる版の説明書を読ませる製品で、版の切り出しを自作する手間がかかります。第二に、Next.jsを社内で保守していない組織です。説明書のためだけにNext.jsのメジャー更新を追い続けることになり、VitePressやMkDocsのほうが軽く済みます。第三に、npmの公開が止まっている間に直ってほしい不具合を抱える案件です。4.6.1の時点では、basePathが必須の配信構成ならmainからのビルドか別ツールかを先に決めます。
ドキュメントサイトと製品サイトの構築を外部に委託する際の進め方
Nextraのサイトを外部に作らせる場合は、着手前に3点を決めておくと引き継ぎで揉めません。既存サイトに同居させるかサブドメインに分けるか、Next.jsのサーバーで配信するか静的に書き出すか、多言語で自動の振り分けが要るかです。どれも後から変えると、URLの構造か配信の費用が変わります。
説明書に加えて技術ブログや製品のお知らせも同じサイトで出す、デザインを製品サイトと揃える、といった要件が重なると、テーマの差し替えだけでは収まりません。当社では記事サイトや情報発信サイトの構築をオウンドメディアサイト制作として受託しており、ツールの選定から公開後の運用設計まで含めて相談いただけます。
よくある質問
Nextraの導入検討で挙がりやすい論点を、公式ドキュメントとnpm registryの記録をもとに整理します。
NextraはPages RouterのNext.jsプロジェクトでも使えますか?
4.x系では使えません。公式のよくある質問は、Pages Routerに対応するのはNextra 1〜3だけで、Nextra 4はApp Router専用だと書いています。Pages Routerのまま使うなら3系に留まることになります。移行するなら、pagesフォルダをcontentに改名してcatch-allルートを置く方法が、移行ガイドで案内されている最小の手順です。
Nextraは無料で商用利用できますか?
できます。npm registryに記録されたnextraとnextra-theme-docsのライセンスはMITで、商用サイトでの利用や改変に制約はありません。費用が発生しうるのはツールの外側で、Next.jsのサーバーを動かすホスティングの料金が該当します。静的に書き出してS3やGitHub Pagesに置けば、配信の費用は小さく抑えられます。
NextraとDocusaurusはどちらを選ぶべきですか?
製品の版ごとに説明書を出し分けるならDocusaurusです。版の切り出しを標準機能で持っており、Nextraの公式ガイドにはその章がありません。版を1つに保つ説明書で、製品がすでにNext.jsで動いているならNextraを選びます。チームがReactを書けるかどうかは両者で同じ条件なので、決め手は版管理の要否と、既存のNext.jsアプリに同居させたいかどうかです。
Nextraの検索で日本語がうまく見つからないのはなぜですか?
まずhtml要素のlang属性を確かめます。Pagefindはlang属性で言語を判定し、日本語の単語の分割はその判定に従って行われます。公式のレイアウト例を写してlang="en"のままだと、日本語として扱われません。次に、postbuildが実行されて_pagefind/がpublicかoutに出力されているかを見ます。開発サーバーでは索引が作られない点にも注意します。
Nextraの開発は止まっていませんか?
2026年11月1日時点で、npmの最新は2025年12月4日の4.6.1です。ただしGitHubのmainでは2026年6月まで修正が入り、package.jsonは4.6.5まで上がっていました。2026年6月にはnpmへの公開手順をTrusted Publishingへ切り替える変更も入っています。公開が止まっている理由は公式に示されていないため、採用時はリリース一覧を定期的に確かめ、直ってほしい不具合がmainにしか無いかを把握しておきます。