プロジェクト構造
デフォルトテンプレートが配置するすべてのファイルとディレクトリを案内する。
zfb new my-site を実行すると、basic-blog テンプレートが小さくも完結したプロジェクトを配置します。各ディレクトリが何のためのものかを知っておくと、これ以降のドキュメントをぐっと読み進めやすくなります。
my-site/
├── pages/
│ ├── index.tsx
│ ├── about.tsx
│ ├── 404.tsx
│ └── blog/
│ └── [slug].tsx
├── layouts/
│ └── default.tsx
├── components/
│ ├── callout.tsx
│ ├── theme-toggle.tsx
│ └── zfb-shim.d.ts
├── content/
│ └── blog/
│ ├── hello-zfb.mdx
│ ├── markdown-showcase.md
│ └── styling-with-tailwind.md
├── lib/
│ └── types.ts
├── styles/
│ └── global.css
├── mdx-components.tsx
├── zfb.config.ts
├── package.json
├── tsconfig.json
├── README.md
└── .gitignoreここに並ぶファイルはすべて、読んで書き換えられることを前提にしています。隠されたレイヤーも、触らずにおくべき生成コードもありません。
pages/
ファイルシステムルーティングはここに置かれます。pages/ 配下のすべてのページファイル(.tsx・.ts・.jsx・.js・.mdx・.md・.html)がルートになります。完全なコントラクトは ルーティング を参照してください。
pages/→index. tsx /pages/→about. tsx /about pages/blog/[slug].tsx→/(動的ルート — 解決された slug ごとに 1 つの HTML ファイル)blog/ : slug pages/docs/[...slug].tsx→ キャッチオール、任意の深さにマッチ
テンプレートには静的ルートが 3 つ、動的ルートが 1 つ含まれます。index.tsx は getStaticProps() で全記事を新しい順に一覧し、about.tsx はデータ取得を一切行わない静的ページ、blog/[slug].tsx は paths() をエクスポートします。zfb はビルド時にこの paths() を呼び出し、[slug] をコレクションのエントリごとに 1 つの HTML ファイルへ展開します。完全な API は 動的ルート を参照してください。
特別な意味を持つファイル名は 404.tsx だけです。トップレベルの pages/ は dist/ ではなく、フラットな dist/ を出力します。これは zfb preview が — そしてたいていの静的ホスティングが — マッチしないリクエストに対して配信するファイルです。
テンプレートが動的ルートを 1 つで止めているのは意図的です。ページ分割された一覧やタグごとのアーカイブは、いずれも同じ paths() のコントラクトの上に数行を足すだけで書けるため、テンプレートはそれらを同梱せず README.md から次の一歩としてリンクしています。paginate() はコレクションをページごとのルートに変換し、pages/tags/[tag].tsx ルートは記事のフロントマターにすでにある tags で記事をグループ化します。
layouts/
再利用可能なページラッパーです。layouts/ はすべてのページが import するシェルで、<head>・ヘッダー・フッターに加えて、保存されたテーマを最初のフレームより前に適用するインラインスクリプトを担います。レイアウトは素の TSX コンポーネントなので、好きなように合成できます。
components/
素のコンポーネントと 島 です。テンプレートには 2 つのコンポーネントと 1 つの型宣言が含まれます。
components/は、ベースとなるcallout. tsx Calloutに加えてNote・Tip・Important・Warning・Cautionの 5 つの名前付きラッパーをエクスポートします。この 5 つの名前は GitHub アラート機能によって固定されています。この機能は> [!NOTE]の引用ブロックを、レンダリング前に<Note>要素へ書き換えます。components/はテンプレート唯一のtheme- toggle. tsx "use client"島です。ダークモードを切り替えるもので、ブラウザへ JavaScript を出力する唯一のコンポーネントでもあります。ファイル先頭の"use client"ディレクティブこそが、コンポーネントをクライアントサイドの島に変えるものです。これがないコンポーネントはサーバー上でのみレンダリングされます。考え方の全体像は Islands にあります。components/はコンポーネントではありません。zfb- shim. d. ts zfb.config.tsがdefineConfigを import する際のベア specifierzfb/configを宣言し、@takazudo/zfbが実際に提供する型へと対応づけます。設定ローダーはこの specifier をパース時に内部スタブへエイリアスするため、ディスク上でこれを解決するものは何もありません。このシムがないと、TypeScript とzfb checkはこの import を解決不能として報告します。
content/
コンテンツコレクションです。content/blog/ は blog コレクションの 3 つのシードエントリを保持します。名前付きディレクトリ内の Markdown・MDX ファイルで、ページから getCollection("blog") でクエリできます。
hello-zfb.mdx— ページがどのように HTML になるか、そして MDX が素の Markdown に何を加えるか。markdown-showcase.md— テンプレートが有効にしている markdown 機能(テーブル、打ち消し線、タスクリスト、フットノート、アラート、エンリッチされたコードブロック、見出しマーカー TOC)の実例を、リファレンスページへのリンク付きで掲載。styling-with-tailwind.md— Tailwind の設定がどこにあり、ダークモードがどう組まれているか。
コレクションスキーマは zfb.config.ts の collections 配下で宣言します。クエリ API については Content Collections を参照してください。
mdx-components.tsx
レンダリングされるすべてのコンテンツエントリに適用される、プロジェクトルートのコンポーネントマップです。zfb はこのファイルを zfb.config.ts の隣で検出してビルドに取り込み、ページがレンダリングされる前にその default export をインストールします。そのため <entry. は、呼び出しごとの配線なしにこのマップを拾います。
テンプレートのマップは、components/ の 5 つのアラートコンポーネントをエクスポートします。素の .md 記事で > [!NOTE] が動くのはこれがあるからです。githubAlerts 機能は <Note> 要素を生成し、解決できない PascalCase の名前はレンダリング時に例外を投げます。マージ順は defaultComponents → このファイル → 呼び出し側の components prop なので、個別のページからローカルに上書きすることもできます。MDX Components を参照してください。
lib/
共有の TypeScript ユーティリティです。テンプレートには lib/ が含まれ、ページやコンポーネント全体で使われるフロントマターとエントリの型を持ちます。ここにフレームワークのマジックはありません。必要な場所で import する素の TypeScript モジュールです。
styles/
グローバル CSS です。styles/ がエントリポイントで、layouts/ から import します。冒頭は @import "tailwindcss"; で始まり、@theme ブロックでプロジェクトのテーマトークンを定義し、Tailwind の dark: バリアントをテーマトグルが書き込む data-theme 属性に結び付け、最後にレンダリング済み Markdown 本文向けのスコープ付き .prose ブロックを置いています。
この分割は意図的なものです。.tsx ファイル内のページの外枠は Tailwind ユーティリティをインラインで使いますが、Markdown が生成するのはユーティリティクラスの届かない素のタグです。そこで後者は CSS 側で一度だけスタイルを当て、class="prose" でオプトインします。テンプレートは設定に tailwind キーを持ちません。tailwind: { enabled: false } を指定しない限り Tailwind は有効です。スタイリング を参照してください。
public/
サイトのルートからそのまま配信される静的アセットです。テンプレートは public/ ディレクトリをスキャフォールドしません。静的ファイルを配信する必要が出たときに作成してください。favicon.ico・robots.txt・SVG・ラスター画像・フォント・マニフェストファイルなど、絶対 URL で参照したいバイナリをここに置きます。このディレクトリは URL には現れません。public/ は zfb dev でも zfb build 後でも / で到達できます。
これらのファイルは TSX・MDX・CSS から URL で参照します。
<img src="/logo.svg" alt="" width={128} height={32} />
<link rel="icon" href="/favicon.ico" />静的アセットにバンドラスタイルの import(import logo from ".)を使わないでください。zfb は public/ に対してアセットパイプラインを実行しません。このディレクトリはそのままのミラーであり、ファイルは相対パスに一致する URL で出力されます。
zfb.config.ts で base が設定されている場合(例: base: "/pj/site/")、public/ 内のファイルもそのプレフィックス配下で配信されます。public/ → / です。同じ前置がビルド時にも行われるため、プレフィックスは dev と prod で一貫します。
public/ を使う場合と島向けに TSX import を使う場合の使い分けを含む完全なリファレンスは、静的アセット を参照してください。
zfb.config.ts
テンプレートがスキャフォールドするのは TypeScript の設定ファイルです。オブジェクトを defineConfig() で包むため、完全な型チェックと IDE 補完が得られます。
import { defineConfig } from "zfb/config";
export default defineConfig({
framework: "preact",
collections: [{ name: "blog", path: "content/blog", schema: { /* … */ } }],
markdown: {
gfm: { taskListItem: true, footnoteDefinition: true },
features: { githubAlerts: true, codeEnrichment: {}, headingMarkerToc: true },
},
});zfb がすでにデフォルト値を持つオプションは、意図的にすべて省いてあります。outDir・publicDir・tailwind はいずれも暗黙のままなので、このファイルにはプロジェクトが実際に下した判断だけが並びます。残っているトップレベルのキーは 3 つです。framework("preact")、blog コレクション(zfb check が全記事のフロントマターを検証する JSON Schema 付き)、そして markdown のオプトインです。最後のものは、常時有効なテーブルと打ち消し線に加えて GFM のタスクリストとフットノート、そして GitHub アラート・コードブロックのエンリッチメント・見出しマーカー TOC です。他に何を有効にできるかの全体像は Markdown 機能のインデックスにあります。
設定ファイルは camelCase スキーマを使います。主なキーには次のものがあります。outDir(デフォルト "dist")、publicDir(デフォルト "public")、host(デフォルト "localhost")、port(デフォルト 3000 — これは zfb dev サーバーのデフォルトで、zfb preview は未設定時に代わりに 4321 にフォールバックします)、framework("preact" または "react"、デフォルト "preact")、collections、tailwind、plugins。これは網羅的な一覧ではありません。完全なスキーマのリファレンスは defineConfig を参照してください。
outDir は zfb dev、zfb build、zfb preview のすべてで尊重されます。build と preview では CLI の --outdir が config の outDir より優先され、組み込みのフォールバックは dist/ です。
素の zfb.config.json もレガシーのフォールバックとして受け付けられます。スキーマは同一ですが、型も defineConfig() も得られません。両方のファイルが存在する場合は .ts が優先されます。
package.json、tsconfig.json、README.md、.gitignore
標準的なプロジェクトの配管です。package.json はフレームワークのランタイム依存(デフォルトでは preact)と、4 つのスクリプト dev・build・preview・typecheck(zfb check を実行し、TypeScript とコレクションスキーマの検証を行います)を宣言します。zfb new は @takazudo/zfb と @takazudo/zfb-runtime を、そのプロジェクトをスキャフォールドした CLI のバージョンに厳密ピン留めします — =0.1.0-next.7 のような exact pin であり、^/~ レンジではありません。これにより、スキャフォールドしたプロジェクトが将来のリリースへ静かにドリフトすることがなくなります。
tsconfig.json はプロジェクト全体の TSX がクリーンに型チェックされるよう構成されており、パスエイリアスは 1 つだけです。~/* がプロジェクトルートに解決され、テンプレートはすべての import でこれを一貫して使っています。
README.md は同じツリーの短い案内に加えて、このスターターで有効になっている markdown 機能と、利用可能だが無効にしてある機能を、それぞれリファレンスページへのリンク付きで表にまとめたものです。
同梱の .gitignore は dist/ と node_modules/ を除外し、ビルド出力と依存関係をバージョン管理の外に保ちます。加えて、ビルド実行中に zfb の各パイプラインが生成する一時ファイルも除外します。その 1 つが **/zfb-tailwind-entry-*.css で、Tailwind パイプラインが CSS エントリの隣に書き出すエントリファイルです(スタイリングを参照)。