tinacms について
コンテンツ中心のサイトを開発する人向けに、GitベースのヘッドレスCMSであるTinaCMSのビジュアル編集と設定を解説します。Next.js連携、コンテンツスキーマ、トラブルシューティング、デプロイ方法を扱います。
主な機能
- 01Gitベースのコンテンツ管理
- 02ビジュアル編集の連携
- 03コレクションとフィールドのスキーマ設定
- 04ビルドや設定のよくある問題の調査
- 05TinaCloudとNode.jsのデプロイ案内
活用シーン
- 01コンテンツ中心のサイトにCMSを設定
- 02Next.jsページでビジュアル編集を有効化
- 03スキーマビルドやパス設定の問題を調査
- 04マネージドまたはNode.jsセルフホストを選択
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill tinacmsインストール後、Claude Code で/tinacmsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.claude-plugin/plugin.jsonassets/links-to-official-docs.mdreferences/common-errors.mdscripts/check-versions.shtemplates/astro/.env.examplepackage.jsontina-config.tstemplates/cloudflare-worker-backend/src/index.tstemplates/collections/author.tsblog-post.tsdoc-page.tslanding-page.tstemplates/nextjs/.env.examplepackage.jsontina-config-app-router.tstina-config-pages-router.tstemplates/vite-react/.env.examplepackage.jsontina-config.tsvite.config.ts詳細
TinaCMS
コンテンツ量の多いサイト向けの、ビジュアル編集機能を備えた Git 管理のヘッドレス CMS です。
最終更新日:2026-01-21 バージョン:[email protected], @tinacms/[email protected]
クイックスタート
パッケージマネージャーの推奨事項:
- 推奨:pnpm(TinaCMS >2.7.3 では必須)
- 代替:npm または yarn(新しいバージョンではモジュール解決に問題が発生する場合があります)
# Install pnpm (if needed)
npm install -g pnpm
# Initialize TinaCMS
npx @tinacms/cli@latest init
# Install dependencies with pnpm
pnpm install
# Update package.json scripts
{
"dev": "tinacms dev -c \"next dev\"",
"build": "tinacms build && next build"
}
# Set environment variables
NEXT_PUBLIC_TINA_CLIENT_ID=your_client_id
TINA_TOKEN=your_read_only_token
# Start dev server
pnpm run dev
# Access admin interface
http://localhost:3000/admin/index.html
バージョンの固定(推奨):
CLI/UI の自動更新による破壊的変更を防ぐため、正確なバージョンを固定してください。
{
"dependencies": {
"tinacms": "3.3.1", // NOT "^3.3.1"
"@tinacms/cli": "2.1.1"
}
}
理由:TinaCMS の UI アセットは CDN から配信されるため、ローカルの CLI より先に更新され、互換性の問題が発生する場合があります。
Next.js との統合
useTina Hook(ビジュアル編集を有効にします):
import { useTina } from 'tinacms/dist/react'
import { client } from '../../tina/__generated__/client'
export default function BlogPost(props) {
const { data } = useTina({
query: props.query,
variables: props.variables,
data: props.data
})
return <article><h1>{data.post.title}</h1></article>
}
export async function getStaticProps({ params }) {
const response = await client.queries.post({
relativePath: `${params.slug}.md`
})
return {
props: {
data: response.data,
query: response.query,
variables: response.variables
}
}
}
App Router:app/admin/[[...index]]/page.tsx の管理ルート
Pages Router:pages/admin/[[...index]].tsx の管理ルート
スキーマ設定
tina/config.ts の構造:
import { defineConfig } from 'tinacms'
export default defineConfig({
branch: process.env.GITHUB_BRANCH || 'main',
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID,
token: process.env.TINA_TOKEN,
build: {
outputFolder: 'admin',
publicFolder: 'public',
},
schema: {
collections: [/* ... */],
},
})
コレクションの例(ブログ記事):
{
name: 'post', // Alphanumeric + underscores only
label: 'Blog Posts',
path: 'content/posts', // No trailing slash
format: 'mdx',
fields: [
{
type: 'string',
name: 'title',
label: 'Title',
isTitle: true,
required: true
},
{
type: 'rich-text',
name: 'body',
label: 'Body',
isBody: true
}
]
}
フィールドの種類:string、rich-text、number、datetime、boolean、image、reference、object
参照フィールドに関する注意:参照フィールドが、フィールド名を共有する複数のコレクションタイプを参照する場合は、フィールドの種類が一致していることを確認してください。種類が競合すると(例:bio: string と bio: rich-text)、GraphQL スキーマエラーが発生します。
// Example: Reference field referencing multiple collections
{
type: 'reference',
name: 'contributor',
collections: ['author', 'editor'] // Ensure shared fields have same type
}
出典:コミュニティからの情報
よくあるエラーと解決策
1. ❌ ESbuild のコンパイルエラー
エラーメッセージ:
ERROR: Schema Not Successfully Built
ERROR: Config Not Successfully Executed
原因:
- カスタムローダー(webpack、babel プラグイン、esbuild ローダー)を使用するコードをインポートしている
- フロントエンド専用のコード(
window、DOM API、React フックを使用)をインポートしている - 特定のモジュールではなく、コンポーネントライブラリ全体をインポートしている
解決策:
必要なものだけをインポートしてください。
// ❌ Bad - Imports entire component directory
import { HeroComponent } from '../components/'
// ✅ Good - Import specific file
import { HeroComponent } from '../components/blocks/hero'
予防のヒント:
tina/config.tsのインポートは最小限にします- 型定義とシンプルなユーティリティのみをインポートします
- UI コンポーネントの直接インポートは避けます
- 必要に応じて、個別の
.schema.tsファイルを作成します
参考:references/common-errors.md#esbuild を参照してください
2. ❌ モジュール解決:「Could not resolve 'tinacms'」
エラーメッセージ:
Error: Could not resolve "tinacms"
原因:
- インストールが破損しているか、不完全である
- 依存関係のバージョンが一致していない
- ピア依存関係が不足している
解決策:
# Clear cache and reinstall
rm -rf node_modules package-lock.json
npm install
# Or with pnpm
rm -rf node_modules pnpm-lock.yaml
pnpm install
# Or with yarn
rm -rf node_modules yarn.lock
yarn install
予防策:
- ロックファイル(
package-lock.json、pnpm-lock.yaml、yarn.lock)を使用します --no-optionalや--omit=optionalフラグは使用しないでください- React 以外のフレームワークでも、
reactとreact-domがインストールされていることを確認します
3. ❌ フィールド名の制約
エラーメッセージ:
Field name contains invalid characters
原因:
- TinaCMS のフィールド名に使用できるのは、英字、数字、アンダースコアのみです
- ハイフン、スペース、特殊文字は使用できません
解決策:
// ❌ Bad - Uses hyphens
{
name: 'hero-image',
label: 'Hero Image',
type: 'image'
}
// ❌ Bad - Uses spaces
{
name: 'hero image',
label: 'Hero Image',
type: 'image'
}
// ✅ Good - Uses underscores
{
name: 'hero_image',
label: 'Hero Image',
type: 'image'
}
// ✅ Good - CamelCase also works
{
name: 'heroImage',
label: 'Hero Image',
type: 'image'
}
注意:これは Forestry.io からの移行に伴う破壊的変更です
4. ❌ Docker のバインドに関する問題
エラー:
- Docker コンテナの外部から TinaCMS の管理画面にアクセスできない
原因:
- デフォルトでは TinaCMS は
127.0.0.1(ローカルホストのみ)にバインドされます - 外部接続を受け付けるには、Docker コンテナを
0.0.0.0にバインドする必要があります
解決策:
# Ensure framework dev server listens on all interfaces
tinacms dev -c "next dev --hostname 0.0.0.0"
tinacms dev -c "vite --host 0.0.0.0"
tinacms dev -c "astro dev --host 0.0.0.0"
Docker Compose の例:
services:
app:
build: .
ports:
- "3000:3000"
command: npm run dev # Which runs: tinacms dev -c "next dev --hostname 0.0.0.0"
5. ❌ _template キーが見つからないエラー
エラーメッセージ:
GetCollection failed: Unable to fetch
template name was not provided
原因:
- コレクションで
templates配列(複数のスキーマ)を使用している - ドキュメントの frontmatter に
_templateフィールドがない templatesからfieldsに移行したが、ドキュメントが更新されていない
解決策:
オプション 1:代わりに fields を使用する(単一テンプレートの場合に推奨)
{
name: 'post',
path: 'content/posts',
fields: [/* ... */] // No _template needed
}
オプション 2:frontmatter に _template があることを確認する
---
_template: article # ← Required when using templates array
title: My Post
---
移行スクリプト(templates から fields に変換する場合):
# Remove _template from all files in content/posts/
find content/posts -name "*.md" -exec sed -i '/_template:/d' {} +
6. ❌ パスの不一致に関する問題
エラー:
- ファイルが Tina 管理画面に表示されない
- 保存時に「ファイルが見つかりません」というエラーが発生する
- GraphQL クエリの結果が空になる
原因:
- コレクション設定の
pathが実際のファイルディレクトリと一致していない - 相対パスと絶対パスの混同
- 末尾のスラッシュに関する問題
解決方法:
// Files located at: content/posts/hello.md
// ✅ Correct
{
name: 'post',
path: 'content/posts', // Matches file location
fields: [/* ... */]
}
// ❌ Wrong - Missing 'content/'
{
name: 'post',
path: 'posts', // Files won't be found
fields: [/* ... */]
}
// ❌ Wrong - Trailing slash
{
name: 'post',
path: 'content/posts/', // May cause issues
fields: [/* ... */]
}
デバッグ:
npx @tinacms/cli@latest auditを実行してパスを確認します- 指定したディレクトリにファイルが存在することを確認します
- ファイル拡張子が
formatフィールドと一致していることを確認します
7. ❌ ビルドスクリプトの実行順序に関する問題
エラーメッセージ:
ERROR: Cannot find module '../tina/__generated__/client'
ERROR: Property 'queries' does not exist on type '{}'
原因:
tinacms buildより先にフレームワークのビルドが実行されている- TypeScript のコンパイル前に Tina の型が生成されていない
- CI/CD パイプラインの実行順序が正しくない
解決方法:
{
"scripts": {
"build": "tinacms build && next build" // ✅ Tina FIRST
// NOT: "build": "next build && tinacms build" // ❌ Wrong order
}
}
CI/CD の例(GitHub Actions):
- name: Build
run: |
npx @tinacms/cli@latest build # Generate types first
npm run build # Then build framework
これが重要な理由:
tinacms buildはtina/__generated__/に TypeScript の型を生成します- フレームワークのビルドを正常に完了するには、これらの型が必要です
- 順序を誤ると型エラーが発生します
8. ❌ TinaCMS アセットの読み込みに失敗する
エラーメッセージ:
Failed to load resource: net::ERR_CONNECTION_REFUSED
http://localhost:4001/...
原因:
- 開発用の
admin/index.htmlを本番環境にプッシュしている(アセットが localhost から読み込まれる) - サイトがサブディレクトリで配信されているが、
basePathが設定されていない
解決方法:
本番環境へのデプロイの場合:
{
"scripts": {
"build": "tinacms build && next build" // ✅ Always build
// NOT: "build": "tinacms dev" // ❌ Never dev in production
}
}
サブディレクトリへのデプロイの場合:
⚠️ サブパスへのデプロイに関する制限:TinaCMS には、サブパス(例:
example.com/adminではなくexample.com/cms/admin)にデプロイした際、アセットが正しく読み込まれない既知の問題があります。これはbasePathを設定していても発生する制限です。回避策:TinaCMS の管理画面をルートパス(
/admin)にデプロイするか、リバースプロキシの書き換えルールを使用してください。出典:コミュニティからの情報
// tina/config.ts
export default defineConfig({
build: {
outputFolder: 'admin',
publicFolder: 'public',
basePath: 'your-subdirectory' // ← May have asset loading issues on sub-paths
}
})
CI/CD の修正:
# GitHub Actions / Vercel / Netlify
- run: npx @tinacms/cli@latest build # Always use build, not dev
9. ❌ Reference フィールドで 503 Service Unavailable が発生する
エラー:
- Reference フィールドのドロップダウンでタイムアウトし、503 エラーが発生する
- Reference フィールドの読み込み時に管理画面が応答しなくなる
原因:
- 参照先コレクションの項目数が多すぎる(数百または数千)
- 現在、Reference フィールドはページネーションに対応していない
解決方法:
方法 1:コレクションを分割する
// Instead of one huge "authors" collection
// Split by active status or alphabetically
{
name: 'active_author',
label: 'Active Authors',
path: 'content/authors/active',
fields: [/* ... */]
}
{
name: 'archived_author',
label: 'Archived Authors',
path: 'content/authors/archived',
fields: [/* ... */]
}
方法 2:バリデーション付きの string フィールドを使用する
// Instead of reference
{
type: 'string',
name: 'authorId',
label: 'Author ID',
ui: {
component: 'select',
options: ['author-1', 'author-2', 'author-3'] // Curated list
}
}
方法 3:カスタムフィールドコンポーネント(上級者向け)
- カスタムコンポーネントでページネーションを実装します
- TinaCMS のドキュメントを参照してください:https://tina.io/docs/extending-tina/custom-field-components/
10. ❌ メディアマネージャーのアップロードがタイムアウトする(ゴーストアップロード)
エラーメッセージ:
Upload failed
Error uploading image
原因:
- メディアマネージャーにはエラーが表示されるものの、画像はバックグラウンドで正常にアップロードされる
- UI のタイムアウトが実際のアップロード状況を反映していない
- 削除時にも同様の問題が発生する(エラーが表示されるものの、削除は成功する)
解決方法:
アップロード時にエラーが表示された場合:
- 5~10 秒待ちます
- メディアマネージャーを閉じて、再度開きます
- 再試行する前に、画像がすでにアップロードされていないか確認します
- アップロードを重複して試みないようにします
ステータス:既知の問題(優先度高) 出典:GitHub Issue #6325
デプロイの選択肢
TinaCloud(マネージド) - 推奨
セットアップ:
- https://app.tina.io でサインアップします
- Client ID と Read Only Token を取得します
- 環境変数を設定します:
NEXT_PUBLIC_TINA_CLIENT_ID、TINA_TOKEN - Vercel/Netlify/Cloudflare Pages にデプロイします
利点:設定不要、無料枠(月間 10k リクエスト)
Node.js でのセルフホスト
⚠️ エッジランタイムの制限:セルフホストの TinaCMS は、
@tinacms/datalayerと@tinacms/graphqlに Node.js 依存関係があるため、エッジランタイム環境(Cloudflare Workers、Vercel Edge Functions)では動作しません。エッジ環境にデプロイする場合は、TinaCloud(マネージドサービス)を使用してください。ソース:GitHub Issue #4363(「wontfix」のラベル付き)
⚠️ セルフホストのサンプルは古くなっている可能性があります:TinaCMS リポジトリの公式セルフホストサンプルは、チームによって「かなり古い」と認められています。サンプルリポジトリだけに頼らず、常に最新のドキュメントと照らし合わせてください。
Node.js 環境専用(エッジランタイムではありません):
pnpm install @tinacms/datalayer tinacms-authjs
npx @tinacms/cli@latest init backend
例(Node.js サーバー、Workers ではありません):
import { TinaNodeBackend, LocalBackendAuthProvider } from '@tinacms/datalayer'
import { AuthJsBackendAuthProvider, TinaAuthJSOptions } from 'tinacms-authjs'
import databaseClient from '../../tina/__generated__/databaseClient'
const isLocal = process.env.TINA_PUBLIC_IS_LOCAL === 'true'
// This ONLY works in Node.js runtime, NOT edge runtime
const handler = TinaNodeBackend({
authProvider: isLocal
? LocalBackendAuthProvider()
: AuthJsBackendAuthProvider({
authOptions: TinaAuthJSOptions({
databaseClient,
secret: process.env.NEXTAUTH_SECRET,
}),
}),
databaseClient,
})
メリット:完全な制御、セルフホスト デメリット:Node.js ランタイムが必要です(エッジコンピューティングは使用できません)