ワダチを作る #2:ハコヅミの土台を写して、雛形・CI・デプロイを本番まで通した
前回(#1)で企画がまとまったので、今回は開発の土台を作りました。ハコヅミのときは雛形・CI・自動デプロイ・Accessまでを1本で書きましたが、今回はハコヅミのものを土台に写せるので、同じことが同じ日の午前中のうちに、本番のリリースまで終わりました。
やったことは次のとおりです。
- ハコヅミの
CLAUDE.mdから、共通の方針だけを切り出す - スキル(
/issue・/implement)と Issue テンプレートを移す - 雛形・CI・デプロイを作る
- 最初のリリースで、本番(
wadachi.jiru-labo.com)まで通す
作業は、ハコヅミと同じ「Issue → ブランチ → PR → マージ」で進めました。実装とPRはClaude Code、レビューと判断とマージは自分です。Issue は、GitHub Projects のボード(優先度と状態)にも入れて管理しています。
CLAUDE.md:方針だけを写して、実装ごとの決まりは写さなかった
ハコヅミの CLAUDE.md は、冒頭に「どのサービスにも通じる話」(共通方針)を置いて、2つ目のサービスのときに切り出す前提で書いてありました。ただ、中身は約600行あります。
多くは、実装した機能ごとの細かい決まりでした。フォームの二重送信の防止、招待の一覧、課金、ホーム画面に追加するときの注意、など。ワダチにはまだ実装がないので、そのまま写すと、存在しないコードの説明になります。
そこで、次の分け方にしました。
- 写したもの:方針。前提、技術スタック、画面のスタイルの3段構え、環境(開発・本番)、開発の流れ、テストの振り分け、データ設計の共通ルール
- 写さなかったもの:機能ごとの決まり。ワダチで同じものを作ったときに足す。ハコヅミから移す予定の土台(ログイン、管理者と凍結、登録数の上限など)は、「未着手の一覧」として名前だけ並べた
- ワダチで変えたもの:デザイントークンの値は茶系、最初からマルチユーザー(ハコヅミは固定の値で始めて、あとで付け替えるマイグレーションが要った)、「その日」は利用者の時刻で決める、KV・R2・Stripeは必要になってから
方針の原本は Notion の「サービス開発の共通方針」ですが、最終更新が9月29日のままで、ハコヅミの CLAUDE.md のほうが新しい決定を含んでいました(結合テストはログインの流れだけにしたこと、E2Eは develop 向けのPRだけで流すこと、ボードの運用、など)。ワダチの CLAUDE.md は新しいハコヅミ側を基にして、Notion のほうも、あとから追記しました。
スキルとテンプレートも、ハコヅミ固有の話を外して移した
/issue と /implement のスキル、Issue のテンプレートは、ハコヅミのものを土台にしました。ここでも、写し方に迷いました。
ハコヅミのスキルには、「ギアは製品名で表す」「visibility の列」「E2Eの補助関数の名前」のような、ハコヅミのコードを前提にした話が入っています。これを全部外して、ワダチの CLAUDE.md とボードを指すようにしました。
一方、まだ雛形がない部分(テストの補助関数、コマンドなど)は、「雛形ができたら足す」とだけ書いて、具体的には書きませんでした。ないものを書くと、嘘になるためです。
ワダチで効く注意は、新しく足しました。たとえば、連続日数や達成率のテストには、日付の境界(日付が変わる前後、週の区切り、うるう年)を必ず入れる、です。
雛形:入れないものを決めた
雛形は、ハコヅミと同じバージョンの SvelteKit(Svelte 5)・TypeScript strict・Tailwind v4で作りました。トップページは「ワダチ」と一言だけです。
ここでは、入れないものを決めるほうが大事でした。
- ログイン(
better-auth)、決済(stripe)、fflateの依存は入れない(ハコヅミにある依存のうち、ワダチにまだ要らないもの) - Web フォント、CSP、UI部品は入れない(必要になったときに足す)
wrangler.jsoncは、開発用の分だけ。D1 以外のバインディング(KV、R2、送信回数の制限)は入れない
色は、トークンの名前をハコヅミと同じにして、値だけ茶系にしました。値は仮です。ハコヅミの「森」の配色と同じく、app.css の値だけで変えられます。
もう1つ、ハコヅミから写した scripts/check-colors.ts(パレットの色を直接書いたら lint で失敗する仕組み)が、そのままでは動きませんでした。調べる場所の src/lib/components が、まだないためです。「ない場所は何もしない」ように直しました。
CI:E2Eは分けない
CI は、ハコヅミの ci.yml を土台にしました。変えたところは次の2つです。
- E2Eを分割しない:ハコヅミはE2Eを3つに分けて同時に流していますが、ワダチはテストがまだ1つなので、1つのジョブにしました。GitHub Actions の無料枠(月2,000分)は、ハコヅミと共有しています。ジョブを分けると、そのぶん、準備の時間も含めて分に切り上げて数えられるためです。遅くなったら、分けます
- リリースの PR では E2E を流さない:ハコヅミと同じ。
develop→mainの PR では、型チェック・Lint・ユニットテストと、「mainにだけ入った変更がないこと」の確認だけにする
この「main にだけ入った変更がないこと」の確認は、ハコヅミではシェルスクリプトだけで、テストがありませんでした。ワダチでは、使い捨ての Git リポジトリで本物の履歴を作って、スクリプトを流すテストを足しました。「main にだけ入った変更があれば失敗する」を、自動テストで確かめるためです。
最初のPRのCIは、check が44秒、e2e が52秒でした。
デプロイ:トークンは、サービスごと・環境ごとに作った
デプロイは develop → 開発用アカウント、main → 本番用アカウントです。ハコヅミと同じ作りで、GitHub の環境(development・production)ごとに、Cloudflare の API トークンとアカウント ID を入れます。
迷ったのは、API トークンをハコヅミのものと共有するかです。Cloudflare のトークンは、リポジトリではなくアカウントに対して発行されるので、使い回しても動きます。ただ、次の理由で別に作ることにしました。
- トークンの値は、作ったときの1回しか見られない。ハコヅミのGitHubに入っているものは読み出せず、使い回すには値を作り直す必要があり、そうするとハコヅミのデプロイが止まる
- 1つのトークンを2つのサービスで共有すると、漏れたとき、両方を同時に止めることになる
- 名前(
wadachi-development・wadachi-production)で、何用か分かる
本番用のトークンは、ゾーンの範囲を jiru-labo.com だけに絞りました。
Cloudflare Access:開発と本番で、付け方が変わった
開発環境は、ハコヅミと同じく、Cloudflare Access の後ろに置きます。ここで、途中でつまずきそうな点がありました。
開発環境:Workers の画面から付ける
開発環境は workers.dev の URL なので、Worker の「ドメイン」の画面から「Access を有効化」を押す形です。このとき、設定の画面の**スコープの初期値が「プレビューのみ」**になっています。そのままにすると、プレビューの URL だけが守られて、メインの wadachi.nori-suz.workers.dev は誰でも開けたままです。「すべての Traffic」に変えて、ポリシーは「Cloudflare account members」にしました。
設定のあと、curl で確かめました。200 ではなく 302(Access のログイン画面への移動)が返れば成功です。
本番:カスタムドメインなので、アプリケーションを自分で作る
本番は、workers.dev と Preview URL を閉じて、カスタムドメイン wadachi.jiru-labo.com だけを入口にしました(ハコヅミと同じ)。この場合、Workers の画面からは付けられないので、Zero Trust の「セルフホスト型」のアプリケーションを、自分で作ります。
ポリシーは、ハコヅミの「アカウントのメンバー」ではなく、自分のメールアドレス2つだけを許可する形にしました。誰が入れるのかが画面から分かるためです。今は自分しか使わないので、結果は同じです。
公開するときは、このアプリケーションを消します。
最初のリリース:本番まで通した
土台ができたところで、develop → main のPRを作って、最初のリリースをしました。マイグレーションがなく、main もまだ最初のコミットだけだったので、中身は単純です。
確かめたことは次のとおりです。
- リリースのPRでは、
e2eが飛ばされ、checkだけが動いた - マージ後の本番のデプロイが、54秒で成功した
https://wadachi.jiru-labo.comで、トップページが開いた- 本番の
workers.devの URL と、バージョンごとの Preview URL は、404 になった(閉じている)
デプロイの前に心配していたのは、カスタムドメインを付けるときに、トークンの権限が足りるかでした。DNS の権限まで要るかもしれず、足りなければ本番のデプロイが落ちるためです。実際は、「Workers スクリプトの編集」「D1の編集」「ゾーンの Workers ルートの編集」のテンプレートのままで足りました。
もう1つ、確かめられた小さなことがあります。Markdown だけを変える PR では、CI もデプロイも動かない、という paths-ignore の設定です。実際に CLAUDE.md だけを変える PR を出して、チェックが1つも出ないことを確認しました。
おわりに
写して分かったのは、方針と、実装ごとの決まりは、分けて持つほうがよいということでした。方針は、どのサービスにも通用します。実装ごとの決まりは、そのコードがあって初めて意味があるので、写さず、同じものを作ったときに足すことにしました。
土台はこれで整いました。次は、最初の機能です。iPad mini でのタイマーの試作と、習慣の登録・記録の画面に進みます。