Mobile Development

What's New in Flutter 3.47: What Actually Matters Before You Run flutter upgrade

A practical breakdown of Flutter 3.47's biggest changes: standalone Material/Cupertino packages, Xcode 27 breaking changes, and Impeller on desktop.

Line-art upgrade arrow rising from a package box on a blue and teal technical background.

Most developers do not read every line of a Flutter release announcement. We update the SDK, let the project rebuild, and only start reading when Xcode, a plugin, or an import decides to ruin the afternoon.

Flutter 3.47 is worth understanding before running flutter upgrade. Flutter’s design libraries are moving out of the SDK, Apple’s next toolchain changes deployment targets and app lifecycle, and Impeller is becoming the normal desktop renderer.

This is the practical version of what changed in Flutter 3.47, what can break, and what I would check on a real project before upgrading.

The Short Version

If you maintain a production Flutter app, these are the changes to put on your board:

  • Material, Cupertino, and their localization code now live in standalone packages.
  • Xcode 27 raises Flutter’s minimum iOS and macOS versions and requires the UIScene lifecycle.
  • Intel Mac support and CocoaPods-based plugin integration are both approaching the end of their useful lives.
  • Impeller is now the default renderer across macOS, Windows, and Linux.
  • Widget Previews are stable and more practical for daily component work.

Before You Upgrade: Audit the Apple Side

Flutter 3.47 is preparing projects for Xcode 27, iOS 27, and macOS 27. This is not just a new simulator runtime. There are deployment and lifecycle changes that can affect whether an app builds and whether it launches.

Your Minimum OS Versions Are Moving

Flutter 3.47 raises the supported minimums:

Platform Previous minimum Flutter 3.47 minimum
iOS 13 15
macOS 10.15 12

Before upgrading, check your analytics. If your product still has meaningful usage on iOS 13 or 14, this is a product decision as well as a build setting. Find out how many users will stop receiving releases and whether other teams need advance notice.

Inspect the deployment target in Xcode, your Podfile, CI settings, and build scripts too. Another environment may still carry an older value.

Xcode 27 Requires the UIScene Lifecycle

This is the change I would test most carefully. UIKit apps built with the iOS 27 SDK must use the UIScene lifecycle. Without it, an app can build and then fail at startup.

Flutter’s tooling migrates ordinary projects during the build, so a standard app may require no manual work. The word “ordinary” matters. Review the native side if your AppDelegate contains custom initialization, notification handling, deep-link logic, SDK setup, or lifecycle callbacks. Do the same for plugins that still expect the older application lifecycle.

My practical test would be:

  1. Upgrade on a separate branch.
  2. Build with Xcode 27, not only the Flutter CLI.
  3. Cold-launch on an iOS 27 simulator and a physical device when available.
  4. Exercise push-notification taps, universal links, background-to-foreground transitions, and any SDK initialized in AppDelegate.
  5. Inspect older or privately maintained plugins for legacy lifecycle assumptions.

Automatic migration cannot prove that custom native behavior still runs at the correct lifecycle point.

Intel Mac Builds Are on Borrowed Time

Flutter has stopped running automated tests on Intel Mac hardware. The CLI now warns when the host is Intel or when a macOS build targets both Intel and Apple Silicon; those warnings are expected to become errors later.

Check CI runners, release machines, and developer laptops now. An old Intel Mac may still be signing production builds somewhere.

You can opt into ARM64-only macOS output today:

flutter config --enable-macos-arm64-only

Before enabling it, confirm whether Intel users still matter. Enabling it early for an Apple-Silicon-only team gives you time to find pipeline assumptions before Flutter enforces the change.

Swift Package Manager Is Becoming the Expected Path

The plugin ecosystem’s move from CocoaPods to Swift Package Manager is nearly complete: 92 of the top 100 iOS plugins have migrated. CocoaPods is now in maintenance mode, and Flutter is clearly treating SwiftPM as the future integration path.

If you previously disabled SwiftPM because an important plugin did not support it, retest that decision:

flutter config --enable-swift-package-manager

Packages that remain on the old path will eventually stop working and can receive a lower pub.dev score. App teams should audit private plugins and abandoned dependencies first.

Material and Cupertino Are Now Standalone Packages

Flutter’s Material and Cupertino widget libraries have reached version 1.0 as material_ui and cupertino_ui on pub.dev. They are opt-in dependencies instead of code tied directly to the core SDK.

