0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【個人開発】一緒に暮らし始めたカップル向け「毎日2分アプリ」をここまで作って学んだこと

Posted at

はじめに

この記事では、個人開発で作っている 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 日
  • 週次レビュー完了時に、ざっくりした来週テーマを生成

    • 例:「負荷レベルが高めの日が多かった → 来週は『ひとり時間の確保』」
  • localStorageco_nextWeekTheme として保存し、Home で表示

🎯 来週のテーマ
{nextWeekTheme}

使ってみた感触

  • 「今週 3/7 日できてるなら、来週は 4/7 日を目指そう」みたいに、小さな目標が立てやすい
  • 週次レビュー → 来週テーマ連携で、「やって終わり」ではなく「次に活きる」感が出る

まだアルゴリズムはかなりシンプルなので、ここは今後 AI コーチと組み合わせて強化したいところです。


3. 研究ノート PDF の沼から抜けるまで

問題:日本語フォント + jsPDF がつらい

アプリ内には、認知行動療法やスキーマ療法などの「研究ノート」をまとめたページがあり、そこを PDF で出力できるようにしています。

最初は jsPDF + 日本語フォント(Noto Sans JP)で素直に実装したのですが、

  • Unicode cmap がない
  • widths が undefined
  • 文字化け or エラーで PDF 生成失敗

と、かなり泥沼になりました。

割り切り:html2canvas で「画面キャプチャ PDF」にする

最終的には、

  1. html2canvas で研究ノート部分の DOM を画像としてキャプチャ
  2. jsPDF に addImage して A4 縦の1ページに収める

という 「画像として出力する」方針 に切り替えました。

メリット:

  • フォントや文字化けを気にしなくていい
  • ブラウザで見えているレイアウトそのままを残せる

デメリット:

  • 拡大すると文字が少しぼやける
  • PDF 的なテキスト検索はできない

しかし、「まずはユーザーが印刷・保存できること」を優先して、今回はこの形で一旦着地しています。


4. 文言とプライバシーポリシーの見直し

Welcome ヘッダのコピー

ターゲットをもう一度はっきりさせるために、Home のヘッダコピーを次のように変更しました。

一緒に暮らし始めたカップルが、
ケンカとモヤモヤを減らすための、毎日2分アプリ。

これに合わせて、Qiita 記事や README も少しずつトーンを揃えています。

プライバシーポリシー

機能追加に合わせて、プライバシーポリシーも更新しました。

特に追記したのは以下の3点です。

  1. 収集する情報と保存場所

    • 基本は端末内の localStorage / IndexedDB
    • サーバー側には行動ログを保存していない
  2. 同意が必要な機能と外部送信

    • ユーザー自身がバックアップ JSON をクラウド等に保存する場合、その管理はユーザー側
  3. 免責事項(非医療・非診断)

    • 本アプリは医療行為ではなく、診断・治療を提供するものではない

これで、「端末内完結だけど、バックアップは自分でクラウド等に置ける」という構造との整合性が取れました。


5. AdSense 下部バナーまわりの調整メモ

詳細は別記事で書きましたが、今回の範囲では:

  • 固定サイズ(320x50)のバナーでスマホ画面が埋まらないよう CSS を調整
  • Cloudflare Pages の環境変数 + .envVITE_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 コーチ」をどう乗せるか、というフェーズ

ここまで読んでいただきありがとうございました!

アプリ自体は以下で公開中です

フィードバックや「こんなワークがあったら使いたい」などのコメントもお待ちしています🙌

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?