Scribe

コンテンツモデル

ファイル、フロントマター、組み込みフィールド、リダイレクト、そして scribe validate のチェック内容についての解説です。

View as Markdown

Files

1つのドキュメントは、コンテンツタイプのフォルダ内にある1つの .mdx(または .md)ファイルに対応します。

content/
  blog/
    hello-world.mdx        → slug "hello-world"
    _redirects.json        → redirect rules for this type (optional)
  authors/
    jane.mdx               → slug "jane"
  • ファイル名がそのまま英語のスラッグになります。スラッグには小文字のケバブケース(kebab-case)を使用します。
  • ディスク上に存在するのは英語のファイルのみです。他の言語バージョンはSQLiteストア内に保存されます。
  • ファイル名が _ や大文字で始まるファイル(例: PUBLISHING.md)は無視されます。コンテンツの横にメモを残したい場合に便利です。

Frontmatter

フロントマターはYAML形式で記述し、コンテンツタイプで設定したZodスキーマに基づいて検証されます。

---
title: "Hello, world"
description: "A long enough description for the schema."
author: jane
publishedAt: "2026-01-15"
updatedAt: "2026-02-01"
---

Body is MDX.

スキーマの検証はZodの設定に従います。通常の z.object を使用した場合、未定義のキーは静かに除外されます。フィールド名の入力ミスをエラーとして扱いたい場合は .strict() を使用してください。

Built-in frontmatter fields

以下のフィールドは、スキーマで宣言しなくてもすべてのコンテンツタイプで利用できます。これらはスキーマの処理が実行される前にフロントマターから抽出されるため、Zodスキーマ内で明示的に宣言しても効果はありません。

フィールドタイプ説明
publishedAtISO date公開日。
updatedAtISO date最終更新日。デフォルトは publishedAt です。サイトマップの lastModified に反映されます。
noindexbooleanサイトマップから除外します。ページのrobotsメタタグとして出力できます。
canonicalPathstring正規URLパスを手動で上書きします。

各言語のドキュメントは、英語の親ドキュメントから publishedAtupdatedAtnoindexcanonicalPath を継承します。翻訳者がこれらを変更することはできません。

また、読み込まれたすべてのドキュメントには、slugenSlug(英語の親スラッグ。英語ドキュメントの場合は slug と同一)、localefrontmattercontent が含まれます。

Bodyless types

参照専用のコレクション(スキーマが構造のみで構成される modelcategory などのタイプ)では、MDXの本文が不要なことがよくあります。この場合、タイプに body: false を指定して明示します。

defineContentType({
  id: "model",
  contentDir: "models",
  schema: modelSchema,
  body: false, // entries are frontmatter-only
});

デフォルトは body: true であるため、完全な下位互換性が保たれます。body: false のタイプに空白以外の本文が含まれているとバリデーションエラーになります。また、ローダーはMDXの解析をスキップし、静的エクスポートでも本文は出力されません。翻訳可能なフィールドがゼロの本文なしタイプは、すべての翻訳ワークフローからも除外されます(不要な通知を防ぎます)。一方、翻訳可能なフィールドを持つ本文なしタイプは、フロントマターのみのペイロードとしてToDoに残ります。翻訳可能性のルールについては、translation を参照してください。

Beyond frontmatter

MDXの本文では、単なるテキスト以上の表現が可能です。

  • インライントークンを使用すると、リンク、アセットURL、翻訳不要なリテラルを本文に直接埋め込み、読み込み時に言語ごとに解決できます。
  • field.asset() で宣言されたアセットはディスク上で検証され、読み込み時に公開URLとして解決されます。

Redirects: _redirects.json

コンテンツタイプのフォルダごとにオプションの _redirects.json ファイルを追加することで、スラッグの移行や廃止されたドキュメントを定義できます。ソースのMDXを削除してもリダイレクトは機能し続けます。翻訳元のスラッグはSQLiteから自動的に展開されます。

{
  "redirects": [
    { "from": "hello-world", "toSlug": "hello-scribe" },
    { "from": ["old-a", "old-b"], "toSlug": "hello-scribe" },
    { "from": "moved-post", "toType": "glossary", "toSlug": "virtual-try-on" },
    { "from": "retired-page", "toUrl": "/pricing" },
    { "from": "retired-ext", "toUrl": "https://example.com/app" }
  ]
}

リダイレクトには3つの種類があります(エントリごとにターゲットは1つだけ指定します)。

種類フィールド説明
Same-typetoSlug同じコンテンツタイプ内のターゲットとなる英語スラッグ。URLはこのタイプの path から構築され、言語ごとにローカライズされます。
Cross-typetoType + toSlugルーティング可能な別のコンテンツタイプ(path が必須)のターゲットとなる英語スラッグ。
AnywheretoUrlルート相対の同一サイトパス、または絶対外部URL。すべての言語で共通です。
  • from: 英語のスラッグのみ指定可能です。翻訳元のスラッグはSQLiteから解決されます。
  • オプションの permanent(デフォルトは true)。

ドキュメントを廃止または名前変更するには、_redirects.json にエントリを追加し、ソースのMDXを削除(または名前変更)してから、scribe validate を実行して再ビルドします。リダイレクトのルールは、プロキシやフレームワークの設定用に buildAllContentRedirects() によって出力されます。

Validation

scribe validate

英語のファイルごとに、スキーマの解析、組み込みフィールドの形式、crossValidate フック、そして本文のMDXコンパイルをチェックします。MDXとして解析できない本文は、英語のソースでも保存された翻訳でも、ビルドをブロックするエラーとなります。

プロジェクト全体では以下の項目もチェックします。リレーションの整合性(必須リレーションの欠落はエラー、オプションのリレーションの欠落は警告)、_redirects.json のルール(有効なターゲット、ソースの重複なし、リダイレクトチェーンの不在)、ローカライズされたスラッグの接尾辞ルール、宣言されたアセットフィールド(ファイルの存在、formatsmaxKB)、本文のインライントークン(不正なスパン、リレーションの欠落、ルーティング不可タイプへの :hrefvars キーの欠落、アセットファイルの欠落)、本文を含んでいる body: false タイプ、アセットディレクトリ設定時の画像アセットの欠落、および翻訳ストアの存在。

エラーが見つかった場合、終了コードはゼロ以外になります。ビルドの前に必ず実行してください。

{
  "scripts": {
    "build": "scribe validate && <your framework build>"
  }
}
コンテンツモデル · Scribe