Flutter Setup & Toolchain
Playground note: This is a setup and toolchain lesson — no runnable in-browser snippet applies here. Follow the steps in your terminal.
Setting up Flutter is closer to installing the Go or Rust toolchain than to npm install. You download one SDK, add it to your PATH, and the flutter CLI handles everything else — dependency management, device emulation, builds, and hot reload.
Install Flutter
Section titled “Install Flutter”Visit flutter.dev/docs/get-started/install and follow the guide for your OS (macOS, Windows, or Linux).
macOS shortcut (Homebrew):
brew install --cask flutterAfter installation, run the doctor to verify your environment:
flutter doctorflutter doctor is Flutter’s equivalent of npx create-react-app --check — it scans for missing dependencies (Xcode, Android Studio, connected devices) and tells you exactly what to fix.
Which versions this course targets
Section titled “Which versions this course targets”Everything here is written against Flutter 3.47 (the current stable) on the React 19 side of the comparison. Flutter’s stable channel ships roughly every quarter, so a few platform requirements are worth checking before you start:
| Target | Requirement on Flutter 3.47 |
|---|---|
| iOS | iOS 15 or later (raised from 13) |
| macOS | macOS 12 or later (raised from 10.15) |
| Xcode | Xcode 27 supported |
| Renderer | Impeller is the default on iOS, Android, macOS, Windows, and Linux |
| iOS plugins | Swift Package Manager; CocoaPods is in maintenance mode |
Impeller replaced Skia as the renderer precisely to kill the “first animation stutters” problem: shaders are compiled at build time instead of being discovered at runtime. If you have read older Flutter posts complaining about jank on the first frame of an animation, that is the problem Impeller solves, and on 3.47 it is on by default everywhere.
The Swift Package Manager move matters the first time you add a plugin with native iOS code. Most popular plugins have already migrated; if you hit one that has not, you will see CocoaPods fall back in. That still works today, but treat an unmigrated plugin as a maintenance signal — the same way you would treat an npm package whose last publish was three years ago.
The flutter CLI vs npm / Vite
Section titled “The flutter CLI vs npm / Vite”| npm / Vite / CRA | flutter CLI | Purpose |
|---|---|---|
npm create vite@latest my-app | flutter create my_app | Scaffold a new project |
npm install | flutter pub get | Install dependencies |
npm run dev | flutter run | Start dev server + hot reload |
npm run build | flutter build apk / flutter build web | Production build |
npm install package | flutter pub add package | Add a dependency |
npm test | flutter test | Run tests |
npx eslint . | flutter analyze | Lint / static analysis |
Scaffold a new project
Section titled “Scaffold a new project”flutter create my_appcd my_appflutter runflutter create generates a project similar to what create-react-app produces: an entry point, a sample widget, and all the platform-specific boilerplate (iOS Xcode project, Android Gradle files, web index.html).
Project structure vs React
Section titled “Project structure vs React”flowchart TB root["my_app/"] lib["lib/"] mainDart["main.dart — entry point (≈ src/main.tsx)"] test["test/"] widgetTest["widget_test.dart — tests (≈ src/__tests__/)"] pubspec["pubspec.yaml — dependencies (≈ package.json)"] android["android/ — Android native shell"] ios["ios/ — iOS native shell"] web["web/ — Web shell"] root --> lib --> mainDart root --> test --> widgetTest root --> pubspec root --> android root --> ios root --> web
Your Dart code lives entirely in lib/. You almost never touch android/ or ios/ unless you need platform-specific native code.
pubspec.yaml vs package.json
Section titled “pubspec.yaml vs package.json”name: my_appdependencies: flutter: sdk: flutter dio: ^5.4.0 # HTTP client (≈ axios) go_router: ^18.0.0 # routing (≈ react-router-dom)
dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^6.0.0After editing pubspec.yaml run flutter pub get (≈ npm install) to fetch packages from pub.dev — Dart’s npm registry.
Adding a package
Section titled “Adding a package”flutter pub add dioThis edits pubspec.yaml and runs pub get in one step — equivalent to npm install dio.
Editor setup
Section titled “Editor setup”VS Code (recommended for React developers):
- Install the Flutter extension (includes Dart language support).
- Open the command palette → Flutter: Select Device to pick a simulator/emulator.
- Press
F5or run Flutter: Run to start with hot reload.
Android Studio / IntelliJ: Install the Flutter and Dart plugins. This is the preferred IDE for Android-heavy work.
Hot Reload vs Fast Refresh
Section titled “Hot Reload vs Fast Refresh”Both work the same way: edit a source file, save, and the running app updates in under a second without losing state. In Flutter:
- Hot Reload (
rin the terminal, orCtrl+Sin VS Code with the extension) — injects updated code, preserves widget state. - Hot Restart (
R) — full restart, resets state. Equivalent toCtrl+C+npm run dev.
Running on a device or emulator
Section titled “Running on a device or emulator”# list available devicesflutter devices
# run on a specific deviceflutter run -d "iPhone 16"flutter run -d chromeflutter run -d macos