← トップへ戻る

本棚(hondana)

紙の漫画・書籍の蔵書を管理する iOS アプリ(Android 版は準備中)。Flutter 製。企画・設計・実装から App Store への申請までを個人で担当しています。


何を解決するアプリか

紙の漫画を買い続けていると「この巻はもう持っていたか」が分からなくなり、書店で同じ巻を買ってしまいます。1冊ずつ記録するだけでは、シリーズとして何巻が抜けているかは分かりません。

このアプリは裏表紙のバーコードを読むだけで登録が終わり、シリーズごとに所持していない巻を自動で検出します。


スクリーンショット

本棚 抜け巻の検出 書籍詳細
本棚 抜け巻 詳細

主な機能

  • バーコード登録 — 裏表紙の ISBN(EAN-13) をカメラで読み取り、書名・著者・出版社・表紙画像を自動取得。連続スキャン対応
  • シリーズ管理 — タイトルから巻数を推定してシリーズ化し、抜け巻を検出
  • 本棚の複数管理 — 用途別に本棚を分けて蔵書を整理
  • 読書管理 — 未読 / 読書中 / 読了、5段階評価、メモ
  • 手動登録 — バーコードのない本、書誌が見つからない本に対応

技術構成

区分 採用技術
フレームワーク Flutter / Dart
状態管理 provider
ローカル DB SQLite (sqflite)
外部 API openBD / Google Books API
バーコード読取 mobile_scanner
課金 in_app_purchase
対応 OS iOS 17.6 以降(App Store で公開中)
Android 7.0 以降(準備中)

設計上の判断

1. サーバーを持たず、端末内 SQLite で完結させた

蔵書データは端末内の SQLite にのみ保存し、アカウント登録もサーバーも持たない構成にしました。

蔵書管理は本質的に個人の手元で完結する用途で、同期を求める場面が限られます。サーバーを持たないので、サーバーの運用コストがかからず、利用者の個人情報も預からずに済みます。書誌の取得と購入以外は、オフラインでも動きます。

2. openBD を優先し、Google Books へフォールバックする二段構成にした

日本の書籍は openBD のカバレッジが高い一方、洋書や一部の書籍は取得できません。そこで openBD を第一候補、Google Books をフォールバックとし、さらに openBD で書誌は取れたが表紙画像だけ無いケースでは Google Books から表紙のみを補完しています。

また、openBD の series フィールドはシリーズ名ではなくレーベル名(例:「ジャンプコミックス」)が入るため、これはシリーズ名として使わず、タイトルからの推定に回しています。著者名に付いてくる生年(例:小畑,健,1969-)や「/著」のような役割表記も、表示前に落としています。どれも実データを確認した上で API の仕様に合わせた箇所です(詳しくは Zenn の記事)。

3. 巻数の推定を純粋関数として切り出し、テストで仕様を固定した

書籍タイトルの巻数表記は「ワンピース 107」「キングダム(73)」「SLAM DUNK 新装再編版 第20巻」のように揺れます。全角数字・全角括弧・全角スペース・第N巻 / N巻 / vol. といった表記差の吸収が必要です。ここは仕様が後から増え続ける場所なので、UI や DB から独立した純粋関数に切り出しました。

表記ゆれのパターンごとにユニットテストを用意して挙動を固定しており、新しい表記に対応する際も既存の判定が壊れないことを確認できます(詳しくは Zenn の記事)。

4. スキーマ変更をマイグレーションとして扱い、旧バージョンの DB を実際に開くテストを書いた

「本棚を複数持てる」機能を後から追加した際、DB スキーマの変更が必要になりました。個人開発でもすでに使っている人の蔵書データを壊さないことを前提に、v1 のスキーマを直接構築してから最新バージョンで開き、既存の本がデフォルト本棚に正しく移行されることを検証するテストを用意しています。

あわせて、新規インストールした DB と移行した DB で、shelf_id 列の定義を PRAGMA table_info で比べるテストも置いています。データの移行だけを見るテストでは、移行後の列に NOT NULL 制約が付いていないずれを見落としていたためです。ストア公開前に見つけて直しました(詳しくは Zenn の記事)。


テスト方針

UI を伴わないロジック層を対象に、壊れると実害が出る箇所を優先してテストしています。

  • series_utils_test.dart — 巻数・シリーズ名の推定と全角・半角の正規化(12ケース)
  • author_utils_test.dart — openBD の著者名の整形。役割表記・生年・没年の除去(6ケース)
  • database_migration_test.dart — 新規作成時のデフォルト本棚生成、v1 → v2 のデータ移行、新規作成と移行後で shelf_id 列の NOT NULL 制約が一致すること(3ケース)
  • cover_utils_test.dart — 表紙画像の補完と、Google の「画像なし」共通画像の判定(6ケース)
  • duplicate_scan_guard_test.dart — 同じバーコードの連続読み取りの抑止(5ケース)
  • purchase_provider_test.dart — 起動時の購入確認と、購入の復元(9ケース)

外部 API を叩くサービスは http.Client を注入できる設計にし、テスト時に差し替え可能にしています。


開発体制

個人開発(1名)。要件定義・画面設計・実装・テストに加え、ストア掲載文言、プライバシーポリシー・利用規約・特定商取引法に基づく表記のドラフト作成まで担当しています。

iOS 版は2026年10月に App Store で公開しました(App Store で見る)。Android 版は、Google Play の登録に必要な D-U-N-S 番号(企業識別番号)の発行待ちです。


連絡先