React + Firebase + Gemini APIで「AI交換日記アプリ(ディープジャーナル)」をPWAとして個人開発した技術構成

はじめまして。個人で「Deep Journal(ディープジャーナル)」というAIジャーナリングアプリを開発しました。
React + Firebase という王道構成に GoogleのGemini APIを組み合わせ、PWAとして実装した事例として、技術スタックや工夫点を紹介します。
成果物 (Deep Journal)
👉 https://monozuki.club/journal/
(登録不要・ゲストモードで動作確認できます)
※この記事は Qiita に投稿した内容をベースに、Zenn向けに再構成したものです。
開発のモチベーション
「日記が続かない」という個人的な課題に対し、「自分の日記を読んでフィードバックをくれるAIがいれば続くのではないか?」という仮説検証のために開発しました。
ネイティブアプリではなく、あえてWeb (PWA) を選択した理由は、デプロイの速さとマルチプラットフォーム対応を優先したためです。
技術スタック一覧
「ランニングコストを抑えつつ、UXはネイティブアプリ並みに」を目指して選定しました。
- Frontend: React (Vite)
- Styling: Tailwind CSS
- Backend (Auth/DB): Firebase (Authentication, Firestore)
- Server-Side Proxy: PHP (レンタルサーバー活用)
- AI Model: Google Gemini 2.5 Flash Lite
- Deployment: 自前ホスティング (独自ドメイン)
工夫点1: セキュアで安価なAPI構成
Firebaseだけで完結させるとCloud Functions等の従量課金やコールドスタート問題が懸念材料でした。
そこで、すでに契約していたレンタルサーバー(PHP)を「軽量プロキシ」として活用するハイブリッド構成を取りました。
- クライアント(React)からはFirebase AuthのIDトークンのみを送信。
- PHP側でトークン検証を行い、Gemini APIキーを環境変数から注入してプロキシリクエスト。
- IPベースの独自レート制限もPHP層で実装。
これにより、APIキーの漏洩リスクを回避しつつ、サーバーコストを既存契約内に抑え込んでいます。
工夫点2: PWAによる「アプリ化」
vite-plugin-pwa を導入し、モバイル端末でのUXを向上させました。
- Service Worker: オフラインキャッシュによる高速起動。
- 自動更新ロジック: アプリ起動時にサーバー上のバージョンファイルをチェックし、不整合があればService Workerを更新してリロードする「キルスイッチ」的な機構を実装。SPA特有のキャッシュ事故を防いでいます。
"人間らしさ"を生むプロンプトエンジニアリング
AIとの対話を自然にするため、システムプロンプトに動的なコンテキスト注入を行っています。
-
Time-Awareness (時間認識)
- 現在時刻をプロンプトに含め、「おはよう」「こんばんは」の使い分けや、「深夜ですね」といった労いの言葉を引き出しています。
-
Seasonal-Awareness (季節認識)
- システム日付から「正月」「クリスマス」等のイベントを判定し、挨拶に反映させています。
開発手法:AIペアプログラミング
本プロジェクトのコードの多くは、AIエージェントとのペアプログラミングによって実装されました。
特に、以下の点で生産性が向上しました。
-
巨大コンポーネントのリファクタリング: 2000行を超えた
JournalApp.jsxの分割・整理。 -
ドキュメント生成: 機能追加ごとの変更履歴や、改善計画書(
improvement_plan.md)の自動更新。
おわりに
技術的には枯れた構成(React x Firebase)ですが、生成AIという新しいピースが加わることで、「自分だけの専属カウンセラー」のような新しい体験が個人でも作れるようになりました。
実際の動作は以下から試せます。
UI/UXの参考になれば幸いです。
フィードバックや、技術的な詳細についての質問があればコメントでお待ちしています!
#React #Firebase #Gemini #PersonalDevelopment #PWA
Discussion