Zettelkasten × SDD:Spec-kit × Codexでやってみた
はじめに
SDD(Specify → Plan → Implement)と spec-kit、Zettelkasten を組み合わせて、AI が迷わず実装できる土台を作るのが本題です。(Next.js でブログサイトを作ります)
用語が一般的ではないので、先にこちらの記事を参照ください:
spec-kit の参考ドキュメントはこちらです:
ざっくり言うと、
「SDDで仕様駆動開発した時に、Zettelkastenは保たれる?邪魔じゃない?」
の検証をしたい、という感じです。
具体的な開発フローの振り返り
1. まずは憲法(Constitution)を決める
.specify/memory/constitution.md に原則を置いて、
「Zettelkasten First」「Atomic Rules Live in Zettels」
「Specs Live in docs/specs」「TypeScript Only」
「Blog-Site Scope Discipline」などのルールを固定しました。
2. 原子仕様(ZK)を先に作る
次に ZK ノートを作成して、仕様の“核”を固定しました。
-
docs/zettels/ZK-20260101-article-definition.md- 記事の id, title, slug, status, publishedAt など
-
docs/zettels/ZK-20260101-article-listing-rules.md- 並び順、公開条件、ページサイズなど
ここが「不変の真実」なので、Spec はここを参照するだけに徹します。
3. Specify → Plan → Implement
spec-kit の流れで、機能ごとに明確に段階を切りました。
-
/prompts:speckit.specify- 仕様書(Spec)を
docs/specs/に作る
- 仕様書(Spec)を
-
/prompts:speckit.plan- 実装計画・設計を固める
-
/prompts:speckit.tasks- 実行可能なタスクに分割して実装へ
この流れで、一覧ページ(001)も詳細ページ(002)も作成しました。
(ここは基本enterしてただけです)
How-to: 実際にやったコマンドと流れ
ここからは、より実践的に「どう進めたか」を書きます。
ステップ1: ZKと索引を作る(Codexに指示して作成)
「ブログ記事(Article)の基本データ構造と制約を定義する
ZKノートを docs/zettels/ZK-20260101-article-definition.md に作成して」
「ブログ一覧の表示ルールを定義する
ZKノートを docs/zettels/ZK-20260101-article-listing-rules.md に作成して」
「docs/indexes/features.md と docs/indexes/zettels.md を作成して
新しい ZK ノートへのリンクを追記して」
Codex は上記の指示を受けて、ZK ノートと索引を作成し、憲法の「Atomic Rules Live in Zettels」を満たす形に整えてくれました。
ステップ2: Spec を作る
/prompts:speckit.specify "Create a blog post listing page..."
/prompts:speckit.specify "Create an article detail page..."
ここで AI は ZK を読み、
「Spec に ZK の内容を重複させない」という制約を守りながら、
必要な要件の穴を補ってくれました。
ステップ3: Plan → Tasks
/prompts:speckit.plan docs/specs/001-blog-listing-page/spec.md
/prompts:speckit.tasks
/prompts:speckit.plan docs/specs/002-article-detail-page/spec.md
/prompts:speckit.tasks
Plan では技術スタックや設計方針を固め、Tasks で実装手順に落とし込み。
AI はここまでを通じて「どう作るべきか」を自律的に整えます。
ステップ4: 実装
# 実装開始
/prompts:speckit.implement
実際の実装は tasks.md の順番に沿って進行。
AI がタスクをチェックしながら進めるので、
「どこまでやったか」「次に何をやるか」が常に明確でした。
ステップ5: 確認
# 実装開始
npm install
npm run dev


