Cross-platform mobile app for relationship-based civic outreach campaigns
A Flutter mobile app that helps campaign volunteers match their own phone contacts against public electoral roll records through a swipe-based triage flow, with server-driven message templates and native SMS handoff so outreach sends from the volunteer's own number.
Campaign outreach has historically meant cold contact from a purchased list — calls and doorsteps from someone the recipient has never met — while relationship-based organising, a message from someone already in the recipient's contacts, converts far better but has no operational support. A volunteer's phone holds hundreds of contacts with no indication of who is registered or who would benefit from a reminder, and matching an informal address-book entry to a formal electoral record is a genuinely hard identity-resolution problem where a wrong match means contacting the wrong person about their voting record — not a minor bug but a reputational incident.
Deliberately kept the human in the matching loop rather than auto-matching contacts to records: the app narrows candidates aggressively from whatever the address-book entry already contains, re-running the search as the volunteer confirms additional detail — a region, an approximate age, a birthday — and requires an explicit tap to confirm. Automation was the wrong instinct here because the volunteer already holds the knowledge that resolves the ambiguity; a common surname with no other qualifier is handled as its own recognised state prompting refinement, rather than dumping an unusable number of candidates onto the screen.
Swipe-based triage lets a volunteer queue a contact for matching or set it aside, with both decisions persisted locally and already-matched contacts subtracted server-side, so the working list visibly shrinks rather than resetting to the same hundreds of contacts every session. All of the campaign's voice — tab labels, screen titles, per-contact prompts, and the message body itself — is delivered by the API and keyed by action type with sensible built-in defaults as fallback, so re-wording an entire outreach programme is a backend change rather than a release.
Outreach opens the device's own SMS composer with the message pre-filled, so it sends from the volunteer's own number rather than a platform shortcode — the entire premise of relationship-based organising. Address-book contents never leave the phone; only opaque contact identifiers and confirmed associations are exchanged with the backend, and the whole thing was built from one Dart codebase so both mobile platforms shipped from a single release process.
Relationship-based outreach became practical on a phone, turning an unstructured personal address book into a short, prioritised working list, and matching accuracy stayed protected by design because the person who actually knows the contact makes the final call rather than an algorithm guessing. Campaign messaging can be revised at campaign speed — wording, labels and templates change centrally with no app release or store review — and outreach retains its personal character, arriving from the volunteer's own number through the device's own messaging rather than from a platform. Both mobile platforms were served from one codebase, keeping delivery and ongoing maintenance proportionate to the product's scope.
Something holding you back?
New build, rebuild, or adding AI to what you already have — I'll take a look and give you an honest perspective.