Civiqapp architecture

Civiq app architecture

How the Flutter app is put together: the paths a request takes, the flows behind each feature, and the reasoning behind the design. Everything here was derived directly from the current source in lib/.

Civiq lets citizens look up their elected representatives — local through national — from GPS or a searched location, see office locations on a map with district boundaries, contact representatives through official channels, and discuss civic matters in district-scoped community hubs. The app talks to a single custom Go backend; every request to it is gated by hardware-backed device attestation, with user accounts layered on top for the features that need identity.

Three decisions shape almost everything else in this codebase. First, the server is the only data authority, but the app is built to feel local: congressional data is synced into SQLite behind SHA comparisons, so the common path renders entirely from disk and the network is consulted only to ask "has anything changed?". Second, no request reaches the server anonymously — an attestation ceremony runs before the first frame of real UI, and its headers ride on every call. Third, state that matters is owned by services registered in Provider; widgets stay thin and re-render off notifier changes rather than holding data themselves.

Documentation map

The system at a glance

Layered architecture diagram: pages and widgets over services, over the API client and SQLite, over the Civiq backend server
The layer model. Widgets reach services through Provider; services own all API and database access.

Reading these pages

Each page opens with the flow diagram, then explains the sequence and — more importantly — why it works that way. Design decisions that are easy to trip over (why the query cache key embeds a dataset version token, why iOS signs every request but Android doesn't, why crash reports need a session marker) get called out where they live. Exact endpoint paths, storage keys, TTLs, and limits are collected in reference tables so the prose can stay readable.

Everything is static: diagrams are pre-rendered SVG and the stylesheet is local, so these files can be read offline, from a git checkout, or attached to a ticket without any network dependency.

Companion repo: the Go backend (civiq-backend-svr) maintains its own architecture documentation. The API contract described here must stay consistent with that repo; cross-repo changes belong in both decision logs.