特殊用途のページ
テーマは、theme.pagesDir を通じて独自のページを同梱できます。これらのテーマページはユーザーページと同様のルーティングルールで処理されますが、ルートが重複した場合は常にユーザー側のページが優先されます。
主な活用例:
- テーマ固有のランディングページ
- 専用のメニュー画面やインデックスページ
- リンク集やコンタクトページ
- テーマ標準の
/404フォールバックページ
テーマからページを提供する方法
theme/index.js でディレクトリを指定します。
export default () => ({
theme: {
root: '.',
pagesDir: './pages'
}
})
theme/pages/ 内の構成例:
pages/
index.mdx
menu.mdx
friends.mdx
contact.mdx
404.mdx
フロントマターによるレイアウトの切り替え
最も柔軟な方法は、フロントマターに layout プロパティを定義し、テンプレート内で条件分岐を行う手法です。
例: menu.mdx
---
title: Menu
layout: menu
hidden: true
---
# Menu
このページは専用のレイアウトでレンダリングされます。
テンプレートでの実装例:
const MenuLayout = ({ ctx, PageContent }) => (
<div class="menu-layout">
<h1>{ctx.page.title}</h1>
<PageContent />
</div>
)
const DocLayout = ({ ctx, PageContent }) => (
<div class="doc-layout">
<aside>{/* ナビゲーション */}</aside>
<main>
<PageContent />
</main>
</div>
)
export default function PageTemplate({ PageContent, ExtraHead, ctx }) {
const layout = ctx.page.frontmatter?.layout
return (
<>
<html>
<head>
<ExtraHead />
<title>{ctx.page.title || ctx.site.name}</title>
</head>
<body>
{layout === 'menu' ? (
<MenuLayout ctx={ctx} PageContent={PageContent} />
) : (
<DocLayout ctx={ctx} PageContent={PageContent} />
)}
</body>
</html>
</>
)
}
ルートパスによる条件分岐
特定のパスに対してルールを固定したい場合は、ルートパスによる判定も有効です。
const route = ctx.page.routePath
if (route === '/menu') { /* ... */ }
補足: ディレクトリのインデックスページの場合、routePath の末尾には / が付与されます(例: /guide/)。
インタラクティブなページの実装(フォームなど)
お問い合わせフォームなどの複雑なインタラクションが必要なページでは、ページ自体のレンダリングは通常通り行い、テーマ側の components/ に .client サフィックス付きのコンポーネントを用意して本文内で呼び出す構成が推奨されます。
代替案: .html ファイルによる実装
特殊用途のページは必ずしも MDX である必要はありません。テーマの pagesDir に直接 .html ファイルを配置することも可能です。
これらのファイルもビルドプロセスに含まれ、Vite による最適化と theme.template によるラップが適用されます。テンプレート側でファイル拡張子や特定のフロントマターを判定し、サイドバーやフッターを除去した独立したレイアウトを適用するのが一般的な手法です。
一般的な判定パターン:
- 拡張子判定:
ctx.page.filePath.endsWith('.html') - パス判定:
ctx.page.routePath === '/menu' - レイアウト指定:
ctx.page.frontmatter?.layout === 'landing'
パス解決に関する注意点
theme.sources で定義された URL や public/ 配下の静的ファイルは、ビルド時に自動的に解決されるため、通常は withBase() を使用する必要はありません。ただし、JavaScript 内でパスを動的に生成する場合の安全策として withBase('/...') を利用できます。 drum