Tsuzumi — 行動心理学に基づくモバイル習慣トラッカーの設計と実装
解決すべき課題
習慣化を続けるのは難しいという課題に対して、既存アプリを調査した結果、市場には2つの極があることがわかりました。
| カテゴリ | 代表例 | 問題点 |
|---|---|---|
| ソロ型トラッカー | Loop, Streaks | 一人で続けるため孤独、モチベーション維持が困難 |
| ソーシャル型 | Habitica, Habitify | チャット・コメント前提で重い、SNS疲れと相性が悪い |
この中間に「誰かの存在は感じたいが、コミュニケーションコストは払いたくない」というニーズがあると判断しました。
設計思想: 「繋がりすぎない繋がり」
本アプリのコアコンセプトは テキスト・音声コミュニケーションを完全に排除した軽量ソーシャル です。以下の設計原則をすべての機能判断の基準としています。
| 原則 | 内容 | 具体的な判断例 |
|---|---|---|
| 軽さ最優先 | 1タップで記録完了 | 量や質の入力は求めない。「やったかどうか」だけ |
| 匿名性 | プロフィール不要 | 「筋トレの仲間」としてのみ表示。ユーザーIDやカード名は非公開 |
| アプリ主導 | マッチングもエール提案もアプリがコントロール | ユーザーは「送る/送らない」を選ぶだけ |
| ポジティブ体験 | 失敗を責めない、再開を称える | ストリーク途切れを強調しない設計 |
行動心理学の知見の適用
設計には以下の理論的背景を取り入れています。
| 理論 | アプリへの適用 |
|---|---|
| Fogg Behavior Model | 1タップ記録で「実行しやすさ」を最大化 |
| Habit Loop(習慣ループ) | エールを「報酬」として習慣ループを強化 |
| 自己決定理論 | 外発的報酬より「成長感」「共走感」を優先 |
| セルフ・コンパッション | 失敗を責めず再開を称える設計(復活バッジ) |
特に「復活の一歩」バッジは、中断後に3日間再開した場合に獲得できるバッジです。連続記録(ストリーク)を主役にすると、1日途切れただけで離脱するリスクがあります。このバッジは「戻ってきていい」というメッセージを設計に組み込むためのものです。
技術選定
| 技術 | 選定理由 |
|---|---|
| React Native + Expo | iOS/Android両対応が必須。Expo Routerのファイルベースルーティングで開発効率を確保 |
| Firebase (Firestore) | リアルタイム同期がエール通知に必要。匿名認証でログインハードルを排除 |
| Cloud Functions | エール生成・バッチ通知などサーバーサイドロジックをサーバーレスで実行 |
| TypeScript | 型安全性による保守性確保。特にFirestoreのデータモデル定義で効果を発揮 |
匿名認証の採用 は、コンセプトとの整合性から決定しました。「すぐに始められる」体験を最優先し、メールアドレス登録のハードルを排除しています。将来的にアカウント昇格(メール/SNS連携)が可能な設計にしてあります。
段階的開発: 10フェーズの意思決定
MVP思考で段階的に機能を追加しました。各フェーズの区切りは「常に動くプロダクトを維持する」ことを基準としています。
| Phase | 内容 | 判断の根拠 |
|---|---|---|
| 1-6 | 基本記録・Firebase連携・ストリーク・統計 | コア機能を先に完成させ、動作する状態を確保 |
| 7 | AIエール機能(Cloud Functions) | コールドスタート問題への対策。ユーザーが少ない段階でも「応援される体験」を提供 |
| 8 | 人間エール機能 | AIエール基盤の上にユーザー間リアクションを追加 |
| 9 | UX改善(3ボタンダイアログ、長押しショートカット) | 実機テストで得たフィードバックを反映 |
| 9.5 | カード管理強化・ニックネーム機能 | 重複防止(Levenshtein距離による類似度検出)、作成上限(50枚)など運用安全性を確保 |
| 10A | お気に入り機能 | エール送信先の固定化ニーズへの対応 |
| 10B | セキュリティ修正 | 10Aで一時的に緩和したFirestoreセキュリティルールを修正 |
セキュリティ対応の具体例
Phase 10Aでお気に入り機能を実装した際、開発速度を優先してFirestoreのセキュリティルールを一時的に緩和しました。機能の動作確認後、Phase 10Bとしてセキュリティ監査を実施し、以下の脆弱性を修正しています。
- リアクション機能における送信者の偽装可能性を修正
- データの公開範囲設定が意図通りに機能していない箇所を修正
- 不要な権限の削除
セキュリティルールの緩和と修正を別フェーズとして明示的に管理し、緩和状態のまま放置しない運用を徹底しています。
テスト導入によるバグ発見
Phase 8で自動テスト基盤(Jest + Firestoreモック)を導入しました。テスト作成の過程で、logServiceのストリーク計算が0を返すバグと、statsServiceの週開始日計算の問題を発見しています。手動テストでは見逃していた問題が、テストコードの作成時に顕在化した実例です。
CI/CD戦略についても、当初の計画を見直しました。テスト整備Phase 1→2→3の順序で進める予定でしたが、「CI環境(GitHub Actions)が最も価値が高い」と判断し、Phase 3を最優先に変更しています。最小限のスモークテストでCIパイプラインを先に構築し、テストカバレッジは段階的に拡充する方針です。
AIエール機能の設計
最も設計に時間をかけた機能です。Cloud Functionsで4つのパターンを実装しました。
| パターン | トリガー | 設計意図 |
|---|---|---|
| 記録直後 | 習慣記録の5-45分後 | 即時フィードバック。意図的な遅延で「監視感」を排除 |
| 継続途切れ | 未記録の翌日(週2回上限) | 優しい復帰誘導。脅迫的にならないよう頻度制限 |
| 長期離脱 | 7日/21日/35日後(最大3回/カード) | 「待っている」メッセージ。段階的に間隔を空ける |
| ランダム | 6時間ごと | 不意の嬉しさ。直近1週間に記録があるユーザーのみ対象 |
68種類の文言を用意し、同じ文言の繰り返しによる「ロボット感」を排除しています。また、お休みモード(デフォルト23:00-07:00)を実装し、ユーザーの生活リズムを尊重しています。
AIエールと人間エールを区別しない 設計も意図的な判断です。どちらも「ハビット仲間」として表示し、「応援されている」感覚を分断しないようにしています。
実装上の技術的課題と対応
SafeAreaView の無限ループ
SafeAreaViewのリファクタリング時に無限ループが発生しました。原因はuseFavoritesフックの不要な状態更新と、buildSections関数の状態更新パターンにありました。
対応として、ヘルパー関数をuseCallbackでメモ化し、状態更新を関数型アップデートに変更しました。レイアウトコンポーネントのアーキテクチャも見直し、_layout.tsxはSafeAreaProviderのみを提供する構成に整理しています。
Android / iOS の時刻ピッカー分岐
設定画面の時刻選択UIで、Androidのネイティブダイアログとの互換性問題が発生しました。iOSではモーダル表示、Androidではネイティブダイアログと、プラットフォームごとに実装を分離することで対応しています。
Lottieアニメーションの統合
起動画面と記録成功時のアニメーションにLottieを採用しました。起動画面ではタップで即座にスキップできる仕組みを実装し、アニメーションを待たされるストレスを排除しています。記録成功時のアニメーションも3.5秒で自動消去されますが、タップで即座に閉じることも可能です。
リリース準備
Google Play向けのリリース準備として、以下を実施しました。
- EAS Buildによる本番ビルド(AABファイル生成)
- アプリ名のリブランディング(「Tsuzumi」に統一)
- データ削除ページの作成(Google Play要件)
- データセーフティ情報の整備
不採用とした機能と理由
設計段階で検討し、意図的に不採用としたものがあります。
| 機能 | 不採用理由 |
|---|---|
| ランキング・レベル・経験値 | 競争・比較要素はSNS疲れと相性が悪い。軽さを損なう |
| テキストチャット | コミュニケーションコストが上がり、コアコンセプトに反する |
| プロフィール公開 | 匿名性の維持が設計の根幹 |
| ストリーク途切れの強調表示 | 完璧主義を助長し離脱リスクを高める |
「何を作るか」と同時に「何を作らないか」を明確にすることで、コンセプトの一貫性を維持しています。
技術スタック
| 技術 | 用途 |
|---|---|
| React Native + Expo (Router) | クロスプラットフォームモバイルアプリ |
| TypeScript | 型安全なコードベース |
| Firebase Firestore | リアルタイムデータ同期 |
| Firebase Anonymous Auth | ログインハードル排除 |
| Cloud Functions | エール生成・バッチ通知 |
| Lottie | アニメーション |
| EAS Build | 本番ビルド(AAB) |