As a developer, I don’t often consider no-code solutions, mostly because it feels like an entirely new type of thinking, where limits can pop up at any time. And while I readily recognized their potential to rapidly develop conventional features, it’s really unadapted to stand out and do more complex things, which we often end up doing.
But one day, I heard whispers about a new player in the game. A company founded by two former Google engineers, promising a no-code solution specifically for creating Flutter apps - FlutterFlow. Given my past experiences, my initial reaction was, predictably, one of skepticism. However, as a Flutter developer I found myself intrigued, especially as FlutterFlow started garnering increased attention from the Flutter team itself since its launch. I decided to delve deeper, to see for myself if FlutterFlow could indeed rise above the limitations of traditional no-code solutions and actually be used to speed up a Flutter application development workflow.
So compared to Flutter, what can be done using FlutterFlow?
This is the first thing I checked is the look of the generated code. And I was quite impressed.
The FlutterFlow team made a lot of effort to generate easily maintainable code, and it shows: all variables have a name that describes them well, the architecture is simple and you can even find some comments.
This is a crucial point, because it means that you can start an app with FlutterFlow and switch at any time to a more standard flutter development approach. Rather reassuring when you doubt that you can do everything you want with no code. Be careful though, this method forces you to use the packages chosen by flutterflow (for exemple goRouter for navigation or SharedPreference for state management), it could be complicated to change for your favorites libs or architecture afterwards.
Good. Now that this point is safe, let’s test the main features.
Even if you never used FlutterFlow, for standard UI you will be faster if you try it than if you stay with Flutter code. And it doesn't only apply to the UI: FlutterFlow has a template system that allows you to create a complete authentication, messaging or e-commerce system in 2 minutes. You’ll tell me that was the promise of no-code from the start, but it really delivers and I had to point it out.
At this point, I started to build a demo app, like those I made while learning Flutter, that just fetch data from an online API and display it in a list, with more info when you click on a list item.
If I wanted to do that today in FlutterFlow, I would juste take the template that does exactly that, but at this time I really wanted to understand every features specificities. Honestly I didn’t see this template but that’s not the point… Anyway I made it from scratch.
Will FlutterFlow manage to call the right resource? To deserialize the result? To provide it in an accessible way, knowing that it doesn’t show any custom type to its user?
Well, just like you would separate the call from the UI in Flutter, you can define different calls in a specific section of your FlutterFlow project, call them when a page or a widget is displayed and use the result thanks to the json_path standard. You can also decide to cache the result and invalidate it when you want, making FlutterFlow support offline mode.
Now I have a page that calls an API to fetch data, and I want to pass some of it to another one and display more information on my list entries.
First approach, recommended for this use case and used in the FlutterFlow template, I pass an argument to the second page and specify it in the onClick function of the first one. Just like you could do in Flutter.
This is clearly enough for my demo app, but what if you want a cleaner way of sharing data between components that are not linked in this particular way, like handling settings for example?
For this you can use the state management: declare a variable in the “app state” and access it anytime anywhere, or declare it in a “local page state” for a more scoped use.
Behind the scene, FlutterFlow generates an AppState class which contains all your app state variables, and creates a new instance in every page that needs to access it. When this class is initiated, it updates the value of all variables from SharedPreferences, and then uses getters and setters to always keep the SharedPreferences instance up to date
For local page state, FlutterFlow just adds variables to the page’s model.
There is a “theme settings” section that provides you with everything you need to build a consistent look over your app. You can of course specify colors for light and dark mode (And obviously generate the theme colors from IA, remember that FlutterFlow was made by former Google engineers) but also typography, icons, some theme widgets and handle responsiveness. The generated code fits into a single file, which may not seem like much, but it's easy to understand.
Same thing, you can add translations, generate them automatically with Google translate and specify them manually in the dedicated section.
The last two points are well implemented and worth mentioning, but they are features I would expect in a no code solution. What if I want something more specific, like choosing the package name? Or the permissions for my app to request? Or if I want to add a splash image? Those are features that I easily found in my project settings, among others like in-app purchases or deep linking. I won’t enumerate here all the options you have, but I hope it gives you an idea of how far you can go into mobile development specificities.
Of course, the FlutterFlow team can’t provide a specific no code adaptation for every Flutter feature that are constantly being created. Knowing that, they were extra careful about providing ways to still be able to use those features, even if it’s not no-code.
The use of packages is crucial in Flutter development. You just can't do without them, and that's why I quickly wondered about their use in FlutterFlow. The answer is: use custom code.
In general, when you can't create a widget in FlutterFlow, custom code is often the solution because it allows you to revert to the power of the code. Be careful, however, not to get carried away and waste time coding components that could have been no-coded. As soon as a custom widget takes another widget as a child, that other widget must be accessible in the custom code, i.e. defined as custom code. Before you know it, you're coding more than you're no-coding. There is however a workaround to avoid manually coding the child. It involves defining a reusable no-code widget for the project, but it’s still clumsy.
Also, the built-in IDE can be less friendly than your favorite one, but as I'll discuss later, implementing and testing your code in your own IDE can solve this problem.
Picture this: you're knee-deep in code, sleuthing for the source of a bug. A trail of breadcrumbs in the form of print statements leads the way. This is the heart of debugging in a traditional IDE. But when I stepped into FlutterFlow, I realized this breadcrumb trail was missing.
In FlutterFlow, you can run your app in a browser, but it's a bit slow and some features don’t work, like Google authentication. And those informative 'print' statements we rely on as developers? Nowhere to be found. You could simulate them by throwing an error with a custom message and checking the browser's console, but it feels like a clunky workaround.
This is where FlutterFlow's pro plan comes to the rescue. It lets you push your code to GitHub, and then pull it into an IDE for a smoother debugging experience. But wait, there's a catch. Each time you want to test a modification, you have to write a commit message and go through GitHub, adding a few extra steps to the process 😕.
There's an alternative if you'd like to skip the GitHub dance: the FlutterFlow extension for VS Code. This tool allows you to download your FlutterFlow code and run it directly with VS Code. It spares you the commit messages and streamlines your debugging process. You don’t have the free choice of the IDE anymore, but you end up waiting just a couple seconds longer every time you launch a new version of your code, compared to standard code debugging 👍
So while debugging in FlutterFlow might initially seem impossible, with these tricks it becomes notably manageable.
If you used to work with Flutter as a team, and want to switch to FlutterFlow, be aware that there is a “work in team” feature, that lets several accounts simultaneously modify the project. But other than that, you’re left on your own. Since the versioning system is really simple, you can consider that you will loose almost all of git’s power**.** No branches, no pull request, no code review.
Considering code regression, you can’t write and automatise tests in FlutterFlow. Actually you can test your custom functions with different input values to check that it does want you want, but you can’t tell FlutterFlow what result you expect. It just prints you the result and you have to check yourself if it’s correct. So don’t think about an automated process with failing tests on code regression.
The only way to do that would be to download the code to an IDE, write manually every test and run them from here… But you don’t want that.
It’s extremely easy to configure Firebase and Supabase, and same thing for Google, Apple and Facebook authentification.
But you can’t do anything else, so if you plan on using FlutterFlow with Auth0, ReachFive, AWS Cognito… You just can’t.
In FlutterFlow, you don’t have access to no-code widgets dispose function. So for example as soon as you want to use a stream, you need to do switch to custom code. Let’s say you want to listen for a change in internet connection, you have to either start a periodic timer that checks the connection (which would be completely illegal in a Flutter code), either coding every widget that depends on the connection as a custom widget.
The FlutterFlow community is still young, and made of developers and non-developers, which makes a forum (the equivalent to Stack Overflow) that isn't always very efficient when you have a problem that's a little specific. That said, FlutterFlow makes every effort to offer maximum support, notably through numerous youtube videos.
FlutterFlow is a powerful tool that can significantly speed up your Flutter development workflow. While it may not be suitable for every project, it can be an excellent option for rapid prototyping or building simple apps.
Its generated code is easily maintainable and the platform provides a wide range of features that can help you build a complete app without writing any code. However, if you need to build more complex features or require more flexibility in your development, Flutter may be the better choice.
Ultimately, the decision between Flutter and FlutterFlow depends on the specific needs of your project and your personal preferences as a developer. I hope the points I discussed helped you find out whether your needs correspond to what can be done with FlutterFlow or not.