釣りアプリ Angla を Web / Android / iOS で公開するまでにやったこと
Flutter の釣りコンディションアプリを公開するまでの全体像。AI プロキシ、ストア、日次バッチの役割分担。
釣りコンディションを見たいとき、天気アプリと潮汐サイトとSNSを行き来するのが面倒だった。なので自分用に作り始めたのが Angla です。いまは Web と Android、iOS で公開しています。
この記事は「全体像」のハブです。細かい実装はあとから個別記事に分けます。
何をするアプリか
Angla は、釣り場の天気・潮まわりの情報をまとめて見られるアプリです。加えて次のような機能があります。
- AI による釣りのアドバイス(今日〜明後日)
- 釣果・セッションの記録
- 写真からの魚種推定(危険種の注意つき)
- 公開できる釣果・トリップページ
作った動機はシンプルで、「自分が毎日使う画面を、自分の判断で持てるようにする」ことでした。
技術スタック(ざっくり)
役割ごとに分けています。
| 層 | 使っているもの |
|---|---|
| クライアント | Flutter(Web / Android / iOS) |
| 認証・DB | Supabase(Auth / Postgres / Storage) |
| AI | VPS 上の Node(Express)プロキシ経由で Gemini |
| 地図・天気 | Google Maps、Open-Meteo、気象庁の公開データなど |
| 収益(アプリ) | AdMob(バナー・リワード) |
ポイントは AI の API キーをアプリに入れない ことです。クライアントは自前のプロキシを叩き、キーはサーバー側だけに置きます。詳細は VPS プロキシで Gemini を呼ぶ話 に書きました。
公開の進め方
一気に全部を完璧にしてから出すのではなく、使えるところから出しています。
- Web: まず angla.jp で触れるようにする
- Android: Play で公開し、広告や権限まわりを実戦で直す
- iOS: App Store 審査を通し、広告やディープリンクを後から揃える
ストア公開後も、「ホームの導線が多すぎる」「バナーが FAB に被る」「キャッシュで古い JS が残る」みたいな、出してから分かる問題が続きました。個人開発では、この“出してから直す”が本番の学習になります。
日次バッチと CI の役割分担
Angla には、地方ごとの釣行スコアを毎日作るバッチがあります。最初は GitHub Actions の定期実行で回していましたが、無料枠を食いつぶす主因になったので、定時実行は VPS の cron に移しました。
いまの分担はだいたいこうです。
- コード変更時の Web デプロイ → GitHub Actions
- Android AAB → 手動の workflow
- 日次スコア → VPS cron(Dart SDK のみ。Flutter 自体は VPS に入れない)
- iOS TestFlight → 手元 Mac のスクリプトが正本(macOS ランナーは高い)
「便利だから全部 Actions」は、個人アカウントだと普通に破綻します。枠が戻っても、日次スコアの schedule は戻さない方針です。詳細は GitHub Actions から VPS cron へ移した話 にまとめています。
つまずきやすいところ(予告)
ハブなので、ここでは名前だけ挙げます。
- Flutter Web の
main.dart.jsキャッシュ - App Links / Universal Links の Content-Type や証明書まわり
- AdMob の審査が「ストア公開前だと進まない」こと
- ゲスト向け AI とログイン済みセッションを混線させない設計
- Neon や Supabase など DB 周りの接続罠(横断インフラ側)
個別に書いたら、この記事からもリンクを増やしていきます。
いまの立ち位置
Angla は「完成して終わり」ではなく、公開しながら直しているプロダクトです。このブログでは、うまくいった構成だけでなく、枠不足・審査・キャッシュ・広告の重なりみたいな、地味に痛い話も書いていきます。
アプリ自体はこちらです。
https://angla.jp