Flutter has been on our Tech Stack for more than three years now and since then, we’ve built a solid team of cherry-picked Flutter developers that can deliver quality apps. In the meantime, this team was working on tailor-made processes and polishing quality standards. 

This post will show you how we ensure a high quality standard of developed Flutter projects

What You Will Find Here

  • Overview of UI goodies built into Flutter 
  • Approach to CI/CD of Flutter apps
  • Usage tips of testing utilities provided by Flutter framework team
  • The app we’ve recreated to play around with

Our Template

For a faster development kick-off, our Flutter team decided upon a few crucial app aspects and prepared an app template.

The template features:

  1. Internationalization. Apps compete in the global market and supporting users’ native language can be a deciding factor for picking our app rather than competition. We start with English, but can easily add any other language support.
  2. Changelog. For an easy end-user release notes creation, we keep a list of updates made to specific app versions.
  3. Architecture Decision Records (ADR). To keep track of the reasons which lead to key architectural decisions, we record those for further browsing.
  4. Splash screen. Utilities for automatic generation of an app splash screen to replace standard white screen with the app logo.
  5. CI/CD. Monterail uses GitHub and AppCenter to streamline app integration and delivery, thus the template provides scripts for those platforms to automatically test, build, and deploy the apps.
  6. Bug tracker integration. Monterail uses Sentry as a bug tracking tool. To accommodate that the template comes with ready-made integration with Sentry. Thanks to BLoC state management, the Sentry plugin can automatically report both UI and logic errors. Also, thanks to BLoC traceability we can easily opt in for detailed breadcrumbs for each error which will speed up bug fixing. We don’t enable enhanced breadcrumbs by default as such a detailed app behavior report probably will contain personal user data which should be noted in the app privacy statement, and we believe that such decisions should be made per-app basis.
  7. Linting and formatting. To maintain consistent code style we opted for a list of opinionated decisions about equivalent approaches to solve popular problems. This allows for shorter code reviews and easier code changes because the developers rather than decrypting the original author’s intent can just recognize known patterns and evaluate if it’s appropriate for a given problem.
  8. State management. To handle business logic in a testable and maintainable way we’ve picked BLoC as a state management solution. It allows for robust app logic traceability which is useful both in development and debugging.
  9. Routing. Managing routing for both mobile/desktop and web applications is tricky. Hence we’ve opted in for a community-made routing library which supports code generation, thus saving the development time for actually demanding tasks rather than writing and managing boilerplate.
  10. Flavoring. For simple to configure app nvironments, the app configuration is kept outside the codebase with environment variables – those are fed in during the build process.
  11. Caching, persisting data. To securely store user and app data locally we use high-performance, community-made package wrapped with our helper mixin abstracting repetitive actions to reduce boilerplate.
  12. Testing. To avoid regressions and keep a high codebase quality we test the code at unit, widget and integration levels.
  13. IDE integration. The team agreed on using Visual Studio Code as an IDE. That’s why the template provides launch configurations and a list of tips on how to configure it to boost productivity.

Also, the template provides a lot of tips about app and third-party services configuration to speed up development kick-off even more.

Initial configuration

Developers on any knowledge level can set up the project since the template provides a first steps checklist.

Sneak peek of the steps:

  • Configuring the app metadata – Replacing app id, app name, icon
  • Connecting the bug tracker – Providing the Sentry project id
  • Managing app signing – Creating signing key for Android, steps to generate files for iOS app signing

Ready-made UI components

One of many strengths of Flutter is a rich widget gallery. Besides the standard ones for layout and spacing, there are two main widget groups built into Flutter: Cupertino and Material. The first one recreates the look and feel of macOS/iOS native apps and the second one provides a widget ecosystem that supports Material design guidelines (with support for Material 3 coming in 2022!)


Flutter provides 20+ high quality and customizable widgets that perfectly mimics iOS native app components.

Although beautiful, the Cupertino widget set is not used as often as Material set is when building Flutter apps. Its look and feel are macOS/iOS specific and can feel foreign for users of other platforms. The great thing about Flutter’s everything-is-a-widget approach is that we can mix and match Cupertino and Material widgets, so if you like you can just use iconic iOS picker in your otherwise Material app.


Material widget set is more popular because the Material design itself is thought out to be adjustable to any branding. Also, it’s bigger, at 40+ widgets, thus more robust and useful for more complicated designs.

Robust testing

Following Flutter guiding principles about apps quality, the framework provides built-in testing support, for every feature level – unit, widget and integration.

Tight test library integration with the framework allows Flutter IDE plugin to display an UI for ran tests. Such a UI can speed up the testing process compared to CLI one, and helps make a mental map of test structure.

Unit, widget, bloc

Flutter provides a robust test suite for unit and widget tests. The common thing throughout the Flutter framework is the fact that everything can be built upon by community members. Tests are no exception and thanks to that we can use community-maintained bloc test library which streamlines BLoC modules testing and can be used without any additional test configuration.


Integration test suite is built into Flutter SDK but has to be explicitly added as a dependency. Integration test code should be stored outside of the default unit and widget test directory (simply test), as those tests are not meant to be run frequently, rather when the app version is a production candidate.

We have just introduced you the brief guide how to build a basic Flutter application by yourself. If you have any enquiry or need our support on build Flutter mobiel application, please don’t hesitate to contact us at: