こんにちは、白々さじきです。
今回は、個人開発プロジェクト「幹事ツール(guided-scheduler)」に利用規約とプライバシーポリシーを整備してReactページとして実装した話を書きます。
はじめに――なぜ今回整備したか
guided-schedulerは、飲み会やイベントの日程調整と店候補の共有ができるWebツールです。「Claude Codeへの完全委任開発を2週間で検証する」というテーマで作ったプロジェクトで、ブログ記事のネタを集めることも目的のひとつです。
技術スタックは以下の構成です。
- フロントエンド:React + Vite + TypeScript + Tailwind CSS v4
- バックエンド:Hono + TypeScript
- インフラ:Cloudflare Workers + D1 + Drizzle ORM
ソースコードはGitHubにMITライセンスで公開しています。個人が外部からアクセスできる形で運用しているサービスなので、「そろそろ法的な整備をしておこう」と思い立ちました。
ただ、動機の正直なところを言うと「法的に絶対必要だから」というより「個人開発の一通りの経験として、利用規約・プライバシーポリシーを整備するプロセスを一回やっておきたかった」のほうが近いです。SIerとして業務システムの開発に携わっていると、規約まわりは法務や顧客側が用意してくれるものなので、自分で書いた経験がなかったんですよね。
設計判断――連絡先・削除方針・GitHubリンクにしなかった理由
文言を決めるにあたって、いくつかの判断をしました。
連絡先を設置しなかった
メールアドレスを公開する選択肢もありましたが、個人の無料運用サービスにメールが来ても現実的に対応できません。そこで連絡先を記載しないようにしました。
データ削除の方針は「時期を保証しない」にした
削除リクエストへの対応を保証してしまうと、受けきれない可能性があります。実際にDBのリセットや運営都合による削除が起きることもありうるため、「削除時期は保証されません。DBのリセット等、運営上の都合により予告なく削除される場合があります」という文言にしました。保証できないことを正直に書いたほうが、利用者にとっても誤解がなくていいと判断しました。
GitHubリンクではなくサービス内ページとして実装した
最初は「利用規約はGitHubのREADMEかWikiに書いておけばいいか」と思っていました。しかし、「変更後の本規約は、本サービス上に掲載した時点から効力を生じます」という要件を考えると、GitHubページがそれを満たすかどうかが曖昧です。サービス本体のドメイン内に /terms と /privacy のページを置いたほうがシンプルに要件を満たせると判断し、Reactページとして実装することにしました。
アレルギー情報の免責を明示した
このサービスはアレルギー情報の入力・集計機能があります。医療目的のツールではないこと、管理画面では個人を特定できない匿名集計のみ表示することを利用規約・プライバシーポリシーの両方に明記しました。
教訓: 利用規約の文言は「保証できないことを書かない」より「保証できないことを正直に書く」ほうが運用しやすい。
実装内容――React化・ルーティング・フッター
実装はシンプルです。
ページコンポーネントの作成
src/client/pages/terms.tsx と src/client/pages/privacy.tsx を新規作成しました。スタイルは既存ページと同じTailwindクラスを使い、bg-white rounded-2xl shadow p-8 のカードレイアウトで統一しました。各条文はHTMLのリストではなくJSXで書き直し、内部リンクはReact RouterのLinkコンポーネントを使っています。
ルーティングの追加
src/client/App.tsx に /terms と /privacy のRouteを追加しました。Cloudflare Workersのwrangler.tomlで not_found_handling = "single-page-application" が設定済みだったので、Honoバックエンド側の変更は不要でした。Workers Assetsが /terms や /privacy への直接アクセスも index.html にフォールバックしてくれます。
フッターコンポーネントの共通化
src/client/components/footer.tsx を作成し、利用規約とプライバシーポリシーへのリンクを配置。App.tsx の Routes の外側に置くことで全ページ共通で表示されるようにしました。
また、イベント作成画面の送信ボタン直上に「利用規約およびプライバシーポリシーに同意の上、作成してください。」の文言を追加しました。チェックボックスは設けず、文言の表示のみです。
ハマりポイント――フッターが画面外に押し出されていた
フッターを実装したあと、ローカルで確認したら「スクロールしないとフッターが見えない」という問題が発生しました。
原因は、各ページの最外側divに min-h-screen が指定されていたことです。各ページがビューポート全体の高さを占有してしまい、フッターがその下に追いやられていたため、スクロールしないと見えない状態になっていました。
修正はApp.tsxのレイアウト構成を変えることで対応しました。
// App.tsx
<div className="min-h-screen flex flex-col">
<main className="flex-1 flex flex-col">
<Routes>...</Routes>
</main>
<Footer />
</div>
div 全体を min-h-screen flex flex-col にして、main を flex-1 で伸縮させることで、フッターが常にmainの直下に表示されるようになります。各ページ側の min-h-screen は削除し、代わりに flex-1 を付けました。
この修正は自分で気づいて指示を出しましたが、Claude Codeが自発的に「フッターが見えなくなっている」と教えてくれるわけではありません。実際に画面を確認するのは人間の仕事です。このプロジェクトを通じて「UIの見た目の確認だけは委任できない」という感覚が強まっています。
教訓: フッターの押し出しはよくあるmin-h-screenの落とし穴。App.tsxでflex-colを使い、mainをflex-1にするのが定番の解法。
まとめ・次にやること
やってみての感想は、思ったより簡単だったです。文言を自分で一から考える必要はなく、個人開発向けの利用規約の雛形はネット上にいくらでもあります。それをサービスの実態に合わせて編集するだけで十分です。整備に要した時間は文言を考える時間も含めて半日以内でした。
「利用規約・プライバシーポリシーを整備する」と聞くと法務的な重さを感じますが、個人開発レベルであれば「サービスの実態を正直に書く」だけで形になります。完璧な規約を目指すより、まず存在させることのほうが重要です。
現場でも、「規約まわりは法務が担当」「要件はお客様が決める」という形で自分が書く機会がないまま経験年数が積み上がることは多いと思います。個人開発はそういった経験の空白を埋める場として機能するな、と改めて感じました。
次にやること
次は、データを一定間隔で削除するためのGithub Actionを作成しようと思います。
また、削除タイミングに関してのQ&Aの作成も行おうと思います。
サポートのお願い
下記リンクからお買い物いただけると、ブログ運営のための費用が増え、有料サービスを利用した記事作成が可能になります。ご協力よろしくお願いします!

コメント