The benefit is release independence. Widget fixes can ship weekly instead of waiting for Flutter’s quarterly stable release, so a small UI fix no longer requires a full framework upgrade.

Migration is designed to be mechanical:

dart fix --apply --code=migrate_design_widgets

That command updates imports automatically. There was an early issue where the migration could change source files without correctly adding dependencies to pubspec.yaml. If that happens, add them yourself and run the migration again:

flutter pub add material_ui
flutter pub add cupertino_ui
dart fix --apply --code=migrate_design_widgets

Run tests after the rewrite, especially golden tests and custom themes. Package versions are now an explicit part of your UI stack.

For gradual migration, MaterialUiCompatibilityBridge lets a converted app coexist with dependencies still using old SDK imports. Treat it as temporary scaffolding while the ecosystem catches up.

The old bundled libraries are scheduled for formal deprecation in the November Fall stable release. In other words, you do not have to migrate every app this morning, but ignoring the move indefinitely is not a plan.

Localizations Move Too

flutter_localizations has been separated along the same design-library boundary. Material translations live with material_ui, and Cupertino translations live with cupertino_ui.

The setup becomes simpler for apps using both design systems. GlobalMaterialLocalizations.delegates now includes the Material, Cupertino, and Widgets delegates, so you no longer need to list all three individually:

localizationsDelegates: GlobalMaterialLocalizations.delegates,

For multilingual apps, test framework controls such as date pickers in less frequently used locales after migration.

Impeller Is Now the Desktop Default

Flutter 3.47 makes Impeller the default renderer on macOS, Windows, and Linux. Impeller prepares a known set of shaders ahead of runtime and targets modern graphics APIs such as Metal and Vulkan. The practical result is fewer first-run animation pauses caused by compiling a shader at the moment it is first needed.

Desktop teams should test custom shaders, embedded platform views, animation-heavy screens, and older graphics hardware. Flutter still provides ways to switch back to Skia for now, but those escape hatches are being phased out. If Impeller exposes a rendering problem, file a reproducible bug instead of building a long-term plan around opting out.

Widget Previews Are Ready for Normal Work

Flutter Widget Previews are now stable. They let you render and adjust an individual component without launching the complete app, navigating to the right screen, and reproducing enough state to see one button or card.

The stable version starts faster by caching project setup in .widget_preview/. It also supports more flexible layered themes, which helps when checking components across brand, brightness, or accessibility variants. For web widgets, assets from the project’s web/ directory are synchronized automatically into the preview environment.

It will not replace device testing, but it shortens the UI loop for components with many visual states.

Web and GenUI: Useful, but Not the Main Upgrade Risk

Flutter continues preparing to make Wasm the default web target. It remains opt-in in 3.47:

flutter build web --release --wasm

If your web app still depends directly on dart:html, start moving toward package:web; the older interop path is not supported by the Wasm target.

genui 0.10.0 also expands A2UI protocol support, including shared protocol types and client-side functions for validation or derived values.

Smaller Fixes You Will Actually Notice

  • Android virtual-keyboard events no longer leave modifier keys such as Shift stuck.
  • iOS signing output now shows both the selected Team ID and Team Name.
  • Provisioning-profile failures provide clearer diagnostic messages.
  • Mobile text-selection handles behave better during small scroll movements and near top-edge menus.
  • ImageIcon can preserve an asset’s original colours with useOriginalColors: true.

None of these sells a release on its own. Together, they remove the kind of small friction that consumes real debugging time.

My Flutter 3.47 Upgrade Order

I would not begin with flutter upgrade. I would begin by creating a branch, recording current production deployment targets, checking the CI machine architecture, and listing plugins with native iOS code.

Then I would upgrade, migrate the design packages, run static analysis and tests, and build every supported platform. For iOS, I would explicitly test lifecycle-dependent behavior under Xcode 27. For desktop, I would compare important screens under Impeller. For web, I would test Wasm separately rather than quietly changing the production target in the same release.

Flutter 3.47 is a healthy update because it separates framework concerns and moves several platforms toward their next long-term foundations. It is also an update where a green Dart test suite does not tell the whole story. Native lifecycle, deployment support, plugin packaging, and rendering all deserve attention.

And Xcode 27 has enough consequences beyond this overview to deserve a dedicated post of its own. That one is coming soon; for now, treat the Apple section above as the part to complete before release day, not the part to bookmark and forget.