Skip to content
99ersstudio
All work
Mobile Apps/Store-pending

Verein App

Offline-first DSGVO-konformer Vereinsmanager: members, fees, events, docs, announcements. Free under 25 active members.

46
tests
6a
phases
25 mbr
free under

The problem

A 30-member Schützenverein or Kleingartenverein does not need a SaaS subscription, a six-figure ERP, or a Steuerberater-grade audit trail. They need a phone-shaped tool that holds the Mitgliederliste, tracks who paid the Jahresbeitrag, schedules the Jahreshauptversammlung, and exports a CSV when the Kassenwart asks for it — all in German, all DSGVO-konform, and ideally without a backend that can leak. The free tier of every commercial alternative is either crippled or evaporates the moment the club crosses a member count.

How we built it

  1. 01Built every feature offline-first against SharedPreferences JSON repositories — MemberRepository, FeeRepository, PaymentRepository, EventRepository, AnnouncementRepository, DocumentRepository — so the entire CRUD surface works on a plane with no signal.
  2. 02Modelled fees properly: MembershipFee plus a separate Payment with four statuses (offen, bezahlt, ueberfaellig, erlassen) and a PaymentStatusEngine that derives effectiveStatus from due date vs. today — the UI never needs to ask which status to render.
  3. 03Wrote a recurrence generator for events (weekly / biweekly / monthly with month-end clamping) plus an EventDetailScreen with per-member RSVP SegmentedButton. RSVP counts roll up into the Dashboard and the upcoming-events tab.
  4. 04Shipped DE-formatted CSV export — semicolon-separated, comma decimals, proper escaping — for members and year-filterable payments, handed to the system share sheet via share_plus. The Kassenwart pastes the result straight into Excel.
  5. 05Added a free-tier gate (PremiumController + freeTierExceededProvider) that caps the free experience at 25 active members, with upgrade banners on Dashboard and Settings. The premium toggle persists locally; the actual paywall (RevenueCat) and the cloud-sync path (Supabase) wait for credentials.

Outcome

Phases 1–5 plus 6a shipped — feature-complete offline. 46 of 46 tests pass, flutter analyze clean. UI is German-only, includes a Haftungsausschluss in Settings, and never makes a network call. Six routes, three audiences for announcements, six document categories, and a Dashboard wired to live counts.

Stack

FlutterDartRiverpodGoRoutershare_plus

Flutter / Dart · Riverpod for state · GoRouter for navigation · SharedPreferences JSON repositories · Material 3 with a green seed (light + dark) · share_plus for CSV / share-sheet handoff · zero backend until Phase 6b.

Next up

Phase 5b: real Datei-Upload via file_picker + storage permissions. Phase 6b: optional Supabase auth / database / storage sync (credential-blocked). RevenueCat for the live paywall once a club commits.

More case studies