AIに実装を任せる前に仕様書を書く — Claude Code × OpenSpecの開発体験

claude-code-openspec-development-flow

はじめに — AI駆動開発における「仕様の曖昧さ」問題

AIコーディングツールが普及した今、「とりあえず動くものを作る」スピードは劇的に上がりました。しかし要件が曖昧なままClaude Codeに実装を委ねると、意図とずれた成果物が生まれやすく、後から修正コストがかさむ問題が浮上してきてしまいます。

この問題を解決するアプローチとして注目したのが、実装前に仕様を言語化・構造化してから開発を進める「仕様駆動開発」です。今回はOpenSpecというフレームワークを使い、IT情報収集ダッシュボードの構築を実践した体験をレポートします。

OpenSpecとは — 仕様駆動開発フレームワークの概要

OpenSpecは Claude Code上で動作する仕様駆動開発フレームワークでpropose → apply → archiveという3ステップのワークフローで開発を進めます。各ステップはスラッシュコマンドで呼び出します。

  • /opsx:propose — 要件の説明からproposal.mddesign.mdspecs/(要件定義)・tasks.mdを自動生成する
  • /opsx:applytasks.mdのチェックリストに沿って Claude Code が実装を進め、完了タスクを自動でチェック済みに更新する
  • /opsx:archive — 完了した Change をarchive/ディレクトリへ移動し、開発の意思決定履歴として保存する

openspec init後のディレクトリ構造は以下のようになります。Change(変更単位)ごとにサブディレクトリが作られ、アーカイブ時はarchive/YYYY-MM-DD-<change-name>/へ移動して意思決定履歴として残ります。

openspec/
├── changes/
│   ├── <change-name>/          # 進行中の Change
│   │   ├── proposal.md         # 目的・背景・スコープ
│   │   ├── design.md           # 技術設計・判断記録
│   │   ├── tasks.md            # 実装チェックリスト
│   │   └── specs/              # 機能別要件定義
│   │       └── <capability>/
│   │           └── spec.md
│   └── archive/
│       └── YYYY-MM-DD-<name>/  # 完了済み Change
└── specs/                      # プロジェクト全体の仕様(archive 時に同期)

開発するもの — IT情報収集ダッシュボードの要件

今回構築したのは、複数の技術情報ソースから記事を一元収集するダッシュボードです。

情報取得元(4ソース)

  • Zenn — RSS フィード
  • Qiita — API v2
  • GitHub Trending — HTML 解析(公式APIなし)
  • Hacker News — Firebase REST API

主な機能

  • 手動スクレイピング実行
  • 記事一覧表示(ソース・既読/未読/お気に入りでフィルタリング)
  • 既読/未読管理
  • お気に入り登録

技術スタック

  • フレームワーク:Next.js App Router(TypeScript)
  • ORM:Prisma
  • データベース:Neon PostgreSQL
  • スタイリング:Tailwind CSS
  • デプロイ:Vercel

セットアップ — OpenSpecとClaude Codeの環境構築

Claude CodeはAnthropicが提供するCLIツールで、ターミナルからclaudeコマンドで起動します。OpenSpecはnpmでグローバルインストールし、openspec initでプロジェクトへ導入します。

# OpenSpec CLI をグローバルインストール
npm install -g openspec

# プロジェクトルートで初期化(Claude Code 向けのスキルファイルを .claude/ に配置)
openspec init --tools claude

openspec initを実行すると、/opsx:proposeなどのスラッシュコマンドが Claude Code上ですぐに使える状態になります。その後プロジェクトルートで claudeを起動します。

# プロジェクトルートで Claude Code を起動
claude

今回は新規システムで構築していますが、既存のプロジェクトに対してもそのまま導入できる手軽さも、OpenSpecの強みです。

/opsx:proposeで仕様書を自動生成する — OpenSpecと仕様駆動開発の第一歩

/opsx:propose に要件を渡すだけで、Claude Codeがproposal.md・design.md・spec ファイル群・tasks.md を自動生成します。今回は以下のように入力しました。

/opsx:propose "IT情報収集ダッシュボードの初期設計。
ソース:Zenn・Qiita・GitHub Trending・Hacker News。
機能:手動スクレイピング実行・記事一覧表示・既読未読管理・お気に入り。
スタック:Next.js App Router + Prisma + Neon PostgreSQL + Tailwind CSS + Vercel"

