Flutter + Firebase: How we built CrochetApp

Profile photo of Daria Orlova
Daria Orlova
May 18, 2021
12 min
Categories: Development
Various items for knitting
Various items for knitting

Who am I? That’s a secret I’ll never tell. Ok, ok, sorry for the lame Gossip Girl reference, just couldn’t help myself. My name is Daria, and I’m an Android and Flutter developer from Chili Labs. What do we do? We build extraordinary mobile apps. From scratch, turnkey. From a very rough client idea to a published product in all markets. And today I will tell you how we built one of them: CrochetApp.

What is CrochetApp?

An app * surprise here * for crocheters. So what do you need for crocheting?

  • Tools. Mostly hooks & yarns. We have inventories for that, where you can keep track of your toolbox either by adding your own or selecting from our huge database of yarns.
  • A way to track your progress. For that, we have a row counter feature, that can be used either on its own or with user-uploaded PDFs (the most popular format for crocheting patterns).
  • And patterns, of course! We have a unique collection of community-created patterns in an awesome, user-friendly format. The collection is always expanding and patterns are something we will be talking more about throughout the post.

https://miro.medium.com/max/1400/1*abb9aux8-GlMnTkGreLKKg.jpeg

Why should you care?

The most important thing about CrochetApp is that it’s a Flutter app in production with real users. Flutter is a relatively young framework, and despite the community’s enthusiasm about it, I understand that businesses may be wary of it — after all, you don’t want your development to halt just because the shiny new piece of software can’t complete a crucial feature. By guiding you through our development path and highlighting the good and the bad moments, I hope to help you decide whether Flutter (and maybe Firebase) is the choice for you. Grab a coffee and let’s go!

Why serverless?

So what do you do, when your project manager comes up to you and says: “your next project is going to be my app, so there won’t be a backend or client involved, and we need to come up with some kind of solution”? Step 1: Panic. Step 2: Google “serverless”.

Ok, just kidding, just panic. Fortunately, we’ve already had a previous successful client project set up with Firebase, using its real-time database and storage with 50k+ users. So that was figured out. Although our previous experience was with an Android native app, that didn’t change much.

The decision to go serverless was a business one — we wanted to launch an MVP first to try out an idea. The whole app was funded by the CrochetApp founder, manager & CEO Slava, and spending time + money on a team of backend, frontend & app just didn’t make sense. Who wants to spend more resources, when you can spend less, without compromising quality?

Almost a year after, as I write this post, CrochetApp has been successfully launched on Android and iOS for some time now, with Firebase functioning as our backend and also hosting our admin panel. So far we didn’t encounter any problems to make us sorry about our decision. But even if we ever will, careful architecture planning gives us confidence that hooking up a different API provider will be seamless.

So today I will tell you a story, how we built a 2 platform app with subscriptions, user registration, a remote database, and a separate admin panel by using just (almost) Flutter and Firebase. The good, the bad, and the ugly.

The apps

This was a no-brainer. We went with Flutter without any discussion. Firstly, because we already had some positive experience with it, and secondly because we wanted to start with an MVP. As of today (May 2021), I think we have about 8 Flutter apps in both stores already. And even more in development. Of course, being a new and cross-platform technology Flutter has its problems & risks, some of which I will mention further on, but the benefits in our case overweighed. I come from a ~5-year-old native Android background and boy, do I not want to return to it (I hope my managers are reading this). 1,5 years into full-time Flutter development and I am absolutely, totally, irrevocably in love. Also, maybe biased a bit because of that, but whatever.

The architecture

We are used to building complex apps and YOLO’ing UI with business logic would never lead us to where we are today. We follow the Clean Architecture principles in our module structure (presentation / data / domain). So if we ever want to move on from Firebase, we can plug in a new data module and be done with it.

https://miro.medium.com/max/1400/1*AOV6CCu5u4pXf92UYXgDpg.png

In the presentation layer, we use the BloC pattern via this library, usually a bloc-per-page structure. The bloc shouldn’t know anything about the UI and the widget should be as business logic agnostic as possible. If you don’t know yet what BloC is, I highly recommend reading about it and trying it out for yourself.

https://miro.medium.com/max/1400/1*jOiQcp1yGXE5eYJCrq0CrA.jpeg

Backend: Firebase Authentication & Firebase Realtime Database.

There aren’t apps without user registration now, are there? Everyone is hungry for data. Not in our case, of course, but we still needed a way to save our user’s data (for them). I think that Firebase authentication is a lifesaver. We have used it in multiple apps (native & Flutter), both the social app handlers and the email + password one. The setup is super easy, the documentation is great and implementation is as effortless as it gets. In CrochetApp we have Google, Facebook & Apple sign-in, as well as a regular email + password sign-up.

