Dead-simple subscription tracker for iOS, built with Flutter/Cupertino widgets. Subctrl keeps tabs on recurring costs, converts currencies automatically, and sends optional local reminders before renewals hit.
- Track subscriptions with local storage backed by Drift (
subctrl.db). - Automatic currency conversion via Yahoo Finance rates with historical seeds to keep analytics stable offline.
- Analytics tabs for monthly burn, category totals, and long-term spend trends.
- Local, timezone-aware notifications driven by
LocalNotificationsService. - Clean Architecture split into presentation, application, domain, and infrastructure layers.
- Enforced code coverage (70%+) through the GitHub Actions workflow.
lib/
├─ presentation/ # UI, view models, localization
├─ application/ # Use cases and dependency wiring
├─ domain/ # Pure business logic + repository interfaces
└─ infrastructure/ # Drift database, currency clients, platform services
lib/main.dartboots the tabbed UI and wires dependencies.lib/application/app_dependencies.dartregisters repositories, use cases, and disposes theYahooFinanceCurrencyClient.- Data lives in
lib/infrastructure/persistence/database.dart(schema version 1 stored assubctrl.dbin the app documents directory).
- Prereqs: Flutter 3.38.5 (matches CI), Dart SDK ^3.10.3, Xcode for iOS simulator/device builds.
- Install deps:
flutter pub get
- Run the app:
flutter run
- Configure notifications (optional): ensure the iOS simulator/device has notification permissions enabled so local reminders can fire.
Static policy/support pages for App Store review live in docs/. The folder now
contains a minimal Jekyll setup (_config.yml, _layouts, and assets) so
Markdown pages gain HTML wrappers when GitHub Pages builds the gh-pages
branch. The Publish Docs workflow pushes the folder to gh-pages only when a
commit touching docs/ lands on master, so publishing simply means editing
Markdown with the required front matter (layout, title, permalink) and
pushing your change. Preview the pages locally with any static server (they
render as plain Markdown locally) or let GitHub Pages handle the Jekyll build.
All unit and widget tests run through flutter test --coverage, and coverage
must stay above 70%. Run locally with:
flutter test --coverageMIT © Denis Dementev