生成された proposal.md には、目的・変更内容・Capabilities・影響範囲が整理されました。

## Why

エンジニアが毎日 Zenn・Qiita・GitHub Trending・Hacker News を個別に巡回するのは非効率で、重要な情報を見落としやすい。IT情報収集ダッシュボードを構築することで、複数ソースの最新情報を一元管理し、既読管理・お気に入り機能により情報のノイズを減らす。

## What Changes

- **新規プロジェクト**: IT情報収集ダッシュボードの初期実装(既存コードベースへの変更なし)
- 手動トリガーによるスクレイピング実行機能(Zenn・Qiita・GitHub Trending・Hacker News)
- 取得した記事の一覧表示(ソース・タイトル・日付・タグ)
- 記事の既読/未読ステータス管理
- 記事のお気に入り登録・解除

## Impact

- **新規依存**: Prisma ORM、Neon PostgreSQL(接続文字列環境変数)、Tailwind CSS
- **データベース**: `Article`・`Source` テーブルを新規作成
- **API Routes**: `/api/scrape`(POST)・`/api/articles`(GET)・`/api/articles/[id]/read`(PATCH)・`/api/articles/[id]/favorite`(PATCH)

design.md にはスクレイピング方式の意思決定(なぜ Puppeteer ではなく RSS/API を優先したか)、データモデル、API 設計、リスクが記録されています。

## Decisions

### スクレイピング方式: 外部 API / RSS フィードを優先、DOM スクレイピングは最終手段

- **Zenn**: 公式 RSS フィード (`https://zenn.dev/feed`) を利用
- **Qiita**: 公式 API v2 (`/api/v2/items`) を利用(API キー不要でレートリミット内)
- **GitHub Trending**: HTML スクレイピング(公式 API なし)
- **Hacker News**: 公式 Firebase API (`https://hacker-news.firebaseio.com/v0/`) を利用

**Alternatives considered**: Puppeteer/Playwright によるブラウザ自動化 → Vercel の関数実行時間制限に収まらないリスクがあるため不採用。

生成された tasks.md は以下のとおり。曖昧な要件が実行可能なチェックリストに整理されます。

## 1. 環境・依存関係のセットアップ

- [ ] 1.1 Prisma と `@prisma/client` をインストールする(`npm install prisma @prisma/client`)
- [ ] 1.2 `npx prisma init` で `prisma/schema.prisma` と `.env` を生成する
- [ ] 1.3 `schema.prisma` に `Article` モデルと `SourceType` enum を定義する
- [ ] 1.4 Neon PostgreSQL の接続文字列を `.env` の `DATABASE_URL` に設定する手順をドキュメント化する(実際の値は `.env.local` に記載、`.gitignore` に追加)
- [ ] 1.5 `npx prisma migrate dev --name init` で初回マイグレーションを実行する
- [ ] 1.6 XML パース用に `fast-xml-parser` をインストールする(Zenn RSS 用)

## 2. スクレイパー実装

- [ ] 2.1 `lib/scrapers/zenn.ts` を作成し、RSS フィードから記事を取得・パースする
- [ ] 2.2 `lib/scrapers/qiita.ts` を作成し、Qiita API v2 から記事を取得・パースする
- [ ] 2.3 `lib/scrapers/github-trending.ts` を作成し、GitHub Trending HTML を fetch してリポジトリ情報をパースする
- [ ] 2.4 `lib/scrapers/hacker-news.ts` を作成し、HN Firebase API から Top Stories を取得・パースする
- [ ] 2.5 `lib/scrapers/index.ts` を作成し、全スクレイパーを `Promise.allSettled` で並列実行するエントリーポイントを実装する

## 3. API Route 実装

- [ ] 3.1 `app/api/scrape/route.ts` を作成し、スクレイパーを呼び出して結果を Prisma で upsert する POST ハンドラーを実装する
- [ ] 3.2 `app/api/articles/route.ts` を作成し、`source` / `status` クエリパラメータでフィルタリングする GET ハンドラーを実装する
- [ ] 3.3 `app/api/articles/[id]/read/route.ts` を作成し、`isRead` をトグルする PATCH ハンドラーを実装する
- [ ] 3.4 `app/api/articles/[id]/favorite/route.ts` を作成し、`isFavorite` をトグルする PATCH ハンドラーを実装する

## 4. UI コンポーネント実装

