You have three ways to build Flutter onboarding screens: a pub.dev package like introduction_screen, a custom widget flow you write yourself, or a server-driven approach where the screens live outside your binary. Packages get you a swipeable walkthrough in an afternoon. Custom builds give you full control over design and logic. Server-driven flows let you change copy, screens, and targeting after release without shipping a new build. The right answer comes down to one question: how often will this onboarding change once real users hit it?
Why Flutter teams build onboarding by hand
Flutter makes UI feel cheap. A PageView, a few Columns, a dot indicator, and you have a working walkthrough before lunch. That is exactly why most Flutter teams never seriously evaluate alternatives: when everything is a widget, onboarding looks like just another widget tree.
The problem is not building it. The problem is everything after. Onboarding is the highest-traffic surface in your app, the first thing every new user sees, and the screen you will want to change most often as you learn what converts. A widget tree you wrote in a day becomes a surface you rebuild and re-release every time someone wants to test a new value proposition. The initial build is the easy ten percent.
What packages like introduction_screen actually solve
Packages such as introduction_screen, intro_slider, and smooth_page_indicator handle the mechanical parts: swipeable pages, indicators, skip and done buttons, sensible transitions. If your onboarding is a static three-page walkthrough explaining what the app does, a package is the fastest honest answer. Add your copy, wire up the done callback, ship.
Be clear about what they do not solve. The content is still compiled into your binary, so every copy tweak is a release. There is no targeting: new users, returning users, and users arriving from a specific campaign all see the same screens. There is no built-in analytics, so you instrument drop-off yourself. And there is no way to compare two versions without maintaining both code paths behind a flag.
Packages solve layout. They do not solve iteration. For a walkthrough you expect to touch twice a year, that trade is fine.
When a custom build is the right call
Write it yourself when onboarding is part of your product's core logic, not just an intro. Branching questionnaires that configure the app, form inputs that feed your backend, animations that carry your brand: these outgrow package APIs quickly, and fighting a package's customization options is worse than owning the code.
The honest cost list: every screen is code you maintain, every analytics event is instrumentation you write, and every experiment means a feature flag plus two living variants. Teams that do this well treat onboarding as a named area of ownership, not a task someone finished in sprint three. Without that, a custom build slowly fossilizes: it works, nobody wants to touch it, and it stops improving. The same calculus applies on other cross-platform stacks; we walked through it for React Native in our React Native onboarding guide.
The real tax: every tweak ships through both stores
Here is the cost packages and custom builds share. Change one headline and the path to production is: edit the string, bump the version, build for iOS and Android, submit to both stores, wait for review, then wait days more for users to actually install the update.
Review itself is fast now. Apple's App Review page states that 90% of submissions are reviewed in under 24 hours. But review was never the real bottleneck. The bottleneck is the batching it forces: because each change costs a full release cycle, teams queue onboarding tweaks behind the next feature release, and a copy test that should take an afternoon waits three weeks. Worse, slow iteration quietly convinces teams to stop proposing changes at all. We covered the alternatives in how to update your app without an App Store review.
Server-driven flows: the third option
A server-driven approach moves the onboarding definition out of the binary. Your Flutter app ships with a lightweight SDK; the screens, copy, order, and targeting live on a server and you edit them from a dashboard. Publish a change and the next user who opens the app sees it. No version bump, no review queue, no waiting for update adoption.
This is what Setgreet does. The Setgreet Flutter SDK supports Dart on Flutter 3.0 and up, and it renders flows with fully native UI components, SwiftUI on iOS and Jetpack Compose on Android, with no web views or iframes, using flexbox layout that adapts to any screen size. You identify users with identifyUser, track behavior with trackEvent, and trigger flows off events and user attributes, so a returning user can get a different onboarding flow than a brand-new signup. Note that flows are fetched over the network, so this approach assumes a connection at display time.
The fit test is simple. If onboarding is a settled, static walkthrough, a package stays cheaper. If it is a growth surface you plan to tune monthly, paying the integration cost once beats paying the release tax forever.
How to choose
- Static walkthrough that rarely changes: use a package and move on.
- Onboarding is core product logic, deeply wired into your app's state: build it yourself and staff its ownership.
- Onboarding is a conversion surface you want to iterate on weekly or monthly: go server-driven so changes skip the release cycle.
These options also combine. Plenty of teams keep account creation and permissions in custom widgets, then hand the educational and promotional screens to a server-driven flow where fast iteration matters most.
Frequently asked questions
How many onboarding screens should a Flutter app have?
Category matters more than framework. Directional estimates from a July 2026 snapshot of PaywallPro's public Open Paywall Gallery dataset of 910 top iOS subscription apps put the median onboarding plus walkthrough length at 17 screens for health and fitness apps but only 8 for entertainment apps. Those are that third party's estimates, not Setgreet data, and top apps skew long because they front-load personalization questions. Start near your category's norm and let your own completion data decide; our guide to onboarding length goes deeper.
Can I change Flutter onboarding without releasing a new app version?
Not if the screens are compiled into your binary, which is true for both packages and custom builds: every change goes through a build, two store submissions, and user update adoption. Server-driven flows avoid this because the screens are remotely managed content rather than code, so publishing an edit changes what users see the next time the app fetches the flow, with no store release involved.
How do I A/B test onboarding in Flutter?
It depends on where the screens live. With compiled onboarding, you maintain both variants in code behind a feature flag and wire up your own exposure and conversion tracking. With server-driven onboarding, variants are content changes rather than code changes, which removes the release cycle from each test. Either way, decide your success metric before the test ships; our guide to A/B testing onboarding flows covers experiment design and common pitfalls.
