Lepaya's Flutter Journey

Jose Carlos Quintas Junior
Lepaya Tech
Published in
5 min readFeb 3, 2023

In the dawn of 2022, we decided to start our adventure into rewriting all three of Lepaya's apps in a unified way in order to speed up feature delivery.

Our previous setup

Our 3 different apps were built for the same purpose, allowing Lepaya's users access to their courses' content and classrooms. We had an iOS, an Android, and a Web app. They were all built natively in different codebases and languages with different logic because of it.

This was a problem since we had to implement the same feature 3 times. We also had only one developer for each domain, which made things even slower.

With the number of developers in the company growing, we decided it was time to act.

The Goal

Our goals were simple.

  1. Decrease the number of repositories we had to maintain.
  2. Speed up feature delivery across platforms.
  3. Feature parity between platforms.

On Decisions and Frameworks

Before we could do any planning, we had to decide which framework we were going to use.

Although we took web into account when making the decision, initially we thought of only re-writing the Mobile apps.

  1. Flutter
  2. React Native

Researching which would be the best approach didn't take long, Flutter was growing a lot and had all the features we needed. It could also potentially be used for web, so we could live the all-in-one dream.

To build our case, we looked for metrics on the app market itself, such as adoption, how the frameworks were liked, who was using it, etc. We also visited a company that had successfully built their apps in Flutter in order to understand their path.

With this information at hand, we set up meetings to present our findings and to show the management team that this was a good investment of our time, as it would make us a more efficient and scalable team, as well as bring benefits to our users in terms of having the same features across all platforms.

Planning

One of the most important parts of this project was all the planning involved in the preparation phase. Since the app we wanted had been built before, we could go through all the screens and have an idea of how long it would take.

So that was it, our first step was to list all the current screens and functionalities in the app. With that in hand, we could then decide which we would keep, which we would let go, and which would be delayed until after the MVP.

Armed with the knowledge of knowing exactly the screens and features we had to build, plus the time it took us to build it in the past, we were ready to give a rough estimation for the release date. 6 months.

It is about the mistakes you make along the way

Creating the MVP was no easy task, we were a team of three by that time, and wanted to hire more, all of us were learning Flutter and Dart on the job, and there were all the initial project decisions to make.

One of the parts that took the longest was CI/CD. Flutter doesn't have the same maturity level as NodeJS when it comes to CI, it took a good amount of time to figure out how to install Flutter on GitHub Actions, set up all our wanted tests and checks, parse coverage (we are now using covered) to have the PR be rejected if coverage was too low, etc.

Dealing with Apple's certificates was also a notable pain, nowadays we use Github Actions for tests, code quality, versioning, and web build and deployment, while codemagic.io is used to build our mobile apps, manage certificates and release to the stores, but at first, we had a manual setup.

Not all packages are created equal, a lot of them don't support web. So we had to go back and find new packages that would check our boxes in all platforms, or implement them ourselves. (Looks at auth0)

It also took a while to figure out routing… As we were initially building and testing only on Android and iOS, we didn't notice we weren't setting routes, a necessary part of web development 😅, so we had to re-implement the entire routing of the app using a new package, for that we chose go_router.

We could have separated concerns a bit more than we did, in the end, we had a mix of logic on the widgets and on our Cubits, and we are now having to refactor the business logic out of our widgets.

E2E testing is not present, as Flutter doesn’t support interacting with iframes inside them, which is a requirement for us to be able to log in. We are looking into using a NodeJS-based approach and running E2E tests on web only.

Those were only a few of the mistakes we did or pitfalls we encountered, but we managed to overcome them all, the only thing left was releasing.

Results!

Our journey started in April 2022 and we managed to release it on both mobile platforms on August 2, 2022. We took less time than expected and it was a big success!

Web would still take a while to be ready, so we ended up releasing for web around November of the same year, in between fixing issues and bugs and finding alternatives to the packages that didn't support web.

We now have 100% of Lepaya users on Flutter.

Where we stand now

Now we have 5 Flutter developers, have released 2 more completely new features, have automatic CI and CD pipelines, have analytics tracking all over our app, have full feature parity between the platforms, and are continuously making improvements to both the user and developer experience.

Feel free to contact us if there are any questions or if you would like to talk about our journey if you find yourself in the same process.

We are in full steam and ready to take on 2023! 🚂

--

--