- [ ] 4.1 `app/_components/ScrapeButton.tsx` を実装する(Client Component、`/api/scrape` POST 呼び出し、ローディング状態表示)
- [ ] 4.2 `app/_components/FilterBar.tsx` を実装する(Client Component、ソース・ステータスフィルター、URL search params と同期)
- [ ] 4.3 `app/_components/ArticleCard.tsx` を実装する(記事タイトル・ソース・公開日・タグ・既読ボタン・お気に入りボタン表示)
- [ ] 4.4 `app/_components/ArticleList.tsx` を実装する(Client Component、記事リスト表示・既読/お気に入りトグルの楽観的 UI 更新)

## 5. ページ実装

- [ ] 5.1 `app/page.tsx` を Server Component として実装し、URL search params に基づき Prisma で記事を取得して `ArticleList` に渡す
- [ ] 5.2 記事が0件・お気に入りが0件の場合の空状態 UI を実装する
- [ ] 5.3 記事タイトルクリック時に自動既読化するロジックを `ArticleCard` に追加する

## 6. スタイリング・仕上げ

- [ ] 6.1 Tailwind CSS でレスポンシブな記事カードレイアウトを整える
- [ ] 6.2 ソース別にバッジカラーを設定する(Zenn・Qiita・GitHub・HN で識別しやすく)
- [ ] 6.3 スクレイピング実行中のローディングオーバーレイまたはトースト通知を実装する

## 7. デプロイ準備

- [ ] 7.1 `package.json` の `build` スクリプトに `prisma generate` を追加する(Vercel ビルド対応)
- [ ] 7.2 Vercel プロジェクトに `DATABASE_URL` 環境変数を設定する手順を確認する
- [ ] 7.3 Vercel にデプロイし、スクレイピング・一覧表示・既読・お気に入りの動作を本番環境で確認する

7セクション・28タスクに分解され、実装の全体像が一目でわかる構成になっています。

これらのファイルは最初のプロンプト一発で生成され、proposal.md・design.md・tasks.md のいずれもほとんど手直しなしでそのまま実装フェーズに進められました。「要件をどこまで詳しく書けばよいか」と心配していましたが、ざっくりとした一文から技術的判断の根拠や実装タスクの粒度まで自動で整理されたのは想定以上でした。

/opsx:applyで仕様駆動の実装を進める — Claude Codeによる自動実装フロー

/opsx:apply を実行するとClaude Codeがtasks.mdを読み込み、チェックリストの順に実装を進めます。完了したタスクは - [ ] から - [x] へ自動更新され、28タスクの進捗がリアルタイムで可視化されます。

/opsx:apply

スクレイパー(lib/scrapers/)・API Routes(app/api/)・UIコンポーネント(app/_components/)・ページ実装まで、ほぼノンストップで実装が進みました。ただし、## 7. デプロイ準備の手前で自動実装は終了し、以降はブラウザ操作が必要なデプロイ手順の案内に切り替わりました。仕様書が存在することでClaude Codeの判断がぶれず、コード生成が一貫していた点はOpenSpecの大きなメリットだと感じました。

完成したアプリ

Vercelへのデプロイは手動でGitHubリポジトリ連携を行い、出来上がったサイト以下になります。

it-information-dashboard-ui

Zenn・Qiita・GitHub Trending・Hacker News の4ソースから記事を一括取得し、ソース・既読/未読/お気に入りでフィルタリングできるダッシュボードが完成しました。

さいごに

OpenSpecを使った仕様駆動開発の最大の効果は、「何を作るか」と「どう作るか」を明確に分離できることだと感じました。proposal.md で目的を固め、design.md で技術判断を記録し、tasks.md で実装を追跡する構造があることで、AIが生成するコードの品質と一貫性が大きく向上したと実感しています。

Claude Code単体でも高い開発生産性を発揮しますが、OpenSpecと組み合わせることで「作りながら考える」から「考えてから作る」サイクルが自然と身につくと感じました。仕様書が先にある安心感は、思っていた以上に開発体験を変えてくれると思います。

株式会社SPで一緒に働いてみませんか?

SPはエンジニアの成長を大切にする会社です。

ご興味ある方は一度気軽な雰囲気で、カジュアル面談はいかがでしょうか?

どのような課題を
解決したいですか?

株式会社SPでは、お客様の取り組みに寄り添いながら、
課題解決を伴走支援していきます。

まずはお気軽にこちらからお問い合わせください。

お問い合わせ・相談する(無料)