Skip to main content
rule

flutter — Cursor rule: Flutter project standards

A Cursor rule that pins down Flutter code style: formatting, lints, MVVM layers and Riverpod. Useful when the agent mixes widgets and state in one file.

Install into Cursor · Manually: put the files in place All methods and platforms ↓
.cursor/rules/flutter.mdc
Open on GitHub

What flutter does

Drop .cursor/rules/flutter.mdc into your repo and Cursor reads it on every request. The rule covers formatting through dart format, editor.formatOnSave in the IDE, and static analysis with flutter_lints. Style arguments stop, and common mistakes get caught earlier.

Project layout follows MVVM. The UI layer holds Views and ViewModels; the data layer holds Repositories and Services. Files are grouped by feature: features/auth/presentation/screens, features/auth/domain/models, features/auth/data/services. Riverpod handles state and dependency injection, with a Provider for the repository and a StateNotifierProvider for the view model in the examples.

The examples assume Dart 3.10+ and modern syntax such as const constructors and super.key. On an older SDK, or in a codebase built on Provider and setState, you will rewrite them to fit — check your SDK version before pasting the rule in.

What it helps with

  • settle on one formatting and lint setup across the team
  • split a Flutter app into features and layers
  • move state out of widgets into view models
  • wire up Riverpod instead of manual dependency injection
  • show the agent examples of good and bad Flutter code

Example prompts for the agent

  • Build a login screen following the rule: features/auth/presentation/screens/login_screen.dart plus its view model.
  • Refactor this widget into MVVM with Riverpod as the flutter rule describes.
  • Check my main.dart against the rule: const constructors, formatting, lints.

How to install flutter

Manually: put the files in place

.cursor/rules/flutter.mdc

Frontmatter: description, globs, alwaysApply

Step by step, with commands for each platform: Cursor rules: .mdc files, four modes and what replaced .cursorrules

Questions about flutter

How do I install the flutter rule in Cursor?

Create .cursor/rules/flutter.mdc in your project root and paste the rule contents into it. Cursor picks it up automatically.

What does the flutter rule do?

It gives the agent Flutter standards: formatting and lints, feature-based structure, a UI and Data layer split, and Riverpod for state and dependencies.

Which Dart version does the rule target?

The examples use Dart 3.10+ syntax like const constructors and super.key. On an older SDK you will need to adapt them.

Source text

flutter.mdc · CC0-1.0
---
description: Definitive guidelines for writing high-quality, performant, and maintainable Flutter applications using modern Dart 3.10+ practices.
globs: **/*
---
# flutter Best Practices

## Code Organization and Structure

### 1.1 Enforce Consistent Formatting and Linting
Always use `dart format` and enable `editor.formatOnSave` in your IDE. Integrate `flutter_lints` for robust static analysis. This eliminates style debates and catches common errors early.

❌ BAD (Manual formatting, inconsistent style)
```dart
// main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: 'My App', home: MyHomePage());
  }
}
```

✅ GOOD (Automated formatting, `flutter_lints` enabled)
```dart
// main.dart
void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      home: const MyHomePage(),
    );
  }
}
```

### 1.2 Adopt MVVM with Clear Layer Separation
Separate your application into distinct UI and Data layers. The UI layer consists of `Views` (widgets) and `ViewModels` (state logic). The Data layer comprises `Repositories` (business logic, data access) and `Services` (external API calls). This ensures maintainability and testability.

*   **`lib/` structure:**
    *   `features/`: Group by feature (e.g., `auth/`, `products/`).
        *   `auth/`:
            *   `presentation/`:
                *   `screens/`: `login_screen.dart` (View)
                *   `viewmodels/`: `login_viewmodel.dart` (ViewModel)
            *   `domain/`:
                *   `models/`: `user.dart` (Immutable data model)
                *   `repositories/`: `auth_repository.dart` (Abstract interface)
            *   `data/`:
                *   `repositories/`: `auth_repository_impl.dart` (Concrete implementation)
                *   `services/`: `auth_api_service.dart` (API calls)

### 1.3 Use Riverpod for State Management and Dependency Injection
Riverpod is the definitive choice for state management and dependency injection. It provides compile-time safety, simplifies testing, and eliminates common `Provider` pitfalls.

❌ BAD (InheritedWidget/Provider for DI, manual state updates)
```dart
// In a widget
final userRepo = Provider.of<UserRepository>(context);
// ...
userRepo.fetchUsers().then((_) => setState(() { /* ... */ }));
```

✅ GOOD (Riverpod for DI and state, auto-rebuilds)
```dart
// providers.dart
final authRepositoryProvider = Provider<AuthRepository>((ref) => AuthRepositoryImpl(ref.read(authApiService)));
final loginViewModelProvider = StateNotifierProvider<LoginViewModel, LoginState>((ref) => LoginViewModel(ref.read(authRepositoryProvider)));

// login_screen.dart (View)
class LoginScreen extends ConsumerWidget {
  const LoginScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final loginState = ref.watch(loginViewModelProvider);
    // ... UI with loginState.isLoading, loginState.error, etc.
    ElevatedButton(
      onPressed

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Similar IDE rules

Everything for Mobile →

From the same set69

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor