「パートナーと一緒に使えるアプリ」を作りたくて、クラウド同期に挑戦した話

AI・テクノロジー

些細な課題こそ、次の学びの入り口になる

前回、FOCUS LINE(フォーカスライン)というタスク管理アプリを作りました。自分の「脱線癖」という困りごとから出発して、AIと対話しながら形にし、GitHub Pagesで公開するところまで持っていった記録です。

あの経験で得たものは、アプリそのものだけではありませんでした。「自分の身近な課題を、自分で道具にできる」という感覚。それが一番大きかった。

だから次も、大きなテーマを探すのではなく、日常の中にある些細な「あったらいいな」を拾い上げることから始めました。

今回作ったのは、トコログ(TOCOLog)。パートナーを駅まで車で送迎した記録を共有管理し、月ごとにバス代相当額を自動集計するWebアプリです。


送迎とお金のやりとりという、小さな課題

現在、私は休職中です。収入が限られる中で、少しでも家計の足しになればという思いから、パートナーを駅まで車で送迎し、その代わりにバス代の相当額を受け取るという取り決めをしています。

ここで大事なのは、パートナーと家計を共にしていても、お金のやりとりをきちんと行うことで、お互いの気持ちの負担感をなくすという目的があること。「送ってもらって当たり前」でも「送ってあげてる」でもない。対等なやりとりとして記録し、見える化する。それが二人の間の心地よさにつながると考えました。

ただ、記録の方法が問題でした。

  • 「今月、何回送った?」と聞かれて、すぐに答えられない
  • スプレッドシートを開くのが面倒で、記録が抜ける
  • 片方だけが記録していると、もう片方は確認しづらい
  • バス代が値上がりしたとき、過去の計算をやり直すのが面倒

こういう「地味だけど毎月繰り返される手間」こそ、アプリにする価値があると思いました。


FOCUS LINEの次に何を作るか

FOCUS LINEを作ったとき、技術構成はシンプルでした。HTML、CSS、JavaScriptだけで構成し、データはブラウザのlocalStorageに保存。GitHub Pagesで無料公開。サーバーは使わない。

この構成には一つ、明確な限界があります。localStorageは端末ごとに独立しているということ。つまり、私のスマホで記録した内容は、パートナーのスマホには反映されない。

FOCUS LINEは「自分一人で使うタスク管理」だったので、それで十分でした。でもトコログは二人で使うアプリ。どちらが記録しても、もう一方の画面にリアルタイムで反映される必要がある。

ここに、FOCUS LINEからの技術的な進化のテーマがありました。

localStorage(端末内保存)から、クラウド同期へ。

新しい技術に挑戦する理由として、これ以上に自然な動機はないと思いました。


愛車トコットが名前をくれた

アプリの名前は最初「のりログ(NoriLog)」でした。「乗る」+「ログ(記録)」。悪くはないけれど、もう少し愛着の持てる名前にしたかった。

そこで思い浮かんだのが、送迎に使っている愛車——ダイハツ ミラトコット。丸みのあるフォルムと、落ち着いたミントブルーの車体。毎日この車でパートナーを駅まで送っているのだから、アプリの名前もここからもらおうと。

トコログ(TOCOLog)。トコット+ログ。

名前が決まると、デザインの方向性も自然に定まりました。ミントブルーを基調とした配色、ヘッダーにはトコットのシルエットをSVGで描いたアイコン、丸いヘッドライトと白いホイールキャップまで再現。アプリを開くたびに、自分の車が出迎えてくれるような親しみのある画面になりました。


「二人で使える」を実現するために必要だったこと

FOCUS LINEとトコログの技術的な違いを整理すると、こうなります。

FOCUS LINE(前作):

  • データ保存:localStorage(ブラウザ内)
  • 同期:なし(端末ごとに独立)
  • ユーザー:自分一人
  • 通信:不要(オフラインで完結)

トコログ(今作):

  • データ保存:Google Firebase(Firestore)+ localStorageバックアップ
  • 同期:リアルタイム(片方が記録すると、もう片方に即座に反映)
  • ユーザー:二人で共有
  • 通信:必要(クラウドとの通信)

見た目は似たようなWebアプリですが、裏側の仕組みはまったく違います。


Firebase という選択肢

クラウド同期を実現するために選んだのが、Google Firebase のFirestoreというデータベースサービスです。

Firebaseを選んだ理由はいくつかあります。

まず、無料枠が十分すぎるほど大きいこと。二人で使う送迎記録アプリ程度では、無料枠の上限に達することはまず考えられません。数百人、数千人規模で使ってようやく気になるレベルです。

次に、リアルタイム同期が標準機能として備わっていること。FirestoreにはonSnapshotというリスナー機能があり、データベースに変更があった瞬間に、接続しているすべてのクライアント(端末)に自動で通知が届きます。つまり、私のスマホで「行き」をタップした瞬間に、パートナーのスマホの画面も自動で更新される。ポーリング(定期的にサーバーに問い合わせる方式)ではなく、プッシュ型の通知なので、遅延もほぼありません。

