
I’ve been running some version of the same starter setup since I was an intern — and I didn’t come up with it myself. My seniors taught it to me, patiently, back when I barely understood what a reducer was. This post is as much a thank-you to them as it is anything else. What they handed me wasn’t just a pattern, it was a shortcut past the part of learning Flutter that trips up almost everyone: the state management learning curve.
Back then I didn’t understand half of what I was copying. I just knew that when I opened a new screen, there was a pattern to follow, and following the pattern meant I didn’t have to make five decisions before writing a single line of feature code. Years later, now working as a Flutter architect, that same instinct — “there should be one obvious way to start” — is still the thing I care about most when I set up a new project.
I’ve templated that setup into a Mason workspace: Flutter-RxDart-Base. I'm not going to get into the architecture itself here — the state management split, the networking layer, how the bricks are structured — that deserves its own dedicated post, and I'd rather do it properly than squeeze it in as a side note. This one is about something narrower: why Mason, the tool underneath all of it, is one of the most underrated things in the current Flutter ecosystem, especially now that everyone's attention has moved to AI-generated code instead.
The instinct that started as an intern
As an intern, state management wasn’t hard because any one pattern was difficult. It was hard because there were too many opinions and no obvious default. Every blog post insisted its pattern was the correct one, and picking between them felt less like an engineering decision and more like picking a side.
What actually helped wasn’t finding the “best” pattern. It was having a pattern — one I could follow consistently, screen after screen, without re-litigating the decision every time. That consistency is what let me be productive early, long before I understood the reasoning behind it.
That instinct — pick a default, template it, stop re-deciding it — is the same one that eventually led me to Mason.
It’s not just fast to learn — it’s fast to ship
The real test of any “beginner-friendly” pattern isn’t how easy it is to learn. It’s whether it still holds up once the app is real, in production, with actual users depending on it.
I’ve shipped 7+ apps on this same structure at this point, some of them with 10K+ active users. Not toy projects — real apps, under real load, maintained over real time. And the pattern hasn’t needed to be reinvented for any of them. That’s what convinced me this wasn’t just a good learning tool for interns; it’s genuinely one of the fastest ways I know to go from a blank Flutter project to something shippable, without state management turning into its own multi-week side quest.
Mason is one of the most underrated tools in Flutter right now
In a Flutter ecosystem where every conversation is about which AI agent writes the cleanest widget, mason_cli barely comes up anymore. That's a shame, because Mason solves a problem AI doesn't actually solve — it solves consistency, not just generation.
A brick isn’t a one-off suggestion. It’s a template you wrote once, reviewed once, and trust every single time it runs. mason make bloc doesn't have good days and bad days. It doesn't forget a convention halfway through a long session. It doesn't need the architecture re-explained in a new prompt because the last conversation aged out of context. It produces the same correct skeleton, every time, because the decisions are already locked into the template.
That’s a fundamentally different kind of tool than a code-generation model, and I think the Flutter community undersells it precisely because it’s less exciting to talk about than AI. Mason isn’t flashy. It’s boring in the best possible way — the same way a linter or a CI pipeline is boring. Boring is exactly what you want from the part of your workflow that’s supposed to be invisible and reliable.
AI saves time. Mason saves time and tokens.
I use AI coding tools constantly — that’s not in question. But there’s a cost to AI-generated boilerplate that doesn’t get talked about enough: every time I ask an agent to scaffold a new feature from scratch, that’s tokens spent, context spent, and — depending on the setup — real money spent, to regenerate something that is, structurally, identical to the last twenty features I built.
Running mason make bloc costs none of that. No tokens, no API calls, no waiting on a model, no chance the output subtly drifts from last time because the prompt was phrased slightly differently or the context window forgot a convention. It's deterministic. What it generates today is structurally identical to what it generated a year ago, because the logic lives in a template file I control, not in a probability distribution.
That doesn’t make Mason a replacement for AI — they solve different problems. AI is what I reach for when the problem is genuinely novel and needs reasoning. Mason is what I reach for when the problem is “I need the same correct scaffold I’ve needed fifty times before, right now, for free.” Reaching for AI for that second category is like hiring a consultant to fill out a form you already have memorized.
Maintaining the bricks taught me more than using AI ever did
This is the part I didn’t expect going in.
Writing and maintaining the bricks themselves forced a level of discipline that just prompting an AI assistant never has. When I ask an AI to generate a piece of boilerplate, I can accept it, use it, and move on without ever fully articulating why it’s structured that way. When I write a brick, I don’t get that shortcut. I have to decide, explicitly and permanently, what the “correct” shape of a feature actually is — because whatever I encode becomes the answer for every future feature, for me and for anyone else who runs it.
That’s a different kind of learning than reviewing generated code. Reviewing teaches you to recognize a good pattern when you see one. Building the template teaches you to justify the pattern well enough to defend it as a default. Maintaining it over time is closer to what senior engineering actually looks like than another afternoon of prompting.
Where this is going
I still think the biggest lesson here isn’t really about Mason as a tool — it’s that some problems are worth solving once, permanently, and for free, instead of regenerating indefinitely at a cost, whether that cost is tokens, money, or consistency.
I haven’t talked about the actual architecture in this post on purpose — the Redux/RxDart split, the networking layer, the error handling, how the bricks are structured underneath. That’s a bigger conversation and it deserves its own space instead of being squeezed in here. I’ll be dropping a full, dedicated breakdown of the architecture soon — how it’s built, why it’s built that way, and what I’d do differently if I started over.
Until then, the repo’s public if you want to poke around ahead of that: Flutter-RxDart-Base.