https://miro.medium.com/max/1400/1*mCUQydSLTsQTe1skoGlBcw.jpeg

The second part is trickier. Firebase provides 2 database options: Cloud Firestore and Firebase Realtime Database. For our use case, both were legitimate options. Because we didn’t need to handle big amounts of data or even perform queries on it, and we also had experience with Realtime Database already, we went with that. But Cloud Firestore would also work just fine, and we might as well use it for other upcoming features. To decide for yourself what will suit you better, Google provides a small test. To this day we didn’t have any problems with Realtime Database. Yes, it’s a NoSQL database (as well as Cloud Firestore), which has its implications. So if you’re looking into the direction of any Firebase data store, you need to keep that in mind. Even though some of our models are quite complex, they don’t have many relations between them. They can also be flattened into simple JSON types, so this didn’t pose a problem for us.

https://miro.medium.com/max/1400/1*RkcagIFU6kj6aDAtzKFIzA.jpeg

Our main “monster” is the pattern’s details. It’s a complex structure, with a lot of general information about the pattern and a list of parts. Parts themselves are complex objects with instructions (which are also complex objects).

https://miro.medium.com/max/1400/1*mSow37zPzbngPcF1vAYSGw.jpeg

To create a model that is flexible, yet structured, was a challenge, but we nailed it. With such a model it’s possible to create toys of any complexity and so far we didn’t have any problems with it. It’s also super extensible in case we ever need to add more types of data.

https://miro.medium.com/max/1400/1*vA88lbzyettHsp0Hf_XZZA.png

Local storage: Floor

Our users can start pattern projects from the app and track their progress. To do that, we save the pattern details and the user's progress into a local database. One of the future features is to also synchronize this data with the backend so that users can continue their progress on another device, but that’s not yet implemented.

I come from an Android background, remember? In Android, we have Room (a lightweight ORM, exposing query results as streams of data), and being a beginner Flutter developer at the time, I googled Room for Flutter. And that’s how I found floor. The rest is history.

As of today’s (May 2021) state of local database solutions (moor, hive) and my experience with Flutter, I would probably not use it again, unless your models are extremely simple. Floor’s TypeConverters are still an experimental feature, unlike Moor’s (according to docs). That’s one choice I had problems with when serializing the patterns details model. So yeah, that’s one F I’d probably ditch if I needed to start from scratch today.

Flavours / schemas

Because testing new patterns straight on production isn’t a very smart or user-friendly idea, we decided to flavour our app.

Even though flavours on Android and iOS are pretty standard, the same thing can’t be said about Flutter. The official docs contain a bunch of links to community posts, each of them offering a different solution. For the backend, we went with different Firebase instances so that the logic could be separate and not mixed up unintentionally. For flutter flavouring, we went with different entry points and flavor config objects. This approach came with a badge and I just love it. The little things that make a developer happy!

https://miro.medium.com/max/1400/1*mIBBTa2puoUyRcjrxk1g1g.jpeg

CI/CD: Bitrise + Firebase App Distribution

This was also a no-brainer because we use the love couple Bitrise + Firebase App Distribution for all of our apps, and it works like a charm. Well, almost. The Firebase App Distribution part has no problems. Bitrise is an absolutely amazing and highly customizable CI tool, but there is one minor flaw. If you’re not an iOS dev (and maybe even if you are), then those provisioning profiles and code signing will eat your brains out. They definitely did the trick with mine and with every colleague that I talked to about it. Android devs hate it. iOS devs aren’t proud of it either. But that’s life, sometimes you gotta handle unpleasant things. Other than that, Bitrise is perfect. You can set up workflows that build you any flavour app, run all tests, ship to both stores.

https://miro.medium.com/max/1400/1*MFkwPwVPworT7HgL5-MPJg.png

Subscriptions: Revenue Cat

Our monetization plan includes paid subscriptions. Now, remembering how I implemented subscriptions with Android’s In-App Billing library I thought I was yet again set up for a trip to hell. But then I stumbled upon RevenueCat, and this thing changed my developer life. RevenueCat is an SDK that takes away all of the hustle of subscription implementation. Their docs are superb, the whole setup process (besides the setup in Play store & App store consoles) takes a couple of hours (if not less) and it just works. Securely. And it’s free up to $10K MTR, by which time it starts to cost $119/mo, which IMO, is nothing for the headache it takes away. Especially for a serverless app like ours. So sending big love to RevenueCat!

The Admin Panel

Now. This is a very personal one. First, why and what for did we need an admin panel?

Well, remember those pattern details? Before they become Dart code or JSON, they are plain data. With photos, just texts, and Excel files with instruction descriptions. Now imagine translating this either to JSON or Dart. Slava did it manually (sorry, Slava). He made attempts on writing some scripts that would automate the process, but that was still very, very painful. And for me to fix the script errors to upload patterns to Firebase. Who thought those cute toys could cause so much mental harm?!