そして、HTMLファイル一つで完結できること。Firebaseの JavaScript SDK をCDN経由で読み込むだけで、サーバーサイドのコードを一切書かずにクラウドデータベースが使えます。FOCUS LINEと同じく「HTMLファイル一つをGitHub Pagesに置くだけ」という構成を維持できたのは大きかった。

データ構造の設計

Firestoreに保存するデータは、3つのドキュメントだけです。

1. rides(送迎記録) 月ごとに日付をキーとして、「行き(outbound)」「帰り(inbound)」の真偽値を持つシンプルな構造。チェックが両方falseの日はデータを保持しないことで、容量を節約しています。

2. farePeriods(料金期間) バス代が変わるたびに「いつから・いくら」という期間を追加していく配列。ある日付の料金を計算するとき、その日付以前で最も新しい期間の金額を適用します。これにより、途中で料金が変わっても過去の記録はすべて当時の金額で計算されます。

3. settlements(清算状態) 月ごとの清算済み/未済みを管理するシンプルな真偽値。

すべてのデータを JSON 文字列としてFirestoreに保存し、読み込み時にパースする構成にしました。Firestoreのドキュメント構造をフルに活用する方法もありますが、このアプリの規模では「3つのドキュメントにまとめる」方がシンプルで、読み書きの回数も最小限に抑えられます。

localStorageとの二重保存

クラウド同期を導入しても、localStorageは残しました。理由はオフライン対応です。

一時的にネットが切れていても、localStorageにバックアップがあれば画面は正常に表示され、操作も可能です。ネットが復旧した時点でFirebaseに書き込まれ、もう片方の端末にも反映される。

ヘッダー右上に「☁️ 同期中」「⚠ オフライン」の表示を入れたのは、今どちらの状態なのかをユーザーが一目で確認できるようにするためです。


AIに教わりながら、Firebaseを導入してみた

FOCUS LINEの記事で「AIと作るというのは、こういう感じだった」と書きましたが、今回もまさにその延長でした。違うのは、今回はアプリのコードだけでなく、クラウドサービスの設定そのものをAIにガイドしてもらったということ。

Firebaseの導入は、大きく5つのステップに分かれていました。

ステップ1:Firebaseプロジェクトを作る

