Use Cases (Mis à jour: 02/06/2026)

Claude Code pour Flutter/Dart : cartographie, état, tests et builds

Guide pratique Claude Code avec Flutter/Dart : pubspec, widgets, état, tests, builds et vérification device.

Claude Code pour Flutter/Dart : cartographie, état, tests et builds

Claude Code est surtout utile en Flutter/Dart quand il travaille comme un partenaire qui comprend le projet, pas comme un générateur de widget isolé. Une modification réelle peut toucher lib/, pubspec.yaml, les assets, les tests, Android, iOS, le Web, les émulateurs et les commandes de build. Un widget est une brique d’interface, le state est la donnée qui change l’affichage, et le pubspec est le fichier qui déclare les dépendances, ressources et contraintes de SDK.

L’exemple de cet article est un petit écran de panier. Il est assez court pour être collé dans un projet flutter create, mais il expose des erreurs courantes : créer l’état dans build, ajouter un package sans nécessité, oublier les widget tests, ou supposer qu’Android, iOS et Web ont les mêmes contraintes.

Gardez les références officielles ouvertes : Flutter CLI, Flutter testing, Widget testing, Flutter pubspec options, Dart pubspec, Platform channels et Claude Code common workflows. À lire aussi : React Native, stratégies de test et bonnes pratiques CLAUDE.md.

Cartographier avant de modifier

Ne commencez pas par “construis un écran panier”. Demandez d’abord à Claude Code d’inspecter le dépôt sans modifier. Ce harness, ou cadre de travail sûr, précise les fichiers autorisés, les limites, les commandes et les critères de revue.

Lis d'abord ce projet Flutter.
Ne modifie aucun fichier pour l'instant.
Rapporte :
1. Contraintes SDK, dépendances et assets dans pubspec.yaml
2. Organisation UI, état et couche data sous lib/
3. Style de tests existant dans test/ et integration_test/
4. Targets actifs dans android/, ios/, web/, macos/, windows/ et linux/
5. Présence de flutter analyze, flutter test et commandes de build
Termine par les fichiers modifiables et ceux à éviter.
ZoneClaude Code peut faireDécision humaine
Carte projetConventions, dépendances, testsLimites de modification
WidgetComposant, accessibilité, responsiveTexte produit et design
ÉtatRespecter setState, ChangeNotifier, Riverpod, Bloc ou le style existantStratégie d’état globale
pubspecProposer dépendances et assetsAccepter ou refuser un package
PlateformeDifférences Android/iOS/Web/DesktopCibles supportées
Tests/buildWidget test, integration test, commandesDécision de merge et release

Garder pubspec maîtrisé

pubspec.yaml contrôle les dépendances, assets, contraintes SDK et packages de test. Avant toute édition, Claude Code doit justifier le changement, proposer une alternative, nommer les fichiers touchés et donner les commandes de vérification.

name: cart_ai_demo
description: A small Flutter cart screen used to verify Claude Code prompts.
publish_to: "none"

environment:
  sdk: ">=3.4.0 <4.0.0"

dependencies:
  flutter:
    sdk: flutter

dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter
  flutter_lints: ^6.0.0

flutter:
  uses-material-design: true
  assets:
    - assets/images/

Pour un sandbox neuf, créez une base propre. Dans un dépôt existant, demandez à Claude Code d’adapter ces commandes au projet.

flutter create cart_ai_demo
cd cart_ai_demo
flutter pub get
flutter analyze
flutter test

Les erreurs fréquentes sont l’indentation cassée sous assets, le changement inutile de pubspec.lock, et l’ajout d’une bibliothèque d’état pour une interaction simple. Utilisez un prompt strict :

Inspecte pubspec.yaml et détermine si le changement panier exige une nouvelle dépendance.
Avant d'éditer, donne raison, alternatives, fichiers affectés et commandes de vérification.
Ne modifie pas pubspec.yaml ni pubspec.lock sans validation.

Modifier widget et état ensemble

Le code suivant peut remplacer lib/main.dart dans un projet flutter create cart_ai_demo. Il n’utilise que le SDK Flutter. CartController porte les mutations d’état, tandis que le widget affiche l’état courant.

import 'package:flutter/material.dart';

void main() => runApp(const CartDemoApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cart AI Demo',
      theme: ThemeData(colorSchemeSeed: Colors.teal, useMaterial3: true),
      home: const CartSummaryPage(),
    );
  }
}

class CartLine {
  const CartLine({required this.name, required this.price, required this.quantity});
  final String name;
  final int price;
  final int quantity;

  CartLine copyWith({int? quantity}) =>
      CartLine(name: name, price: price, quantity: quantity ?? this.quantity);
}

class CartController extends ChangeNotifier {
  final List<CartLine> _lines = const [
    CartLine(name: 'Dart notebook', price: 1800, quantity: 1),
    CartLine(name: 'Flutter sticker', price: 500, quantity: 2),
  ].toList();

  List<CartLine> get lines => List.unmodifiable(_lines);
  int get total => _lines.fold(0, (sum, line) => sum + line.price * line.quantity);

  void increment(int index) {
    final line = _lines[index];
    _lines[index] = line.copyWith(quantity: line.quantity + 1);
    notifyListeners();
  }

