【個人開発】二児のパパエンジニアが絵本読み聞かせ記録アプリを作った


はじめに

先日、初めて個人開発で作った絵本読み聞かせ記録アプリ「ヨンデ」をリリースしました。
現在はAndroid版のみのリリースで今後はiOS版もリリース予定です。

今回は本アプリの紹介をさせてもらいつつ、本システムの全体構成やリリースに至るまでの経緯をまとめてみたいと思います。

これから個人開発でアプリを作ってみたい!という方に何か参考になることがあれば幸いです。

絵本読み聞かせアプリ「ヨンデ」の紹介

ヨンデは一言で言うと、「読んだ絵本を集めた電子アルバムを作成して、絵本を通して親子の思い出を残すためのサービス」です。

解決したかったこと

「娘との絵本の思い出を残してるの」

すべては妻のこの発言からアプリ開発がスタートしました。
我が家では僕の帰りが遅くなることもあり、妻が毎晩寝る前に、娘に絵本の読み聞かせをしてくれていました。

さらに、娘と読んだ絵本を楽天roomにコメントをつけて記録していたんですね。

ただ、楽天ROOMは絵本以外の商品も並んでしまうのがちょっと嫌。絵本だけのアルバムみたいなのが作れて、そこに思い出を残していけたらいいよねという話になり、今回のアプリ開発に至りました。

思い出と言えば、"写真"ですよね。我が家では、mixi社が作った「みてね」という子供の写真共有アプリを愛用しているのですが、月ごとに娘の写真が残せてこれが非常に見やすかった。(娘も自分の写真を見てはにやけてます。)

今回のアプリは、「みてね」のように写真ではないけど、絵本が際立つようなUI(画面)にすることで、絵本を写真を見るときのように振り返ることができればいいなと考えておりました。

妻だけでなく、毎日絵本の読み聞かせを頑張られている親御さんに使ってもらえると嬉しいですね。

アプリの特徴

①読んだ絵本をワンクリックで記録できる
②よく読まれている絵本をランキング化して表示

読んだボタンをタップすると記録され、アルバム画面に反映されます。

③読んだ絵本はアルバム感覚で振り返りできる

年月ごとにタブが作成され、アルバム感覚で読んだ絵本が振り返りできます。

④絵本にコメントが残せる

読んだ絵本に対して、子どもの反応や様子など自由にコメントが残せます。
また、SNSのような使い方はできませんが、他の利用者が投稿したコメントも確認することができます。

基本操作はNotionで作成し、アプリ内からも参照できるようにしました。

ライバルは公文です

もちろんすでに競合アプリがありました。

その代表格が公文のミーテ(←リンクを貼ってあげる優しさ)。

Android版は約1万ダウンロードされていますね。

ただ、実際にミーテを利用してみると…うーん、画面遷移やボタンなどのアクションのレスポンスが悪く、個人的にはこれを毎日の記録に使うのはちょっと…という印象。(大手にしてはダウンロード数が少ないのかそれとも需要がないのか??)

充実した機能では負けるが、レスポンスはこれより良いものを作れば勝負できるかなと思いました。

システムの全体構成

以降でもう少し細かく触れます。

アプリ開発言語はFlutter(Dart)を採用

Flutter採用は最初から決めていましたが、

  • 学習中の言語であり、いじっていて楽しかったこと
  • ひとつのコードでAndroid, iOS両方作れる
  • 今後さらに流行りそうな言語
  • 本業にも活かせそう

ということで、Flutterを採用しました。

本業ではFlutter開発案件にも携わることができ(僕がFlutterでやると決めただけですが)、結果的に個人開発とのかなりの相乗効果が得られました。

FlutterはAndroid, iOS両方作れちゃうので、一人で開発するのにも向いており、個人開発におすすめの言語(正確にはフレームワーク)です。

楽天ブックスAPIを採用

絵本検索時は、楽天ブックスが提供しているAPIを利用して絵本の情報を抽出しました。

解説不要と思いますが、こちらは非エンジニア向けにツイートしたものです。
ご参考まで。

Firestoreの構成


以下にフィールドの記載は抜きで、親子関係はインデントで表現してみました。

