Flutter Lesson 79 of 83 4 min read
Build Flutter Apps for Web and Desktop
Build and deploy a Flutter app for the web, Windows, macOS and Linux: build commands, hosting, base href, and packaging installers.
On this page
The same Flutter project can also be built for browsers and desktop computers. Each target has its own build command and its own way of reaching users.
Enabling a platform #
A project has a folder for each platform it supports. To add one to an existing project:
flutter create --platforms=web,windows,macos,linux .
Check what your machine can build with flutter doctor. Desktop apps must be built on the platform they target: Windows apps on Windows, macOS apps on a Mac, Linux apps on Linux.
Web #
flutter run -d chrome # develop
flutter build web # release build
The output is a folder of static files in build/web/. Upload it to any static host.
Hosting #
Firebase Hosting:
firebase init hosting # public directory: build/web, single-page app: yes
flutter build web
firebase deploy
GitHub Pages, when the site lives at username.github.io/my_app/:
flutter build web --base-href /my_app/
Then publish build/web. The base href must match the path the site is served from, with a slash at each end. A wrong value gives a blank page.
Netlify, Vercel, Cloudflare Pages: set the build command to flutter build web and the publish directory to build/web, or upload the folder.
Single-page app routing #
With go_router, addresses such as /product/42 are handled by the app, not by files on the server. Configure the host to serve index.html for every path, or reloading a deep link returns a 404. On Firebase, answering “yes” to “configure as a single-page app” does this.
By default, Flutter web URLs contain a hash: example.com/#/product/42. For clean URLs, call usePathUrlStrategy() from package:flutter_web_plugins/url_strategy.dart before runApp.
WebAssembly #
flutter build web --wasm
This compiles to WebAssembly, which runs faster in browsers that support it, with a JavaScript fallback for the rest. Check that the packages you use are compatible.
What to edit in the web folder #
| File | Contains |
|---|---|
web/index.html | Page title, description, the loading indicator shown before Flutter starts |
web/manifest.json | Name, colours and icons when installed as a web app |
web/favicon.png, web/icons/ | Icons |
Things that differ on the web #
dart:iois not available: noFile, noPlatform. UsekIsWebto guard such code.- Requests to other servers need those servers to allow your site (CORS).
- Some plugins have no web implementation. Check on pub.dev.
- The first load downloads the engine, so it is heavier than an ordinary page.
- Text selection, right-click, the back button and keyboard shortcuts are expected. See adaptive apps.
- Search engines index Flutter web poorly. Build content sites with HTML, and applications with Flutter.
Windows #
Needs Visual Studio with the “Desktop development with C++” workload.
flutter build windows
The output is in build/windows/x64/runner/Release/. Distribute the whole folder: the .exe needs the DLLs and the data folder next to it.
To give users an installer:
| Tool | Produces |
|---|---|
The msix package | An MSIX package, for the Microsoft Store or direct installation |
| Inno Setup | A classic setup.exe |
flutter pub add --dev msix
dart run msix:create
Unsigned Windows apps trigger a SmartScreen warning. A code-signing certificate, or publishing through the Microsoft Store, removes it.
macOS #
Needs Xcode.
flutter build macos
The app bundle is in build/macos/Build/Products/Release/.
macOS apps run in a sandbox and must declare what they need in the entitlements files, macos/Runner/DebugProfile.entitlements and Release.entitlements. For network access:
<key>com.apple.security.network.client</key>
<true/>
Without it, every HTTP request fails. This is the most common macOS surprise.
To distribute outside the Mac App Store, the app must be signed with a Developer ID certificate and notarised by Apple, or macOS refuses to open it. For the store, archive and upload through Xcode as for iOS.
Linux #
Needs clang, cmake, ninja-build, pkg-config and the GTK development libraries.
flutter build linux
The output is in build/linux/x64/release/bundle/. Distribute the whole folder, or package it as a Snap, a Flatpak, an AppImage or a .deb.
Desktop expectations #
A desktop app is used with a mouse, a keyboard and a resizable window.
- Layouts adapt to any window size. Set a sensible minimum with the
window_managerpackage. - Menus, keyboard shortcuts, tooltips and hover states are present.
- Density is higher than on a phone.
- Files are opened and saved with system dialogs (
file_picker,file_selector).
One codebase, several targets #
| Concern | Approach |
|---|---|
| Layout | Breakpoints and LayoutBuilder. See responsive layouts |
| Platform checks | kIsWeb and defaultTargetPlatform, never dart:io Platform in shared code |
| Missing plugins | Hide the feature, or provide a different implementation behind an interface |
| Storage | shared_preferences works everywhere. For databases, pick one that supports your targets |
| Build and release | One pipeline per platform. See CI/CD |
Build modes #
| Mode | Command | For |
|---|---|---|
| Debug | flutter run | Development. Hot reload, assertions, slow |
| Profile | flutter run --profile | Measuring performance |
| Release | flutter build <platform> | Users. Optimised, no debugging |
Try it yourself #
Build one of your apps for the web and open build/web with a local server, for example python3 -m http.server inside that folder. Resize the browser window through phone, tablet and desktop widths and note everything that needs to change. If you can, deploy it to a free static host.