From jarvus-skills
Mobile app development using Flutter + Riverpod + go_router. Use when creating Flutter apps, adding screens, managing state with Riverpod, implementing routing, building offline-first features, or setting up storybook component development. Also use when the user mentions Flutter, Dart, mobile apps, or cross-platform development.
How this skill is triggered — by the user, by Claude, or both
Slash command
/jarvus-skills:mobile-flutterThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Cross-platform mobile app stack:
Cross-platform mobile app stack:
No code generation. Models use hand-written fromJson/toJson.
For offline-first apps that need a local relational database, add drift. This is the one exception to the no-codegen rule — drift generates typed query code from table definitions. See offline-first.md for setup and patterns.
Use asdf to manage Flutter and all tool versions:
# Install Flutter plugin (one-time)
asdf plugin add flutter
# Set project Flutter version
asdf set flutter latest
# Also set support tools as needed
asdf set ruby latest
asdf set cocoapods latest
asdf set rust latest # needed by some native deps
This creates a .tool-versions file in the project root. Never use the official Flutter installer, mise, or other version managers.
If .mcp.json doesn't exist in the project root, create it with this content:
{
"mcpServers": {
"dart": {
"type": "stdio",
"command": "dart",
"args": [
"mcp-server"
],
"env": {}
}
}
}
This wires up dart mcp-server so the agent can drive the app, inspect widgets, capture screenshots, and analyze files. See mcp-driving-and-screenshots.md for usage.
| File | When to Use |
|---|---|
| setup-guide.md | Starting a new Flutter project from scratch |
| patterns.md | Riverpod providers, repositories, screen architecture |
| offline-first.md | Adding drift for local SQLite, offline download/collect/sync |
| storybook.md | Setting up storybook, adding stories, mock data |
| gotchas.md | Common mistakes and platform-specific issues |
| mcp-driving-and-screenshots.md | Launching, driving (tap/type), debugging, and screenshotting a running app via the Dart MCP — and delivering screenshots to the user |
| mcp.json | Sample .mcp.json for the project root — copy here if it doesn't exist |
This skill defines the stack; pair it with the foundational Dart & Flutter agent skills that
apply to essentially any project on it. Install them into a project with npx skills
(the agent is auto-detected, so -y runs non-interactively):
# Quality, testing & debugging foundations
npx skills add dart-lang/skills \
-s dart-run-static-analysis \
-s dart-add-unit-test \
-s dart-fix-runtime-errors -y
npx skills add flutter/skills \
-s flutter-apply-architecture-best-practices \
-s flutter-add-widget-test \
-s flutter-add-integration-test -y
| Skill | Why it's foundational |
|---|---|
dart-run-static-analysis | dart analyze + dart fix --apply — during dev and before every commit |
dart-add-unit-test | unit tests for logic with package:test |
dart-fix-runtime-errors | stack-trace → fix → hot_reload loop |
flutter-apply-architecture-best-practices | layered UI/logic/data structure (complements patterns.md) |
flutter-add-widget-test | component-level tests with WidgetTester |
flutter-add-integration-test | Flutter Driver / integration_test harness — pairs with mcp-driving-and-screenshots.md |
Everything else is project-dependent — pick based on what the app actually does (JSON
serialization, declarative routing, localization, responsive layout, HTTP, drift, coverage,
mocks, pattern matching, …). Browse the full catalogs and --list to choose:
npx skills add dart-lang/skills --listnpx skills add flutter/skills --list# Install dependencies
flutter pub get
# Run on macOS (local dev)
flutter run -d macos
# Run storybook
flutter run -d macos -t lib/storybook/main.dart
# Run on web
flutter run -d chrome
# Analyze
flutter analyze lib/
Always use CLI commands — never edit pubspec.yaml directly:
# Add runtime dependency
flutter pub add <package>
# Add dev dependency
flutter pub add --dev <package>
# Add from git
flutter pub add --dev storybook_toolkit --git-url https://github.com/org/repo.git --git-ref branch-name
├── lib/
│ ├── main.dart # App entrypoint
│ ├── app.dart # MaterialApp.router + GoRouter + theme
│ ├── models/ # Plain Dart classes with fromJson/toJson
│ ├── providers/ # Riverpod providers
│ ├── repositories/ # Abstract interfaces + implementations
│ ├── database/ # drift tables + generated code (if using drift)
│ ├── screens/ # One directory per route
│ ├── storybook/ # Storybook entrypoint + mock data
│ ├── widgets/ # Shared reusable widgets
│ └── constants/ # Theme, colors, typography
├── specs/ # Feature specifications (if using spec-first)
├── .env # Environment config (gitignored)
├── .env.example # Template
└── pubspec.yaml
Screens (widgets) → read from providers, dispatch actions
Providers (Riverpod) → async state, business logic
Repositories (abstract) → data access boundary
API Client / Local DB → external boundaries
Screens never call repositories directly — always through providers. Repositories are abstract interfaces with real and fake implementations. Fakes are injected via Riverpod provider overrides in storybook and tests.
// Riverpod provider
final stationsProvider = FutureProvider<List<Station>>((ref) {
return ref.watch(stationRepositoryProvider).getAll();
});
// Family provider (parameterized)
final stationProvider = FutureProvider.family<Station?, String>((ref, id) {
return ref.watch(stationRepositoryProvider).get(id);
});
// Consumer widget
class MyScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final dataAsync = ref.watch(stationsProvider);
return dataAsync.when(
data: (stations) => ListView(...),
loading: () => CircularProgressIndicator(),
error: (e, _) => Text('Error: $e'),
);
}
}
// Navigation with go_router
context.push('/items/${item.id}'); // push onto stack
context.go('/login'); // replace stack
Package management: Use flutter pub add, never edit pubspec.yaml directly
VSCode SDK path: Use ~ not ${env:HOME} in .vscode/settings.json:
{"dart.flutterSdkPath": "~/.asdf/installs/flutter/3.41.6-stable"}
macOS entitlements: Network requests need com.apple.security.network.client, keychain needs keychain-access-groups — both in macos/Runner/DebugProfile.entitlements and Release.entitlements
macOS signing: Set development team in Xcode (Runner target → Signing & Capabilities → Team → All configurations)
Commit generated code separately: After any command that generates/changes code, commit those changes with the exact command in the message BEFORE making manual edits
npx claudepluginhub jarvusinnovations/agent-skills --plugin jarvus-skillsCreates bite-sized, testable implementation plans from specs or requirements, with file structure and task decomposition. Activates before coding multi-step tasks.