This guide will help you build and run the Task Manager sample application.
-
.NET 9.0 SDK or later
- Download from: https://dotnet.microsoft.com/download
- Verify installation:
dotnet --version
-
IDE (Choose one)
- Visual Studio 2022 (Windows/Mac) with MAUI workload
- JetBrains Rider with MAUI support
- Visual Studio Code with Ionide and MAUI extensions
-
Platform-Specific Tools
For Android Development:
- Android SDK (API level 21 or higher)
- Android Emulator or physical device
- Java Development Kit (JDK) 11 or later
For iOS Development (macOS only):
- Xcode 14.0 or later
- iOS Simulator or physical device
- Apple Developer account (for device deployment)
dotnet workload install mauiVerify installation:
dotnet workload listYou should see maui in the list of installed workloads.
Navigate to the tutorial folder:
cd FabulousMauiTutorial/TaskManagerAppdotnet restoreThis downloads all required dependencies:
- Fabulous.MauiControls
- Microsoft.Maui.Controls
- SkiaSharp.Views.Maui.Controls
- FSharp.Core
For Android:
dotnet build -f net9.0-androidFor iOS (macOS only):
dotnet build -f net9.0-ios- List available devices:
adb devices
adb.exe has to be in the path.
-
Create an emulator (if needed):
# List available system images sdkmanager --list # Create emulator avdmanager create avd -n TaskManager -k "system-images;android-33;google_apis;x86_64"
-
Run on emulator:
dotnet build -t:Run -f net9.0-android
This needs to have the emulator set up (Tools -> Android -> Android Device Manager). See: https://learn.microsoft.com/en-us/dotnet/maui/android/emulator/troubleshooting?view=net-maui-9.0 Also if VS2022 runner doesn't work well for you, try starting from command line.
- Enable Developer Options and USB Debugging on your Android device
- Connect device via USB
- Run:
dotnet build -t:Run -f net9.0-android
-
List available simulators:
xcrun simctl list devices
-
Run on simulator:
dotnet build -t:Run -f net9.0-ios
- Connect your iOS device
- Open Xcode and configure signing
- Run:
dotnet build -t:Run -f net9.0-ios
Error: "Workload 'maui' not installed"
dotnet workload install mauiError: "Java SDK not found"
- Install JDK 11 or later
- Set
JAVA_HOMEenvironment variable
Error: "Android SDK not found"
- Install Android SDK via Visual Studio or Android Studio
- Set
ANDROID_HOMEenvironment variable
App crashes on startup
- Check for missing dependencies in
.csproj - Verify all F# files are included in compilation order
- Check platform-specific implementations
Controls not rendering
- Ensure SkiaSharp workload is installed
- Check
UseSkiaSharp()is called in MauiProgram
iOS: Code signing error
- Open project in Xcode
- Configure signing & capabilities
- Select valid development team
Android: Deployment failed
- Enable USB debugging on device
- Accept RSA key fingerprint prompt
- Check device is authorized:
adb devices
Enable detailed logging:
-
Set environment variable:
export DOTNET_LOGGING_LEVEL=Debug -
Run with verbose output:
dotnet build -t:Run -f net9.0-android -v detailed
If experiencing persistent issues:
# Clean all build artifacts
dotnet clean
# Remove bin and obj folders
rm -rf bin obj
# Restore and rebuild
dotnet restore
dotnet build.NET MAUI supports hot reload for rapid iteration:
- Start the app in debug mode
- Make changes to F# code
- Save the file
- Changes apply automatically (XAML hot reload)
Note: F# hot reload support is limited compared to C#. Some changes may require app restart.
- Set breakpoints in F# code
- Press F5 to start debugging
- App runs with debugger attached
- Install Ionide-fsharp extension
- Configure launch.json for MAUI
- Press F5 to debug
# Android
dotnet build -t:Run -f net9.0-android -c Debug
# iOS
dotnet build -t:Run -f net9.0-ios -c DebugFor XAML previews:
- Open in Visual Studio
- Use XAML previewer
Note: This sample uses Fabulous (code-based UI), so XAML preview isn't applicable.
TaskManagerApp/
├── Domain.fs # Core domain models
├── MockData.fs # In-memory data store
├── Controls/
│ └── RadialSlider.fs # Custom radial slider control
├── Features/
│ ├── TaskList/ # Task list feature
│ │ ├── Types.fs
│ │ ├── State.fs
│ │ └── View.fs
│ └── TaskDetail/ # Task detail feature
│ ├── Types.fs
│ ├── State.fs
│ └── View.fs
├── Root/ # App root and navigation
│ ├── Types.fs
│ ├── State.fs
│ └── View.fs
├── MauiProgram.fs # App initialization
└── Platforms/ # Platform-specific code
├── Android/
└── iOS/
The order in TaskManagerApp.fsproj is crucial:
- Domain models first
- Shared utilities and controls
- Features (Types → State → View)
- Root module last
- MauiProgram.fs at the end
-
Start with Domain.fs
- Understand the data models
- See how F# types ensure correctness
-
Check MockData.fs
- See the in-memory data store
- Notice the API abstraction
-
Examine TaskList feature
- Follow the MVU pattern
- See how messages flow
-
Study the RadialSlider
- Custom SkiaSharp control
- Integration with Fabulous
Try these exercises:
-
Add task categories
- Update domain models
- Add category filter
- Update UI
-
Implement persistence
- Replace MockDataStore with SQLite
- Add data migration
-
Add authentication
- Create login screen
- Manage user sessions
- Secure API calls
-
Enhance UI
- Add animations
- Implement swipe gestures
- Add dark mode
If you encounter issues:
- Check the Troubleshooting section
- Review the Architecture Guide
- Search existing GitHub issues
- Ask in F# community forums
- Create a detailed issue report
Debug Build:
dotnet build -c Debug- Includes debug symbols
- Larger app size
- Slower performance
- Better for development
Release Build:
dotnet build -c Release- Optimized code
- Smaller app size
- Better performance
- For production deployment
Android APK:
dotnet publish -f net9.0-android -c ReleaseAndroid AAB (for Play Store):
dotnet publish -f net9.0-android -c Release -p:AndroidPackageFormat=aabiOS IPA:
dotnet publish -f net9.0-ios -c Release-
Use Release builds for testing
- Debug builds are significantly slower
- Test performance with Release configuration
-
Optimize images
- Use vector graphics (SVG) where possible
- Compress raster images
-
Profile the app
- Use platform profiling tools
- Monitor memory usage
- Check for performance bottlenecks
-
Minimize rebuilds
- Use incremental builds
- Cache NuGet packages
-
Generate signing key:
keytool -genkey -v -keystore myapp.keystore -alias myapp -keyalg RSA -keysize 2048 -validity 10000
-
Configure signing in
.csproj -
Build signed APK/AAB:
dotnet publish -f net9.0-android -c Release
- Configure signing in Xcode
- Archive the app
- Upload to App Store Connect
Example GitHub Actions workflow:
name: Build
on: [push, pull_request]
jobs:
build-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: 9.0.x
- name: Install MAUI
run: dotnet workload install maui
- name: Build
run: dotnet build -f net9.0-androidYou now have a working Fabulous MAUI F# application! The Task Manager sample demonstrates core concepts and patterns that you can apply to your own projects.
Happy coding! 🚀