綺麗なサイトですね ^ ^
実際に起きたトラブルと解決
1. 日付のズレ
一覧ページで「日付表示がブラウザ依存」でズレる問題が発生しました。
具体的には toLocaleDateString() の出力差で SSR と CSR が不一致になり、
Hydration Error が出ました。
解決: date-fns の format を使い、
yyyy/MM/dd 固定フォーマットで表示することでズレを解消。
この修正は、Plan に「表示形式は固定」と追記する形で「設計に還元」しました。
2. specs ディレクトリのパス問題
spec-kit のスクリプトは specs/ を前提にしていましたが、
憲法上は docs/specs/ が正しい。
このズレが原因で Plan/Tasks の出力先が一致しない問題が発生。
解決: specs を docs/specs へシンボリックリンクし、
スクリプトの前提を壊さずに憲法を守る形に調整しました。
ここも「場当たり的修正」ではなく、
Constitution のルールを守るための“設計的解決”になっています。
図解で見るフロー
全体の流れ
基本的なSDDの流れですが、改めていいですね。
specの参照もクリーンな感じがします。
Zettelkasten 的なドキュメント管理の検証
docs/ 構造が「知識の最小単位」を支える
実際のリポジトリ構成を含めると、こんな形です。
zettelkasten-sdd/
├── content/
│ └── articles/
│ └── test-article.md
├── docs/
│ ├── indexes/
│ │ ├── features.md
│ │ └── zettels.md
│ ├── specs/
│ │ ├── 001-blog-listing-page/
│ │ │ ├── data-model.md
│ │ │ ├── plan.md
│ │ │ ├── quickstart.md
│ │ │ ├── research.md
│ │ │ ├── spec.md
│ │ │ └── tasks.md
│ │ └── 002-article-detail-page/
│ │ ├── data-model.md
│ │ ├── plan.md
│ │ ├── quickstart.md
│ │ ├── research.md
│ │ ├── spec.md
│ │ └── tasks.md
│ ├── zettels/
│ │ ├── ZK-20260101-article-definition.md
│ │ └── ZK-20260101-article-listing-rules.md
│ └── llm/
├── src/
│ ├── components/
│ ├── lib/
│ ├── pages/
│ └── services/
└── .specify/
この構成で役割がはっきり分かれます。
-
docs/zettels/= 原子仕様の置き場(不変の真実) -
docs/specs/= 機能仕様の置き場(設計の一時領域) -
docs/indexes/= 索引(features / zettels の導線) -
docs/llm/= AI 用のガイドや補助情報
ここで重要なのは、実際にファイル同士がリンクで繋がっていることです。
たとえば docs/indexes/zettels.md には次のようなリンクがあります。
-
ZK-20260101-article-definition→../zettels/ZK-20260101-article-definition.md -
ZK-20260101-article-listing-rules→../zettels/ZK-20260101-article-listing-rules.md
さらに docs/indexes/features.md も ZK へのリンクを持っています。
-
ZK-20260101-article-definition→../zettels/ZK-20260101-article-definition.md
そして Spec 側では、docs/specs/001-blog-listing-page/spec.md と
docs/specs/002-article-detail-page/spec.md の両方が
docs/zettels/ の該当ノートを参照しています。
実際の Spec から抜粋すると、こんな記述があります。
FR-002: System MUST follow the listing behavior defined in
docs/zettels/ZK-20260101-article-listing-rules.mdwithout duplicating those
rules in this spec.
FR-002: System MUST load the markdown file associated with the requested
slug and parse it into article data per
docs/zettels/ZK-20260101-article-definition.md.
ここで重要なのは、Spec 同士が直接リンクしていないことです。
それでも整合性が保たれているのは、ZK をハブにする構造が
「ドキュメントの正規化」を実現しているからです。
1. 「スパゲッティ・スペック」から「ハブ・アンド・スポーク」へ
通常のドキュメントでは「一覧仕様は詳細仕様の〇〇に従う」など、
機能間依存が増えがちで、これがスパゲッティ化を招きます。
このリポジトリでは、以下の構図が成立しています。
-
Hub(中心):
ZK-20260101-article-definition.md -
Spoke(スポーク):
specs/001-blog-listing-page/spec.mdと
specs/002-article-detail-page/spec.md
一覧(001)と詳細(002)は互いの存在を知る必要がなく、「記事とは何か?」という中央の真実(ZK)だけを見ていれば、整合性が自動的に保たれます。
2. AI にとっての「計算効率」と「S/N 比」の最大化
詳細ページ(002)を実装するとき、AI が一覧ページ(001)の UI やページネーションを読む必要はありません。
AI は「002 の Spec」と「参照先の Zettels」だけ読めば十分で、ノイズが減り、S/N 比が最大化されます。
3. 索引(Indexes)こそが自律性を支える
直接リンクがない代わりに、docs/indexes/zettels.md が地図になります。
AI はまず索引をスキャンし、必要な ZK へ自律的に辿り着きます。
実際の docs/indexes/zettels.md はこのように明示的なリンクを持っています。
この「地図 → 原子仕様 → Spec」という動線が、人間の細かい指示を減らし、AI の探索性を高めます。
4. 知識の正規化がもたらす未来
ZK が増えるほど、AI は「過去の教訓」を参照して新しい Spec を検閲できます。
たとえば Spec-003 を作るときも、既存 ZK と矛盾しないかを自動検知できる。
結論
機能同士が直接繋がっていないことは、情報の依存関係を排除し、知識を純粋な状態で管理できている証拠です。通常の SDD が「機能の積み上げ」だとすれば、Zettelkasten 導入型 SDD は「不変の知識のネットワーク化」です。だからこそ、機能が増えてもドキュメントは複雑化せず、むしろ AI にとっての「理解の軽さ」が加速していきます。
ZK が「これ以上分解できない知識」として機能し、Spec はそれを引用するだけにすることで、仕様の“重複コピー”を防げました。
おわりに
SDDを動かしつつ、仕様の整理はZKの規律に従うように動作させました。これといった違和感なく、機能開発をSDDツールを利用して行うことができました!
ZKの規律が、SDDツールの邪魔をしないか?という観点では問題なさそうです。
この方針を成立させる基盤(仕様インポートなど)を整えるのが一番大変そうですが、なかなか良さそうです。
Discussion