Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

invoiceninja/flutter

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

282 Commits
282 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Invoice Ninja - Beta

v2 client application for Invoice Ninja.

Desktop Apps

Mobile Apps

Table of Contents


Setting up the app

# 1. Enable the repo's pre-commit hook (formats staged Dart, mirrors CI)
git config core.hooksPath .githooks

# 2. Install dependencies
flutter pub get

# 3. Generate freezed / json_serializable / drift code
dart run build_runner build --delete-conflicting-outputs

# 4. Run (pick a device)
flutter run -d macos      # or -d chrome, or an iOS simulator

Don't have an Invoice Ninja backend? Test against the demo server:

  • URL: demo.invoiceninja.com
  • Email: demo@invoiceninja.com
  • Password: Password0

To avoid retyping credentials, copy dev.json.exampledev.json and run with --dart-define-from-file=dev.json (debug/profile only; release builds tree-shake it). macOS entitlements, platform targets, and the web/WASM assets are documented in docs/setup.md.

Application architecture

Layered MVVM: ChangeNotifier + ListenableBuilder only.

View (StatelessWidget)
  └─ ViewModel (ChangeNotifier)
       └─ Repository (single source of truth per entity)
            ├─ Drift database (local state, watched by streams)
            ├─ Outbox (offline mutation queue)
            └─ Service (HTTP client → /api/v1/...)

Drift is the only thing the UI reads from: the network writes into Drift, the UI watches Drift. Every write goes through the outbox, so the app keeps working offline; mutations reconcile with the server later via a strictly-ordered, idempotent drain loop. Every list is scoped by company_id (multi-company), and on native platforms Drift sits on SQLCipher (encrypted at rest).

Project structure

lib/
├── main.dart         boot sequence (DI, restore, runApp)
├── app/              DI bag, router, theme, design tokens, env
├── data/
│   ├── models/       freezed domain models + API DTOs
│   ├── services/     HTTP clients (one per entity + shared ApiClient)
│   ├── repositories/ single source of truth per entity
│   └── db/           Drift database, DAOs, tables
├── domain/           entity types, registry, sync dispatchers
├── ui/
│   ├── core/         generic list/detail/edit scaffolds + shared widgets
│   └── features/     feature folders (auth, clients, products, …)
├── l10n/             localization delegate + supported locales
└── utils/            Formatter, parsing helpers, etc.

Every entity follows the same shape under data/ and ui/features/. When in doubt, mirror Client.

Documentation

Code generation

Regenerate freezed models, JSON serializers, and Drift code after editing any annotated source:

dart run build_runner build --delete-conflicting-outputs

Tests

flutter analyze              # static analysis
flutter test                # unit + widget + repository-contract suite
flutter build web --wasm    # the authoritative web compile gate

Integration tests (integration_test/) boot the real app and take over the foreground. Let CI run them; don't run them during a focused session. The on-request procedure is in docs/integration-tests.md.

Screenshots

The images at the top are generated, not hand-captured, produced by integration_test/screenshots_test.dart, which boots the real app (web) against the demo server and captures each marketing screen. This is a local, on-demand task (needs chromedriver):

bash tools/capture_screenshots.sh   # writes PNGs into samples/screenshots/

Credits

https://github.com/invoiceninja/invoiceninja/tree/v5-develop#credits

Contributions

We gladly accept contributions! To get involved, join our Slack group or Discord server.

License

See LICENSE.txt.

About

Invoice Ninja: Desktop/mobile admin portal built with Flutter

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.