# フィールド抜き(コレクションとドキュメントのみ)
users: <collection>   # ユーザープロフィール
  userId: <document>
  children: <collection>  # お子さまプロフィール
    childId: <document>
      album: <collection>   # アルバム管理
        albumId: <document>   # -年月ごとにdocumentを作成
          albumIsbns: <collection>  # 当該年月の読んだ絵本の画像を管理(アルバム画面に表示するため)
            albumIsbnId: <document> 
      favouriteBooks: <collection>  # お気に入り絵本管理
        favouriteBookId: <document>
      memoryBooks: <collection>     # 歴代読んだ絵本一覧
        memoryBookId: <document> 
          coments: <collection>     # コメント
            commentId: <document>
      readBooks: <collection>   # 読んだ絵本一覧
        readBookId: <document>
  originalBooks: <collection> # 自分で登録した絵本一覧
    originalBookId: <document>
rankingBooks: <collection>  # ランキング管理
  rankingBookId: <document>
    reader: <collection> # 読んだ子の情報
      readerID: <document>
unsubscribed_users: <collection>  # 退会したユーザー
  unsubscribed_userId: <document>

すべては解説できませんが、以下のような構成です。

  1. アプリで読んだボタンをタップすると、readBooksコレクションに読んだ絵本が保存される。同時にcloud functionsにイベント通知。
  2. cloud functionsはイベント受信したら、年月ごとに管理されるアルバムおよびアルバムISBNコレクション、ランキングコレクションなどを更新する。
  3. 本にはISBNコードという一意の値が存在する。documentIDには適宜これを採用して、各ドキュメントと連携しやすい設計とした。
  4. ユーザーの子供ごとに保存しているコメントコレクションはCollectionGroupを使って読み出すことで、ユーザー間のコメントを抽出→アプリ内の"みんなのコメント"機能に使用。

NoSQLの独特なデータベースの取り扱いには苦戦しました。

僕が仕入れた情報では「Firebaseって簡単だよ」って感じですごく門戸を開いてくれてるイメージがありました。

確かにごく小規模のデータベースで間に合うならその感覚であってますが、少し凝ったことをしようと思うと、初めにしっかりスキーマ設計をしておかないと、あとで取り返しのつかないことになりかねない"ツンデレ仕様"となっておりました(デレが先だから"デレツン"ですね。どうでもいいですね)。

そもそもFirestoreのスキーマ設計において、解説記事もまだまだ不足していますね。
それだけベストプラクティス的な設計が難しく、実現したいサービスに合わせた設計が必要なのかなという印象です。

とはいえ、サーバを一から導入するより楽ですし、ログイン認証、リアルタイム同期などの欲しい機能が備わっており、Firebaseは個人開発においては強い味方となるサービスです。

開発で参考になったサイト・書籍

Firestore設計

書籍:実践Firestore (技術の泉シリーズ(NextPublishing)
Cloud Firestoreの勘所 パート1 — 概要
Firebase入門 フリマアプリを作りながら、認証・Firestore・Cloud Functionsの使い方を学ぼう!

セキュリティルール

公式サイト
【改訂版】 Firebase Cloud Firestore rules tips
本気でやりたい人のためのFirestore設計入門 - 超シンプルなTODOアプリ編
Cloud Firestoreの勘所 パート3 — セキュリティルール

Flutter状態管理・モデリング

udemy動画:Flutter & Firebase: Build a Complete App for iOS & Android

 ※すべての解説はありませんが、上記動画内で製作されているアプリのRiverpod版Projectも参考になります。

リリース準備

codemagic公式サイト
【Mac不要】FlutterアプリにFirebase SDKを組み込んでiOSとAndroidに実機配備する手順 - Codemagic編
FlutterでCI(Codemagic編)
flutter + firebaseで本番環境と開発環境を切り替える

製作期間

こちらのアプリは、開発~リリースまでに約6か月かかりました。

子育て世代は時間の確保に苦労するとはいえ、想定していたより多くの期間を要しました。

期間が延びるとどうしてもだれてくるし、挫折しやすいので、初めはもう少し短期間で開発できるアプリにしたほうが良かったのかも(機能を最小限に絞るなり、スマホ単体で完結させたりなど)。

そんな中、リリースするまで継続できた要因を挙げるとすれば、開発当初の画面設計ができたタイミングでTwitterの企画でパパママさんを中心にフィードバックを頂けたことは大きかったです。

そのときの企画はこちら。

第1回 絵本記録アプリの紹介

継続できた要因については、またの機会にまとめたいと思います。

今後の展開

  1. もう少しこのアプリを育てたい
    2021年8月現在のダウンロード実績は、20ダウンロードを超えたあたり。
    ライバルにはまだまだ程遠いので、今後も機能改善を図ってライバルに近づきたい。
    (子育て世代のエンジニアさんはぜひ使ってみてください♪)
  2. fooks + riverpodに置き換えてみる
    開発途中で学び、本業のプロジェクトでは導入済み。本アプリもトライしたい。