Mobile Application

Fishing with Friends

FlutterSupabasePostgreSQLDartiOSAndroidOffline-first

By the Bunshin Development Studios Team · May 2026

The product

Fishing with Friends is an iOS and Android app for recreational anglers — catch logging, trip tracking, and live tournaments with friends. We built it in-house at Bunshin as a full commercial product, shipped to the App Store and Google Play in spring 2026.

The brief had two requirements that had to ship together: genuinely useful to a solo angler on a Tuesday, and compelling enough during a live tournament that they'd actually invite people to it. A logbook without the social hook is a notes app. Social features without solo value means the app only works when people already have friends on it. Both had to be real from day one.

The social model is friends-only throughout. No public feed, no public profiles, no public discovery. Every catch is visible only to confirmed friends — enforced at the database level, not as a client-side filter. This decision was foundational and propagated to every feature that followed.

Catch detail screen showing fish species, weight, and photo
Catch detail — hero product shot
Live tournament leaderboard updating in realtime
Live tournament leaderboard
Trip summary with photo grid and catch statistics
Trip summary with photo grid

Where it gets hard

Three categories of problems in this build don't have obvious solutions. We solved all three before any of them were features.

Offline in the field. Fishing happens where phones don't have signal. "Log a catch" is exactly the feature that gets used in the middle of a lake or a remote river. We built the app so that every feature works without connectivity — catches, photos, stats, maps — and syncs automatically when signal returns. No loading spinners. No error states. No data lost on the boat. No UI screen in the app was ever written to handle an offline state, because none of them see one.

Privacy that can't be circumvented. Friend-scoped visibility is enforced at the database layer — not as a UI rule that a determined developer could route around. A raw query against the catches table still can't return another user's data. When we added tournaments later, the same pattern held: competitors see what they need to see during a competition without touching the underlying private records.

Live competition at scale. Tournament leaderboards need to update when entries are approved — without a page refresh, and without anyone waiting. We wired real-time updates across the full tournament flow without compromising the privacy model. The two requirements don't naturally coexist; making them work together required deliberate architecture.

Offline-first sync architecture — catches queue locally and drain to the server on reconnect

How we delivered it

Seven milestones, each planned when the previous one shipped. The core experience came first — the visual system, then real catch persistence end-to-end, then the social and competitive layers, then the storytelling and statistics layer, then offline sync.

Offline sync shipped last, after the rest of the UI was stable. That sequencing was intentional: by the time the sync layer landed, zero existing screens had to change. The architecture made it additive rather than disruptive.

Each milestone extended the integration test suite of the previous one. The privacy contract was tested at every level of the stack from the beginning — not added as a compliance check at the end. By the time tournament features shipped, we had assertions that verified the access model held across every new surface.

What this demonstrates

FWF is a production product on two app stores, built by the same team that works on client projects. The problems in this build — offline reliability, database-layer privacy, real-time competition — show up constantly in serious software: field tools, healthcare platforms, logistics, anything running where connectivity or data access can't be assumed.

Different domain. Same constraints.

Stack: Flutter · Supabase · PostgreSQL · Dart · iOS · Android

Work with us

Have a project with similar constraints?

Reach out and let's talk. For serious prospects, we also share the full technical case study — architecture decisions, implementation patterns, and the edge cases we hit along the way.

Not posted publicly. Shared after a discovery call.

Start the conversation →
← All Projects