Googleアカウントでログインして、Firebase コンソール(https://console.firebase.google.com/)を開き、「プロジェクトを作成」を押す。名前を tocolog と入力して、あとはいくつかの選択肢を選ぶだけ。

ここで早速、迷いました。「Gemini を有効にしますか?」「Google アナリティクスを有効にしますか?」——聞き覚えのない選択肢が並ぶ。Claudeに聞いたら「個人の小さなアプリには全部オフでOKです」と即答。分からないことをその場で聞けるのが、AIと作る最大の利点だと改めて感じました。

ステップ2:データベースを作る

プロジェクトの中に「Firestore Database」というデータベースを作ります。ここでも「Standard/Enterprise」の選択が出てきましたが、Claudeに「Standardで十分」と教わり、そのまま進行。サーバーの場所は「asia-northeast1(Tokyo)」を選びました。日本から近いので速い、という理由もAIが教えてくれました。

ステップ3:設定情報を取得する

Firebaseが発行する「設定情報」——APIキーやプロジェクトIDなどが含まれた一連のコード——をコピーします。これをアプリのHTMLに貼り付けることで、アプリとクラウドデータベースがつながる仕組みです。

この設定情報の取得方法も、Claudeが「Webのマーク(</>)をクリックして、ニックネームを入力して……」と、画面の操作を一つずつ教えてくれました。スマホの小さな画面で操作していたので、ボタンの場所が分からない場面もありましたが、スクリーンショットを送れば「この画面ならここをタップしてください」とガイドしてくれる。まるで隣で一緒に画面を見てくれている感覚でした。

ステップ4:コードに組み込む

取得した設定情報をClaudeに渡すと、トコログのHTMLにFirebaseの読み込みコードと同期処理を組み込んでくれました。データの保存先がlocalStorageからFirestoreに切り替わり、リアルタイム同期のリスナー(onSnapshot)が追加される。

ここで一つ、予想外のエラーが出ました。画面が真っ白になり、ボタンが一切動かない。Claudeにスクリーンショットを送ると、すぐに原因を特定してくれました。Firebase SDKの読み込み方式の問題で、別の方式に切り替えることで解決。自分一人では原因の特定すら難しかったと思います。

ステップ5:GitHub Pagesにデプロイ

FOCUS LINEの時と同じ要領で、GitHubにリポジトリを作り、HTMLファイルをアップロードし、GitHub Pagesを有効にする。ここはもう一度やったことのある手順なので、スムーズに進みました。

ただし、最初はページが404エラーで表示されませんでした。原因は、GitHub Pagesの設定で「Branch」が「None」になっていたこと。これもClaudeに画面を見せながら解決。一度経験したはずの作業でも、細かい設定は忘れるものです。

公開後、自分のPCとスマホの両方でトコログを開き、片方で「行き」をタップしたら、もう片方の画面にも瞬時に反映された瞬間は、素直に感動しました。「あ、クラウド同期って、こういうことか」と。


セキュリティという現実と向き合う

Firebaseを導入して、FOCUS LINEにはなかった新しい問題に直面しました。セキュリティです。

localStorageなら、データはその端末の中にしか存在しません。でもFirestoreはクラウド上にあり、適切なルールを設定しないと、URLを知っている誰もがデータを読み書きできてしまいます。

Firestoreには「セキュリティルール」という仕組みがあり、「誰が」「何を」「どこまで」できるかを細かく制御できます。

最初は「テストモード」——つまり誰でも読み書き可能な状態で開発を進めました。次に「ログインした人だけ書き込める」ルールに変更しましたが、これだとアプリ側にGoogle認証機能を組み込む必要があり、毎回ログインする手間が増えます。

最終的に、こういう判断をしました。

「このURLを知らない限り、誰もアクセスできない。URLは二人だけで共有する。それで十分。」

技術的には完璧ではないけれど、実際の運用では問題ない。この判断ができたのは、FOCUS LINEの開発を通じて「完璧を目指して一人で抱え込むより、小さく作って早く外に出す」という感覚が身についていたからだと思います。

セキュリティの世界には「リスクをゼロにすること」と「リスクを許容可能な水準に管理すること」の違いがあります。個人開発では後者の感覚が特に大切だと感じました。


完成したトコログの全体像

完成したトコログの画面を紹介します。

カレンダー画面

月間のカレンダーが表示され、各日付に「行」「帰」の2つのボタンがあります。タップすると色が変わり、記録完了。もう一度タップで取り消し。1日あたり行き1回、帰り1回が最大です。

カレンダーの下に、その月の集計がリアルタイムで表示されます。行き・帰りの回数と合計回数、そして金額。

月別履歴画面

<!– 📸 画像2:月別履歴(清算未/清算済) –>

過去の月ごとの金額が一覧で見られます。各月に「清算未」ボタンがあり、お金を受け取ったらタップして「✓ 清算済」に切り替えます。これで「先月分、もう払った?」という確認が不要になります。

設定画面

バス代(片道)の変更と、アプリ内の使いかたガイドがあります。

バス代の変更機能は、最近のバス代値上げの頻度を考えて、最初から組み込みました。変更前の記録は以前の金額のまま計算されるので、過去の集計がずれる心配はありません。

使いかたガイド

設定タブ内にアコーディオン式の使いかたガイドを組み込みました。家からトコットに乗って駅へ向かうイラスト付きで、パートナーが初めて開いても迷わない構成にしています。


この経験から見えたこと

FOCUS LINEは「自分の困りごとを自分で道具にする」経験でした。

トコログは、その一歩先——「パートナーと一緒に使える道具を作る」という経験です。

技術的には、localStorageからFirebaseへの移行という、明確なステップアップがありました。クラウドデータベースの設計、リアルタイム同期の実装、セキュリティルールの設定。どれも初めての経験でしたが、「二人で同じデータを見たい」という具体的な動機があったからこそ、一つひとつの技術選択に迷いがなかった。

開発の進め方としても、学びがありました。FOCUS LINEの時は「まず動くものを作り、その後で人に見せる」という流れでした。今回は最初から「パートナーと一緒に使う」という前提があったので、仕様を決める段階から「使う人の視点」を意識できた。清算ボタンも、料金の日付別計算も、パートナーとの運用を想像したからこそ生まれた機能です。

そしてもう一つ。些細な課題をアプリにするという行為は、技術を学ぶための最も自然な入り口だと改めて感じました。

「Firebaseを勉強しよう」と思って教材を開くのと、「パートナーと記録を共有したいからFirebaseを使ってみよう」と思うのでは、同じ技術を学んでいても手触りがまったく違います。前者は勉強、後者は問題解決。私には後者の方が圧倒的に続きます。

自分の生活の中に「あったらいいな」は、探せばいくらでもあります。それをAIと一緒に形にする過程で、必要な知識や経験が一つずつ身についていく。大きなプロダクトを作ろうとしなくていい。身近な課題を大事にして、楽しみながら一つずつ。

次に何を作るかは、まだ決まっていません。でもきっと、日常の中の「ちょっと不便」から始まるはずです。


参考・このプロジェクトで使ったツール

Claude(Anthropic社の対話型AI)https://claude.ai/ 前作に続き、すべての開発をこのAIとの対話で行いました。仕様の整理からコードの実装、Firebase の導入ガイドまで、一貫して対話ベースで進めています。

Google Firebase(クラウドデータベース)https://firebase.google.com/ Firestoreを使ったリアルタイムデータ同期。無料枠(Sparkプラン)で運用。

GitHub Pages(無料ホスティング)https://pages.github.com/ FOCUS LINEに続き、GitHub Pagesを使ってURLひとつで公開。

GitHub(コード管理)https://github.com/ ソースコードの管理と公開に使用。

タイトルとURLをコピーしました