← Works
← 一覧に戻る
Thanks Letter
匿名で「ありがとう」を贈り合えるWebサービス。
「あのとき言えなかった、ありがとう」を、匿名で贈り合える公開ウォール型のWebサービス。 本人に届いたら嬉しいけれど、届かなくてもいい——そんな距離感で感謝を書き残せる場所を 目指して、個人開発でMVPを作りました。
概要
ログイン不要・完全匿名で投稿でき、誰でも公開ウォールから他の人の手紙を読めます。 任意でニックネームや「二人だけが知る合言葉」を添えられるのが特徴です。

主な機能
- 公開ウォール — 新着・ランダムで手紙を表示。宛先での絞り込み(部分一致)にも対応
- 匿名投稿 — ログイン不要。宛先・本文・ニックネームを入力するだけ
- そっと頷く — 手紙への軽いリアクション(「いいね」の代わり)
- 本人認定チャレンジ — 投稿者が「二人だけが知る質問」を設定でき、本人が答えると 🕊️ バッジが付く(連絡先は一切持たせない設計)
- 通報・自己削除 — 不適切な手紙の通報と、投稿者自身による削除

技術構成
- Next.js(App Router)/ React / TypeScript — 書き込み系はすべて Server Actions で 実装し、フロントとバックの境界を明確化
- Supabase(PostgreSQL) — 読み取りは anon キー + RLS(Row Level Security)で公開列 のみ、書き込みは service_role をサーバー側に閉じ込めて分離
- Tailwind CSS — 「凪」をイメージした落ち着いたトーンのデザイン
- Vercel にデプロイ、Cloudflare Turnstile で bot 対策
- Vitest / Playwright でユニット・E2E テスト、GitHub Actions で CI
設計で工夫したところ
匿名サービスゆえに「荒らし」「個人情報の流出」「合言葉の総当たり」への備えを多層で 用意しました。
- 段階的なアクセス制御 — RLS と列権限で、IPハッシュ・トークン・モデレーション情報 といった機微な列は匿名クライアントから一切見えないようにした
- 個人情報を残さない — 生のIPは保存せず、サーバー秘密ソルト + SHA-256 でハッシュ化。
手紙ページは
noindexにして二次拡散を防止 - 合言葉の安全な検証 — チャレンジの答えは scrypt + pepper + 手紙ごとのソルトで ハッシュ保存。照合はDB側の関数で行ロックを取りながら原子的に行い、失敗回数に応じて 一時ロックする(総当たり対策)
- 入口モデレーション + 通報フロー — 連絡先やNGワードは投稿時に即ブロック、それ以外 は即時公開しつつ、通報がしきい値に達したら自動で非表示
- fail-closed な運用 — 本番では必要な環境変数が揃っていないと起動を止める設計にして、 設定漏れによる事故を防いだ