This is just a small part of one pattern details:

https://miro.medium.com/max/1400/1*-NWMqCJU4edPvFPav-AkgQ.png

And scripts that produced something like this, which then also required manual fixing…

https://miro.medium.com/max/1400/1*woDdkbdTwOlBHJCL9x6Hvg.png

It quickly became absolutely clear that this approach wasn’t scalable or even usable AT ALL. So we decided to come up with a GUI that would allow Slava to create toys. We went with a website. The only experience with the web at that moment I had was a bit of Ruby on Rails and I would sell my soul to the devil to never touch that one again (still would, still hope managers are reading this). For a moment I considered picking up React, but then decided to be even bolder — try out the Flutter web, which was in beta at the time.

https://miro.medium.com/max/1400/1*cU7lIGmrEDrrltjsxtXl8Q.png

So a beta SDK and a developer, who spent a couple of hours swapping a checkbox for a switch in rubies, what could go wrong?

Actually, nothing much did, except for the deadlines (sorry, Slava. Again).

But the development wasn’t easy. If you think apps are still unstable due to Flutter being a young technology, think about the web. It was in beta for a reason, and even though it recently became stable with the introduction of Flutter 2.0, it wasn’t the case then.

The problems don’t stop there. Here goes a big one: there is no support for Web Realtime Database in the official Firebase plugin. Yeah. When I realized that, I thought I was, f..luttered. Luckily for me, an unofficial package was published literally a couple of days before I needed it. A couple of days. Otherwise, that would have been where it ended with Flutter web for me. So a shoutout to this incredible package. Now, we only host the admin panel for dev flavour, so no prod data is touched with it. For transferring patterns from dev to prod we have some hacks, on which I won’t elaborate in this post and plan to get rid of by making use of Firebase Cloud Functions, but that’s not done yet.

In the end, I came up with this beauty, that allows to create toys and upload them to Firebase without fiddling with any code or scripts. We still need Excel files for pattern part instructions, but they’re now exported as CSV and parsed in the admin panel. There are also options to add or edit instructions from the GUI.

https://miro.medium.com/max/1400/1*ojX99u0oPeFEbWCFnoScPw.png

https://miro.medium.com/max/1400/1*ITNvkFCvRmZikk4CXjqg7w.png

Oh, yeah, and about hosting. We host it… on Firebase. I mean, isn’t this just beautiful? And deploying a new version takes 5 minutes in CLI. We have android, ios and a web app done on Flutter, backed by Firebase, hosted by Firebase, distributed by Firebase, authenticated by Firebase. Did I mention we also use Firebase Crashlytics and Analytics? Push notifications, deep links, storage, and cloud functions are also coming. Despite the MAJOR drawback of the Firebase Realtime Database plugin not supporting the web, we use Firebase and Flutter EXTENSIVELY, and it works great. We are in production, we have ~5k users now and it was all done by just 2 devs. Well, to be completely honest, there were a couple of features implemented by other devs, so kudos to Kristine and Rihards, because we were unavailable at the time, but mostly yeah, it’s me and my teammate Maksims. We launched this project from scratch and I’m absolutely and totally proud of it.

https://miro.medium.com/max/1400/1*MqR5OyXgwnHEHs2OwudOlA.jpeg

Summary

CrochetApp was a technical challenge, to say the least. Flutter being young, us as Flutter devs being young, serverless being different from what most of the developers are used to. Nevertheless, I think our stack works very neatly together (except for Floor, probably) and Flutter is becoming more stable and less buggy every minute. Because we follow fundamental architecture principles, we can feel pretty safe about the current and future status of our app. There are limitations that you should consider (like libraries availability, data complexity, and native device features use) before committing to Firebase or/and Flutter. But even if you don’t launch a full-blown app, or decide to go with a different solution for the web, the power that Firebase + Flutter brings to devs can be applied to validate ideas and try out MVPs, without hiring and managing a whole team of different developers. This saves you or the client both money and time. A carefully planned architecture allows expanding your idea into a product, if it proves itself worthy, with close to no problems.

I hope you found this tech stack review interesting and have fun bringing your ideas to life!

You can download CrochetApp from PlayStore & AppStore :)

P.S. I’m working on a series of tutorials on how to use all of those Firebase features with Flutter that I mentioned. Stay tuned!

Daria.

https://miro.medium.com/max/300/1*hB1OofoTpqI6wm43oKjH8A.png

Receive a new Mobile development related stories first. — Hit that follow button

Twitter: @ChiliLabs

www.chililabs.io

Share with friends

Let’s build products together!

Contact us