  void decrement(int index) {
    final line = _lines[index];
    if (line.quantity == 1) return;
    _lines[index] = line.copyWith(quantity: line.quantity - 1);
    notifyListeners();
  }
}

class CartSummaryPage extends StatefulWidget {
  const CartSummaryPage({super.key});

  @override
  State<CartSummaryPage> createState() => _CartSummaryPageState();
}

class _CartSummaryPageState extends State<CartSummaryPage> {
  late final CartController controller;

  @override
  void initState() {
    super.initState();
    controller = CartController();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Cart summary')),
      body: AnimatedBuilder(
        animation: controller,
        builder: (context, _) => ListView(
          padding: const EdgeInsets.all(16),
          children: [
            for (final entry in controller.lines.indexed)
              ListTile(
                title: Text(entry.$2.name),
                subtitle: Text('JPY ${entry.$2.price} x ${entry.$2.quantity}'),
                trailing: Wrap(
                  spacing: 8,
                  children: [
                    IconButton(
                      tooltip: 'Decrease ${entry.$2.name}',
                      onPressed: () => controller.decrement(entry.$1),
                      icon: const Icon(Icons.remove_circle_outline),
                    ),
                    IconButton(
                      tooltip: 'Increase ${entry.$2.name}',
                      onPressed: () => controller.increment(entry.$1),
                      icon: const Icon(Icons.add_circle_outline),
                    ),
                  ],
                ),
              ),
            const Divider(),
            Text('Total: JPY ${controller.total}',
                style: Theme.of(context).textTheme.headlineSmall),
          ],
        ),
      ),
    );
  }
}

Les pièges sont clairs : créer le controller dans build, oublier notifyListeners(), disperser le calcul du total dans plusieurs widgets ou ne pas appeler dispose.

Ajouter tests et vérification device

Avec le nom de projet cart_ai_demo, placez ceci dans test/cart_summary_test.dart.

import 'package:cart_ai_demo/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('updates the cart total when quantity changes', (tester) async {
    await tester.pumpWidget(const CartDemoApp());
    expect(find.text('Total: JPY 2800'), findsOneWidget);

    await tester.tap(find.byIcon(Icons.add_circle_outline).first);
    await tester.pump();
    expect(find.text('Total: JPY 4600'), findsOneWidget);

    await tester.tap(find.byIcon(Icons.remove_circle_outline).first);
    await tester.pump();
    expect(find.text('Total: JPY 2800'), findsOneWidget);
  });
}
flutter analyze
flutter test

Pour un émulateur ou appareil réel, ajoutez un integration test.

import 'package:cart_ai_demo/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('cart can be changed on a real device', (tester) async {
    await tester.pumpWidget(const CartDemoApp());
    await tester.tap(find.byIcon(Icons.add_circle_outline).last);
    await tester.pumpAndSettle();
    expect(find.text('Total: JPY 3300'), findsOneWidget);
  });
}
flutter devices
flutter test integration_test -d <device_id>

Cas d’usage et pièges plateforme

Cas 1 : ajouter quantité, filtre ou tri à une liste existante. Cas 2 : nettoyer pubspec.yaml et les assets. Cas 3 : diagnostiquer un bug limité à Android, iOS ou Web, comme permissions, notifications, localisation ou liens externes. Cas 4 : ajouter des tests de régression à un écran legacy. Dans chaque cas, donnez les fichiers cibles, la commande attendue et le format de rapport en cas d’échec.

Flutter partage la couche Dart, pas tout l’environnement de déploiement. Android peut demander des permissions manifest, iOS des textes Info.plist, CocoaPods et signature, Web peut échouer sur CORS ou des API navigateur, Desktop a ses propres permissions et plugins.

flutter analyze
flutter test
flutter build apk --debug
flutter build web --release

Ne demandez pas une vérification iOS release sur une machine sans macOS ni Xcode. Le prompt doit indiquer ce qui peut être exécuté et ce qui reste à vérifier.

Prompts sûrs et note terrain

Investigation : lis lib/, test/, pubspec.yaml et les dossiers plateforme. N'édite rien. Retourne carte et risques.
Implémentation : change seulement lib/features/cart. Respecte le style d'état existant. N'ajoute pas de dépendance.
pubspec : si une dépendance est nécessaire, arrête-toi et donne raison, alternatives, impact et commandes.
Vérification : ajoute un widget test. Lance flutter analyze et flutter test. Rapporte les échecs avec fichiers.
Revue critique : vérifie dispose, async, effets dans build, plateforme, accessibilité, packages et tests manquants.

La note de terrain de Masa : les meilleurs résultats Flutter viennent du rythme “carte d’abord, petit diff ensuite, tests et build à la fin”. Le mauvais prompt était “fais un bel écran Flutter” : interface plausible, mais état créé dans build, packages inutiles et aucune revue plateforme. Les équipes peuvent commencer par la fiche gratuite puis structurer l’adoption avec formation et conseil Claude Code. Pour concevoir des garde-fous réutilisables, lisez harness engineering.

Ces extraits ciblent un projet flutter create cart_ai_demo. Cet environnement de rédaction n’a pas Flutter SDK installé, donc la vérification finale doit être faite dans un vrai environnement Flutter avec flutter analyze, flutter test, le build de la plateforme cible et un test émulateur ou appareil.

#Claude Code #Flutter #Dart #développement mobile #multiplateforme
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.