Keystatic (GitHub storage) 導入・運用ガイド
このドキュメントは、Next.js プロジェクトにおける Keystatic の GitHub Storage モードを使用した導入、設定、および運用に関する標準ガイドラインです。
1. 導入目的と全体像
目的: Headless CMS を別途契約することなく、管理画面からコンテンツを更新し、すべての変更を GitHub 上のコミットとして保存・管理する(Git-based CMS)。
アーキテクチャ概要
- 管理画面 UI (`/keystatic`): クライアントサイドで動作するエディタ。
- API ルート (`/api/keystatic`): GitHub との認証 (OAuth) およびデータのコミット処理を担当。
- データ保存先: リポジトリ内の `content/` ディレクトリなどに Markdown/JSON/YAML として保存。
2. 基本セットアップ
以下のパッケージとディレクトリ構成を基本とします。
依存パッケージ
npm install @keystatic/core @keystatic/next
必須ファイル構成 (App Router)
| パス | 役割 |
|---|---|
keystatic.config.ts |
Keystatic の設定ファイル(スキーマ定義、保存先設定) |
app/keystatic/[[...params]]/page.tsx |
管理画面のUIコンポーネントを描画するルート |
app/api/keystatic/[[...params]]/route.ts |
GitHub認証およびAPI処理を行うルート |
3. GitHub storage の設定
keystatic.config.ts にて、ストレージモードを GitHub に設定します。
NEXT_PUBLIC_ プレフィックスが付いた環境変数を使用してください。
// keystatic.config.ts
import { config, fields, collection } from '@keystatic/core';
export default config({
storage: {
kind: 'github',
// クライアント側でも参照できるよう NEXT_PUBLIC_ をつける
repo: process.env.NEXT_PUBLIC_KEYSTATIC_GITHUB_REPO as `${string}/${string}`,
},
// ... collections settings
});
4. GitHub App の作成と設定
Keystatic がリポジトリを操作するために、GitHub App を作成してインストールする必要があります。
認証フロー
- ユーザーが
/keystaticにアクセス - GitHub へリダイレクトされ認証
- GitHub が
/api/keystatic/github/oauth/callbackへコード付きで戻す
GitHub App 設定のポイント
- Homepage URL: 本番のトップページ URL (例:
https://my-site.com) - Callback URL: 以下の2つを必ず登録する(改行区切り)
http://localhost:3000/api/keystatic/github/oauth/callback(ローカル開発用)https://my-site.com/api/keystatic/github/oauth/callback(本番用)
- Permissions:
- Contents: Read and write
- Metadata: Read-only
注意: 作成後、対象のリポジトリに対してこの App を「Install」しないとアクセスできません。
5. 環境変数(一般形)
.env.local および本番環境(Vercel 等)に以下の変数を設定します。
| 変数名 | 公開範囲 | 説明 |
|---|---|---|
NEXT_PUBLIC_KEYSTATIC_GITHUB_REPO |
公開 | owner/repo-name 形式。設定ファイルで参照。 |
NEXT_PUBLIC_KEYSTATIC_GITHUB_APP_SLUG |
公開 | GitHub App のスラッグ(ID名)。 |
KEYSTATIC_GITHUB_CLIENT_ID |
非公開 | GitHub App の Client ID。サーバー側のみで使用。 |
KEYSTATIC_GITHUB_CLIENT_SECRET |
非公開 | GitHub App の Client Secret。絶対に公開しないこと。 |
KEYSTATIC_SECRET |
非公開 | セッション暗号化用。ランダムな32文字以上の文字列。 |
6. コンテンツ読み込み
フロントエンド(/news 等)で Keystatic 管理データを表示する場合、サーバーコンポーネントで読み込むのが基本です。
// app/news/page.tsx
import { createReader } from '@keystatic/core/reader';
import keystaticConfig from '@/keystatic.config';
const reader = createReader(process.cwd(), keystaticConfig);
export default async function NewsPage() {
// スラグ一覧を取得
const slugs = await reader.collections.news.list();
// 各記事の詳細を取得
const newsList = await Promise.all(
slugs.map(slug => reader.collections.news.read(slug))
);
return (
// ...レンダリング処理
);
}
7. 本番で記事が反映されない時の対策
Vercel などでのデプロイ時、ソースコードとして import されていない content/ ディレクトリ内のファイルは、ビルドのトレース対象外となり、本番環境に含まれないことがあります。
対策: outputFileTracingIncludes
next.config.mjs にて、コンテンツディレクトリを明示的に含める設定を行います。
// next.config.mjs
const nextConfig = {
experimental: {
// どのルートでデータが必要か指定(ここでは全ルート対象の例、または /news など特定も可)
outputFileTracingIncludes: {
'/**': ['./content/**/*'],
},
},
};
export default nextConfig;
8. UI/レイアウト上の注意
Keystatic の管理画面(/keystatic)は、サイト共通のヘッダーやフッター、グローバル CSS の影響を受けるとレイアウト崩れや動作不良を起こす可能性があります。
- 推奨:
app/layout.tsx(Root Layout) とは別に、Keystatic 専用のシンプルなレイアウト、または Root Layout 内でパスによる条件分岐を行い、管理画面には余計なスタイルを適用しないようにします。 - Keystatic 提供の
Keystaticコンポーネントは独自の HTML 構造を持つため、<html>タグや<body>タグを二重に生成しないよう注意してください。
9. よくあるエラーと原因
redirect_uri is not associated with this application
原因: GitHub App の設定画面で、「Callback URL」にアクセス中の URL(例: 本番ドメイン)が含まれていません。
対策: GitHub App の設定を修正し、本番URLを追加してください。
Repo not found / 404 Error
原因:
- 環境変数の
repo値が間違っている。 - GitHub App が作成されたが、対象のリポジトリに「Install」されていない。
ビルド時の型エラー
原因: keystatic.config.ts 内で process.env... をそのまま渡すと string | undefined になるため。
対策: as `${string}/${string}` のようにキャストするか、変数の存在チェックを行ってください。
10. 運用フロー(推奨)
- 記事作成: 管理画面 (
/keystatic) で記事を書き、保存・公開する。 - 自動コミット: Keystatic が裏側で GitHub にコミット&プッシュを行う。
- CI/CD 起動: GitHub へのプッシュを検知して Vercel 等がビルドを開始。
- 本番反映: 数分後に本番サイトが更新される。
※ 反映されない場合は、ビルドログを確認し、セクション 7 の「トレース設定」を見直してください。
補足: Git-backed CMS の運用イメージ
- ローカル編集 → commit/push → CI/CDで本番反映(開発者向けに一般的)
- /keystatic 管理画面 → GitHub Appがcommit → CI/CDで本番反映(非開発者向けに便利)
つまり「差分をGitに積んでデプロイへ流す」運用が基本で、これが便利さの本体です。
なお local storage は開発専用なので、本番で編集したい場合は GitHub storage(または Cloud)が前提になります。
✅ 導入完了チェックリスト
本番デプロイ前に確認してください。