はじめに
「仲間内で共有できる、ホワイトボード風のカレンダーアプリが欲しい」というアイデアが浮かんだとき、こんな順番で作りました。
- 画面 UI とロジックを作る
- REST API で外部から操作できるようにする
- AI エージェント(Claude Code)に使わせるために Skill 化する
最近はこうした開発フローをとって、なるべく運用しやすいアプリに仕上げたいと思っています。本記事では、WhiteBoard-Calendar の実装を例に、この流れを紹介します。
1. アプリの概要
WhiteBoard-Calendar は、モバイル閲覧を前提としたホワイトボード風の縦型スクロールカレンダーです。
- 技術スタック: Next.js (App Router) + TypeScript + Supabase + Tailwind CSS
- 認証: 合言葉(passphrase)による2段階ロール制(一般ユーザー/管理者)
- デプロイ: Vercel
付箋を縦に並べたようなシンプルな UI で、管理者はドラッグ&ドロップで予定を移動できます

2. Step 1:画面 UI とロジックを作る(Phase 1〜6)
最初はひたすらアプリを作るフェーズです。Claude Code との対話で一気に実装しました。
実装したこと
- Phase 1:認証基盤 — 合言葉 → サーバーサイドで照合 → HMAC トークン発行。クライアントに passphrase は露出しない。
- Phase 2:カレンダー UI — date-fns で 14 日分を生成し、DateBlock を縦に並べる。EventCard は付箋デザイン。
- Phase 3:Supabase 連携 — useEvents フックで一覧取得。CRUD は API Route 経由(管理者のみ)。Realtime でリロード不要。
- Phase 4:ドラッグ&ドロップ — @dnd-kit で別日付へドロップすると start_at の日付部分だけ更新。
- Phase 5:モバイル最適化 — 空き DateBlock タップで即座に予定追加モーダル。スケルトン表示。
この段階では「Webアプリ」として完結しています。PCやスマホのブラウザから使う分には十分。しかし、外部プログラムから操作する手段がないという制約がありました。
3. Step 2:REST API で拡張性を持たせる(Step4)
「外部 から叩けるようにしよう」という動機で API を整備しました。
追加したエンドポイント
| メソッド | パス | 用途 |
|---|---|---|
| GET | /api/events | 期間指定でイベント一覧取得 |
| GET | /api/events/[id] | 単体取得 |
| POST | /api/events | イベント登録(admin のみ) |
| PATCH | /api/events/[id] | 部分更新(admin のみ) |
| DELETE | /api/events/[id] | 削除(admin のみ) |
| GET | /api/calendars/me | トークンに紐づくカレンダー情報 |
| GET | /api/calendars/[slug]/labels | ラベル一覧 |
設計のポイント
既存トークンの流用: 新しい認証機構は作らず、ログイン時に発行済みの HMAC トークンをそのまま Bearer として使います。DB 変更もゼロ。
バリデーションに zod を採用: POST/PATCH の入力を型安全に検証し、エラー時は詳細を返します。
# 予定一覧を取得する例
curl "https://your-app.vercel.app/api/events?calendarId=<uuid>&from=2026-05-01T00:00:00Z&to=2026-05-31T23:59:59Z" \
-H "Authorization: Bearer <token>"
この時点で curl が使えるあらゆるプログラム からカレンダーを操作できるようになりました。スクリプト自動化、他サービスとの連携、外部アプリからの呼び出し——可能性が大きく広がります。
4. Step 3:AI エージェントに使わせる(Claude Code Skill 化)
REST API が整ったことで、次の改善です。
「Claude に『明日10時に打合せ○○を入れて』『打合せは、毎週金曜日同じ時刻に同じ内容で行われる。5/22から7/17まで、登録してください』と話しかけるだけで予定が登録できるようにたら便利では?」
Claude Code には Skill という仕組みがあります。リポジトリ内の .claude/skills/<skill-name>/SKILL.md に手順を書くと、Claude がその手順を読んで自律的に動いてくれます。
Skill ファイルの構成
.claude/
└── skills/
└── calendar-event/
└── SKILL.md ← AIへの指示書
SKILL.md の役割
SKILL.md には以下を記述しました:
- 設定値の取得方法 —
.env.localからWBCAL_BASE_URL/WBCAL_TOKEN/WBCAL_CALENDAR_IDを読む手順 - ユーザー発話の解釈ルール — 「明日10時」→ ISO 8601 への変換など
- curl テンプレ — 登録・更新・削除・一覧取得のコマンド例
- エラー時の対処 — 400/401/404 の原因と回避策
- Windows 環境の注意点 — 日本語を含む場合は JSON をファイルに書き出して
--data-binary @file.jsonで送信(インライン-dでは文字化けする)
使い方(実際の会話例)
Claude Code で /calendar-event と打つと Skill が起動します。あとは自然言語で話しかけるだけ。
> /calendar-event 来週月曜 14:00 に「定例会議」を入れて
[Claude が .env.local を読み、curl で POST し、登録完了を報告]
Claude は SKILL.md の指示に従い、
.env.localを Read して認証情報を取得- 「来週月曜 14:00」を ISO 8601 に変換
- curl で
POST /api/eventsを実行 - 結果をユーザーに報告
という流れを自動で実行します。
5. この開発フローが良いと思う理由
各 Step が独立して価値を持つ
「API を整備しなければ Skill が作れない」という依存はありますが、それぞれが自立したアウトプットです。Web アプリだけで使い続けることもできるし、API だけをスクリプトから叩くことも、Skill だけを使うこともできます。
AI との共作が各層で成立する
このプロジェクトは全フェーズを Claude Code と共に実装しました。
- UI/ロジック層: 設計を伝えると実装してくれる
- API層: エンドポイント設計・バリデーション・ドキュメント生成
- Skill層: 完成した API を使って、自分自身が操作するための手順書を書く
最後の「AI が API の使い方を Skill として記述し、AI が Skill を読んで実行する」という自己参照的な構造が面白いと思っています。
REST API がハブになる
「外から操作できる API がある」という状態は、さらなる活用を生みます。今回の Skill 化はその一例で、将来的には MCP(Model Context Protocol)サーバー化、他ツールとの連携、自動化スクリプトへの組み込みなども同じ API をベースに実現できます。
おわりに
アイデア → UI+ロジック → API → AI Skill という流れを、ひとつのアプリの成長させることは、シンプルながら示唆に富んでいると感じています。
特に「API を整備する」ステップが、アプリを 閉じたツール から 開いたプラットフォーム に変える転換点です。そして Skill は、その API を AI エージェントが使うための「取扱説明書」に過ぎない——それだけシンプルな構成です。
もともとはMCP サーバー化する想定でしたが、それだけでMCPと接続するだけで、それ自体を使用していなくてもトークンを使用してしまうという仕様がネックになっています。
