この記事はZennにも掲載しています。
はじめに
「今日も一日頑張ったけど、何を学んだんだっけ?」
こんな感覚、ありませんか?
アジャイル開発では「振り返り(レトロスペクティブ)」がスプリントの締めくくりとして重要視されています。チームで「よかったこと・改善したいこと」を話し合うことで、次のスプリントをより良くしていく——この考え方はエンジニアリング文化として広く浸透しています。
でも、個人レベルでの振り返りはどうでしょうか?
エビングハウスの忘却曲線によれば、人は学んだことの約70%を翌日には忘れてしまいます。復習や記録をしなければ、1週間後には大半が記憶から消えている。
私はエンジニアとして日々コードを書きながら、「詰まった→解決した→次の問題へ」を繰り返しているうちに、数ヶ月前に何で詰まって、どう解決したかを全然覚えていないことに気づきました。チームの振り返りはやっているのに、自分自身の学びは記録されていない。
転職活動の自己PRでも、「どんなスキルが身についたか」を言語化しようとして詰まる。
せっかく毎日成長しているのに、それが記録されていない。
この課題を解決するために、ReflektaというAI振り返りアプリを個人開発しました。
もちろん、自分自身でも毎日使っています。「今日も1エントリー記録できた」という積み重ねが、数ヶ月後に「こんなことを学んでいたのか」という振り返りになる。そのループを自分のエンジニアとしての成長に活かしたい、というのが開発の大きな動機のひとつです。
この記事では、なぜ作ったか・どう作ったか・リリースして気づいたことを書きます。
どんなアプリか
Reflektaは、今日やったことをテキストで入力すると、AIが以下の4つに整理してくれるアプリです。
- 学び: 今日得た知識・理解
- 詰まったこと: 解決に時間がかかったこと
- 原因仮説: なぜ詰まったのか
- 次のアクション: 明日やること
入力した内容は日付ごとに保存され、過去の振り返りを履歴として見返せます。
プレミアムプランでは、過去の振り返りを参照した分析(「先週も同じエラーで詰まってますね」という気づき)や、週次・月次レポートも生成されます。
技術スタック
| カテゴリ | 採用技術 | 理由 |
|---|---|---|
| フロント | Next.js 14 (App Router) | Server Componentsで初期表示を速くしたかった |
| スタイル | Tailwind CSS + shadcn/ui | 個人開発はデザインに時間をかけたくない |
| DB・認証 | Supabase | RLSでセキュリティを担保しつつ個人開発向けの速さ |
| AI | Claude API (claude-sonnet-4-6) | JSON出力の品質とPrompt Cachingのコスト効率 |
| デプロイ | Vercel | ゼロコンフィグでデプロイでき、PRごとにプレビュー環境が自動生成される。個人開発のCI/CDとして最速 |
| モバイル | Capacitor | 同じコードベースでiOSアプリ化できる |
なぜClaudeを選んだか
GPT-4も試しましたが、JSON形式での安定した出力という点でClaudeの方が壊れにくかったです。また、Prompt Cachingを使うとシステムプロンプトのトークンコストを最大90%削減できるため、個人開発のAPI費用的に助かっています。
実装で工夫したところ
1. フリーミアム設計
無料プランでも「価値を体験できる」ことが大事だと思い、登録なしでも1回だけAI生成を試せるゲスト体験機能を実装しました。
「登録してからしか試せない」はユーザーの離脱につながりやすいという経験則から。
2. 成長の可視化(4つの仕組み)
振り返りを続けてもらうための「可視化」に一番力を入れました。
学習ヒートマップ
GitHubのコントリビューショングラフと同じ構造で、振り返りを記録した日をグリーンで塗りつぶします。外部ライブラリは使わず、純粋なTailwind CSSのグリッドで実装しました。
実は私自身、GitHubの草を生やすのが好きで、「今日もコミットしないと途切れる」という感覚がコードを書き続ける動機のひとつになっています。同じ仕組みを振り返りにも使えば、自分が続けられるはずだと思って採用しました。
「今日も記録しないとヒートマップが途切れる」という心理が継続を生みます。
ランクシステム
累計振り返り回数に応じて、見習い→ブロンズ→シルバー→ゴールド→プラチナと昇格していく仕組みです。
| ランク | 必要累計回数 |
|---|---|
| 見習い | 0回〜 |
| ブロンズ | 5回〜 |
| シルバー | 20回〜 |
| ゴールド | 50回〜 |
| プラチナ | 100回〜 |
ランクアップ時にはモーダルで祝福メッセージを表示し、Xへのシェアボタンも出ます。「◯◯ランクになりました!」という投稿が口コミにつながることを期待しています。
スキル成長グラフ
振り返りのテキストからAIが技術・ツール・概念を自動抽出(プロンプトに "skills": ["React", "TypeScript"] フィールドを追加するだけ)し、期間別の頻度を棒グラフで表示します。
「直近1週間でReactを5回・Supabaseを3回使った」という客観データが見えます。
外部チャートライブラリは使わず、SVGで直接描画しました。
週別・累計ポイントグラフ
週ごとの記録数と累計の折れ線グラフ。ランクの閾値(5・20・50・100)を破線で表示し、「あと◯回でゴールド」が一目でわかるようにしています。
これら4つの可視化は全てライブラリなしのSVGとTailwind CSSで実装しました。外部依存を増やしたくなかったのと、モバイルでのレンダリング品質を完全にコントロールしたかったためです。
AIを活用した開発体験
Reflektaの開発では、AIを「使うアプリを作る」だけでなく、開発プロセス自体にもAIをフル活用しました。
エージェント + SKILLによるハーネスエンジニアリング
Claude Codeのエージェント機能と、役割ごとに定義したSKILL(カスタムプロンプトのハーネス)を組み合わせて開発を進めました。
pm-agent → スプリント計画・競合分析
developer-agent → 実装タスクへの分解・サブエージェントへの委譲
仕様書(requirement.md)を「変更しない」制約として明示することで、AIが勝手に仕様を書き換えないようにしつつ、仕様駆動開発を実践できました。また、テストを設計工程として捉え、Red→Green→Refactorの順で進めるテスト駆動開発も取り入れました。
爆速で動いた
個人開発はどうしても「詰まると止まる」サイクルに陥りがちです。AIと一緒に進めることで詰まりが即座に解消され、想定の数倍のスピードで実装できました。
テスト・型チェック・リファクタリングをAIに任せながら、自分は「何を作るか」「なぜそう作るか」の判断に集中できる——この分業が個人開発の体験をガラッと変えました。
エンジニアリングそのものがより楽しくなった、というのがこのプロジェクトで一番驚いた発見です。
苦労したこと
サブスクリプション実装とテストの難しさ
個人開発で初めてStripeを使ったサブスクリプション課金を実装したのですが、これが想像以上に難しかったです。
まずテスト環境の複雑さ。Stripeにはテストモードとライブモードがあり、webhookのローカルテストにはstripe listenコマンドでトンネルを張る必要があります。「課金した→Supabaseのプランが更新される」という一連のフローを確認するだけで、設定すべきことが多い。
# ローカルでwebhookを受け取るには
stripe listen --forward-to localhost:3000/api/stripe/webhook
次にサブスクリプションのライフサイクル管理。単発決済と違い、サブスクリプションは「契約」「更新」「解約」「支払い失敗」など複数のイベントを適切にハンドリングする必要があります。それぞれのwebhookイベントでSupabaseのプランを正しく更新する実装が必要でした。
// 扱うべきwebhookイベント
switch (event.type) {
case "checkout.session.completed": // 新規契約
case "invoice.payment_succeeded": // 更新成功
case "customer.subscription.deleted": // 解約
case "invoice.payment_failed": // 支払い失敗
}
個人開発でサブスクリプションを初めて実装する方は、Stripeのテストカード番号(4242 4242 4242 4242)とstripe listenの使い方を先に把握しておくことをおすすめします。
Supabase・Vercel の初期設定とアプリ連携
個人開発でSupabaseとVercelを初めて本番利用したのですが、ドキュメントを読むだけでは把握しきれない設定が多く、予想以上に時間がかかりました。
Supabaseでは、RLS(Row Level Security)の仕組みの理解に時間がかかりました。実装自体はAIが書いてくれましたが、「なぜこう書くのか」を理解しないまま進めるのは不安だったので、生成されたポリシーを読み解くことに時間を使いました。テーブルを作るだけではデータを取得できず、SELECT / INSERT / UPDATE それぞれに auth.uid() = user_id のポリシーを定義する必要があること、サービスロールキーとアノンキーの使い分けなど、概念を掴むまでが大変でした。
Vercelでは、環境変数の管理が手間でした。ローカルの.env.local・Vercelのプレビュー環境・本番環境の3つで同じキーが正しく設定されているかを都度確認する必要があります。
各サービスの無料枠や制限事項の把握も大切で、いざ本番運用してみると想定外の制約に気づくことがありました。事前に公式ドキュメントのFAQやPricingページを一通り読んでおくことをおすすめします。
ログイン仕様の検討
認証方式として「Google / Apple のOAuthのみ、パスワードなし」を採用しました。
Appleログインを入れた理由は一つです。 iOSアプリをApp Storeに申請する場合、「サードパーティログインを実装しているなら、Apple Sign-Inも必ず実装しなければならない」というAppleのガイドラインがあります。GoogleログインだけだとリジェクトされるためAppleも対応しました。
iOSアプリをApp Storeに申請する場合、Google等のサードパーティログインを実装しているとApple Sign-Inも必須になります(App Store Review Guidelines 4.8)。見落としやすいので要注意です。
また、ゲスト体験(登録なしで1回AI生成を試せる機能)との共存設計にも悩みました。未ログインユーザーをIPアドレスで識別してレート制限をかける、というアプローチを取りましたが、IPの取得はVercelのx-forwarded-forヘッダーを使う必要があり、ローカル・本番で挙動が違う点に注意が必要でした。
リリースして気づいたこと
流入が思ったより少なかった
リリース直後にXでアナウンスしましたが、インプレッションは数百程度で、実際にアプリを触ってくれた人はほぼいませんでした。Google Search Consoleを確認すると、検索からの流入はほぼゼロ。
「良いものを作れば広まる」は幻想でした。エンジニアが新しいツールを知るきっかけはZennやQiitaの記事経由が多いはずだ、と気づきこの記事を書くことにしました。
「登録なしで試せる」は絶対に必要
リリース初期にゲスト体験機能(登録なしで1回AI生成を試せる)を後から追加したのですが、これを最初から入れておくべきでした。認証の壁はユーザーが思う以上に離脱を生みます。「登録してみたけどよくわからなかった」より「触ってみたら良かったので登録した」の方が圧倒的に転換率が高いはずです。
機能より「なぜ使うか」を伝える方が難しい
機能を作るより、それを「誰のどんな課題を解決するか」として伝えるLPやコピーを整えるほうが難しかったです。「AIが振り返りを整理してくれる」という説明だけでは刺さらず、「転職活動でスキルを言語化できなかった」「数ヶ月前に詰まったことを覚えていない」という具体的な課題感を先に伝えることで、ようやく「自分のことだ」と思ってもらえる気がしています。
App Storeの審査は1〜2週間かかる
現在App Store申請中で、まだ審査通過を待っている状態です。審査には1〜2週間かかることが多く、機能追加やバグ修正のたびに再申請が必要です。モバイル展開を計画している場合は、Webでの機能検証を先に済ませてからバイナリを提出するサイクルを意識するといいと思います。
まとめ・今後の展望
Reflektaは現在も開発中です。今後追加したい機能:
- 振り返りテンプレートの拡張(YWT・KPTなどアジャイルで使われるフォーマットへの対応)
- チームでの利用(複数人で成長を共有)
- GitHubなどの外部ツールとの連携
ぜひ一度試してみてください。
登録なしでもAI振り返りを体験できます(1回無料)。毎日の詰まりを記録する習慣、一緒に作りましょう。
よかったらコメントも頂けると嬉しいです。

