はじめに
scribe-cmsのインストールからスキーマ定義、コンテンツの作成、型安全な読み込みまでの5つのステップを解説します。
View as Markdownインストール
pnpm add scribe-cms zod better-sqlite3
動作要件として、Node 20以上、Zod v4が必要です。Scribeは特定のフレームワークに依存せず、Nodeベースの環境であればどこでも動作します。better-sqlite3はネイティブモジュールであるため、バンドラーの対象外に設定してください(詳細はランタイムAPIのページを参照)。
1. scribe.config.tsの作成
プロジェクトのルートディレクトリに配置します。
import { z } from "zod";
import { defineConfig, defineContentType, field } from "scribe-cms";
const blogSchema = z.object({
title: field.translatable(z.string().min(1)),
description: field.translatable(z.string().min(50).max(250)),
author: field.relation("author"),
tags: field.structural(z.array(z.string()).default([])),
});
const authorSchema = z.object({
name: field.structural(z.string().min(1)),
});
export default defineConfig({
rootDir: ".", // relative to this file (CLI) / process.cwd() (runtime)
locales: ["en", "fr", "de"],
types: [
defineContentType({
id: "blog",
path: "/blog/{slug}",
schema: blogSchema,
slugStrategy: "localized",
orderBy: "-publishedAt",
}),
defineContentType({
id: "author",
contentDir: "authors",
schema: authorSchema,
}),
],
});
defineConfigとdefineContentTypeは、リテラル型を保持するための恒等関数です。これにより、後でscribe.blogやrelated(doc, "author")を使用した際に完全な型推論が可能になります。
2. コンテンツの作成
content/
blog/
hello-world.mdx
authors/
jane.mdx
---
title: "Hello, world"
description: "A first post that says hello to the world, at length, because the schema demands fifty characters."
author: jane
publishedAt: "2026-01-15"
---
本文はMDX形式です。**Markdown**とコンポーネントの両方が使用可能です。
ファイル名(hello-world)は英語のslugとして扱われます。publishedAtは、すべての型で利用可能な組み込みフィールドの1つです。詳しくはコンテンツモデルをご覧ください。
3. バリデーション
pnpm installの実行後、scribe CLIコマンドがパスに追加されます。
pnpm scribe validate
pnpm scribe status
ビルドプロセスに組み込む場合は次のように設定します。
{
"scripts": {
"build": "scribe validate && <お使いのフレームワークのビルドコマンド>"
}
}
4. コンテンツの読み込み
import { createScribe } from "scribe-cms/runtime";
import config from "./scribe.config";
const scribe = createScribe(config);
const posts = scribe.blog.list(); // BlogDocの配列、新しい順
const { document } = scribe.blog.resolve("hello-world", "fr");
const author = scribe.blog.related(document!, "author"); // AuthorDoc、nullにはなりません
document.frontmatterはZodスキーマに基づいて型付けされます。詳細な仕様についてはランタイムAPIを参照してください。
5. 翻訳
export GEMINI_API_KEY=... # または.envファイルに記述します
npx scribe translate --locale fr
Scribeは、フランス語で不足しているページや古いページを検出し、field.translatable()で指定されたフィールドを翻訳し、その結果を.scribe/store.sqliteに保存します。このディレクトリは必ずコミットしてください。.scribe/を.gitignoreに追加しないよう注意してください。詳細は翻訳機能のページで確認できます。