はじめに
この記事では、個人開発で作っている PWA アプリ 「CoupleOps」(一緒に暮らし始めたカップルが、ケンカとモヤモヤを減らすための毎日2分アプリ)の開発ログをまとめます。
前回までの Qiita 記事では、
- 最初のプロトタイプ作成
- Every Day / Weekly の心理ワーク設計
- AdSense の導入&下部バナー表示
あたりまでを書きました。
今回はそこから一歩進めて、
- データのフルバックアップ(Dexie + localStorage)
- 利用継続のための「今週のふりかえり」「来週のテーマ」
- 文言&プライバシーポリシーの見直し
- 研究ノート PDF 出力まわりの改善
といった 「まだ AI を使っていない部分」 の改善に集中した回の振り返りです。
アプリのざっくり紹介
-
対象:
- 一緒に暮らし始めたカップル / 夫婦
- ケンカやモヤモヤを減らしたいけど、ガチのカウンセリングはまだハードル高い人
-
コンセプト:
- 1日2分で「負荷」「感謝」「承認」「If-Thenプラン」を記録
- 週に1回ふりかえりをして、次の1週間のテーマを決める
-
技術スタック:
- Vite + React + TypeScript
- IndexedDB (Dexie) + localStorage
- Cloudflare Pages でホスティング
- AdSense で下部バナ―広告
実際に触れるβ版はこちら(※内容は今後変わる可能性あり)
👉 https://coupleops-app.pages.dev
1. データのフルバックアップをどうするか問題
背景
最初の実装では、
- localStorage の一部キーを JSON で出力 / 読み込み
- Dexie(IndexedDB)のワークフローデータはバックアップされない
という状態でした。
このままだと、
- 機種変更時に記録が全部消える
- β版から正式版に移行するときも不安
なので、「アプリ内の心理ワーク記録を丸ごとバックアップしたい」 という課題が出てきました。
方針:バージョン付きのフルバックアップ JSON
今回決めた仕様はこんな感じです。
// バックアップ JSON のトップレベル
{
"version": 1,
"exportedAt": "2025-11-22T08:25:00.000Z",
"data": {
"localStorage": { /* 端末内キーのスナップショット */ },
"workflows": {
"entries": [ /* Dexie の WorkEntryRecord[] */ ]
}
}
}
``
ポイントは:
- `version` フィールドを必須にして、将来のフォーマット変更に備える
- `localStorage` と `workflows.entries` を 1 つのファイルにまとめる
- 旧フォーマット(version なし)の JSON も、最低限 localStorage だけは復元できるようにする
### 実装メモ
- `src/utils/backup.ts`
- `collectFullBackupSnapshot()`
- localStorage のダンプ(既存実装を流用)
- Dexie から `WorkEntryRecord[]` を `listAllEntries()` 的な関数で取得
- `restoreFullBackupSnapshot(payload)`
- `version` を見て v1 / legacy を分岐
- v1 の場合は Dexie の既存 entries をクリアしてから `bulkPut`
- `src/components/Settings/DataExport.tsx`
- 「JSON をダウンロード」 → `collectFullBackupSnapshot()` を呼び出し
- 「JSON を読み込む」 → `restoreFullBackupSnapshot()` を呼び出し
### 実際の動作確認
1. Daily Reset を1件記録
2. 設定 > データエクスポート から JSON をダウンロード
3. JSON の中身に
- `version: 1`
- `data.localStorage`
- `data.workflows.entries[0].payload`(負荷レベル / 感謝 / If-Then)
が入っていることを確認
4. その後、データを少し変えてから JSON をインポート → 元に戻るか確認
ここまで問題なく動いてくれたので、一旦「フルバックアップ v1」として固定しました。
---
## 2. 継続利用のための「今週のふりかえり」と「来週のテーマ」
### 課題:毎日アプリを開いてもらう理由づけ
心理学的には、
- 「行動ログをつける」だけだと、だんだん飽きてくる
- 代わりに「次の一週間をうまく過ごすための手がかり」が見えると続きやすい
という前提があります。
そこで、ホーム画面に **「今週どれくらい Daily Reset ができたか」** と **「来週のテーマ」** を出すことにしました。
### 実装イメージ
- `getWeeklyDailyResetStats()` で、今週の Daily Reset 実施回数を集計
- Home (`Welcome.tsx`) で:
```tsx
今週のふりかえり Daily Reset:{count} / 7 日
-
週次レビュー完了時に、ざっくりした来週テーマを生成
- 例:「負荷レベルが高めの日が多かった → 来週は『ひとり時間の確保』」
-
localStorageにco_nextWeekThemeとして保存し、Home で表示
🎯 来週のテーマ
{nextWeekTheme}
使ってみた感触
- 「今週 3/7 日できてるなら、来週は 4/7 日を目指そう」みたいに、小さな目標が立てやすい
- 週次レビュー → 来週テーマ連携で、「やって終わり」ではなく「次に活きる」感が出る
まだアルゴリズムはかなりシンプルなので、ここは今後 AI コーチと組み合わせて強化したいところです。
3. 研究ノート PDF の沼から抜けるまで
問題:日本語フォント + jsPDF がつらい
アプリ内には、認知行動療法やスキーマ療法などの「研究ノート」をまとめたページがあり、そこを PDF で出力できるようにしています。
最初は jsPDF + 日本語フォント(Noto Sans JP)で素直に実装したのですが、
- Unicode cmap がない
- widths が undefined
- 文字化け or エラーで PDF 生成失敗
と、かなり泥沼になりました。
割り切り:html2canvas で「画面キャプチャ PDF」にする
最終的には、
-
html2canvasで研究ノート部分の DOM を画像としてキャプチャ - jsPDF に
addImageして A4 縦の1ページに収める
という 「画像として出力する」方針 に切り替えました。
メリット:
- フォントや文字化けを気にしなくていい
- ブラウザで見えているレイアウトそのままを残せる
デメリット:
- 拡大すると文字が少しぼやける
- PDF 的なテキスト検索はできない
しかし、「まずはユーザーが印刷・保存できること」を優先して、今回はこの形で一旦着地しています。
4. 文言とプライバシーポリシーの見直し
Welcome ヘッダのコピー
ターゲットをもう一度はっきりさせるために、Home のヘッダコピーを次のように変更しました。
一緒に暮らし始めたカップルが、
ケンカとモヤモヤを減らすための、毎日2分アプリ。
これに合わせて、Qiita 記事や README も少しずつトーンを揃えています。
プライバシーポリシー
機能追加に合わせて、プライバシーポリシーも更新しました。
特に追記したのは以下の3点です。
-
収集する情報と保存場所
- 基本は端末内の localStorage / IndexedDB
- サーバー側には行動ログを保存していない
-
同意が必要な機能と外部送信
- ユーザー自身がバックアップ JSON をクラウド等に保存する場合、その管理はユーザー側
-
免責事項(非医療・非診断)
- 本アプリは医療行為ではなく、診断・治療を提供するものではない
これで、「端末内完結だけど、バックアップは自分でクラウド等に置ける」という構造との整合性が取れました。
5. AdSense 下部バナーまわりの調整メモ
詳細は別記事で書きましたが、今回の範囲では:
- 固定サイズ(320x50)のバナーでスマホ画面が埋まらないよう CSS を調整
- Cloudflare Pages の環境変数 +
.envのVITE_ADS_PUB_ID/VITE_ADS_SLOTで広告ユニットを切り替え - プライバシーポリシー画面にだけは広告が被らないよう、
padding-bottomを増やす
といった微修正も行いました。
6. やってみての振り返り
良かった点
- フルバックアップが入ったことで、「記録が消える怖さ」がだいぶ減った
- Home に「今週のふりかえり」「来週のテーマ」が出ることで、毎日の記録と週次レビューがつながった
- 研究ノート PDF はかなり試行錯誤したが、「画像出力」という現実解で一旦ユーザー価値を出せた
課題として残っているところ
- バックアップ JSON をどこまで暗号化するか(端末内 / 外部クラウド)
- Ad ブロック時の見た目や収益バランス
- 週次レビュー → 来週テーマのロジックがまだ単純
ここは次のフェーズ(AI コーチ導入)と合わせて、もう一段アップデートしていきたい部分です。
7. 次回以降:AI コーチをどう使うか
この記事ではあえて 「AI を使っていない改善」 だけをまとめましたが、次のステップとしては:
- 無料枠を活かした、1日数回までの AI コーチ(If-Then プランや感謝文の提案)
- ユーザー自身の API キー利用 vs アプリ側でまとめて負担、どちらがいいか
- 「毎日2分」の中で AI に手伝ってもらうとしたら、どんな対話が一番気持ちいいか
などを考えています。
このあたりは、また実装が進んだら別記事でまとめる予定です。
まとめ
-
CoupleOps は「一緒に暮らし始めたカップルのケンカとモヤモヤを減らす」ことを狙った 1日2分アプリ
-
今回は AI 以外の部分を中心に、
- フルバックアップ
- ホーム画面でのふりかえり&来週テーマ
- 研究ノート PDF 出力の現実解
- 文言・プライバシー周りの整備
を行った
-
次のステップは、ここで整えた土台の上に「AI コーチ」をどう乗せるか、というフェーズ
ここまで読んでいただきありがとうございました!
アプリ自体は以下で公開中です
- アプリ:https://coupleops-app.pages.dev
- 前回までの Qiita 記事:AIエージェントと一緒に、個人開発PWAに「テーマ切替」と「下部固定AdSenseバナー」を入れた話
フィードバックや「こんなワークがあったら使いたい」などのコメントもお待ちしています🙌