Flutter + Claude Code — одна кодовая база на все платформы

Flutter — это когда надо один раз написать и получить iOS, Android, Web и десктоп. Claude Code знает Dart достаточно хорошо, чтобы генерировать идиоматический код, если в CLAUDE.md зафиксировать современный стек: Riverpod 2.x, GoRouter, freezed.

Flutter + Claude Code — одна кодовая база на все платформы

Канал с гайдами и контентом по claude code, выкладываем новости (когда режут лимиты в 10 раз) и какие инструменты через claude реализуем для проектов, канал: https://t.me/claudedevolper

Стартовый каркас

flutter create my_app cd my_app flutter pub add flutter_riverpod go_router dio freezed_annotation json_annotation flutter pub add --dev build_runner freezed json_serializable

CLAUDE.md

Стек - Flutter 3.24+, Dart 3.5+ - Riverpod 2.x (flutter_riverpod, не provider) - go_router для навигации - dio для HTTP - freezed для моделей - flutter_test + integration_test ## Структура - lib/features// — фича (UI + providers + модели) - lib/core/ — общее (theme, router, http client) - lib/main.dart — entry point ## Правила - Все модели через freezed, никаких ручных fromJson/toJson - State через Riverpod providers, не setState - Нет StatefulWidget где можно ConsumerWidget - Navigator.push запрещён — только GoRouter

Freezed-модель

// lib/features/product/product.dart import 'package:freezed_annotation/freezed_annotation.dart'; part 'product.freezed.dart'; part 'product.g.dart'; @freezed class Product with _$Product { const factory Product({ required int id, required String name, required int priceCents, }) = _Product; factory Product.fromJson(Map json) => _$ProductFromJson(json); }

После flutter pub run build_runner build получаешь ==, copyWith, JSON-сериализацию бесплатно.

Riverpod-provider

// lib/features/product/products_provider.dart import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:dio/dio.dart'; import 'product.dart'; final dioProvider = Provider((ref) => Dio(BaseOptions( baseUrl: 'https://api.example.com', ))); final productsProvider = FutureProvider>((ref) async { final dio = ref.read(dioProvider); final res = await dio.get>('/products'); return res.data!.map((e) => Product.fromJson(e)).toList(); });

UI с AsyncValue

// lib/features/product/products_page.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'products_provider.dart'; class ProductsPage extends ConsumerWidget { const ProductsPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final async = ref.watch(productsProvider); return Scaffold( appBar: AppBar(title: const Text('Продукты')), body: async.when( loading: () => const Center(child: CircularProgressIndicator()), error: (e, _) => Center(child: Text('Ошибка: $e')), data: (products) => RefreshIndicator( onRefresh: () async => ref.invalidate(productsProvider), child: ListView.separated( itemCount: products.length, separatorBuilder: (_, __) => const Divider(height: 0), itemBuilder: (_, i) { final p = products[i]; return ListTile( title: Text(p.name), subtitle: Text('${p.priceCents / 100} ₽'), onTap: () => context.push('/product/${p.id}'), ); }, ), ), ), ); } }

Маршрутизация через GoRouter

// lib/core/router.dart import 'package:go_router/go_router.dart'; import '../features/product/products_page.dart'; import '../features/product/product_detail_page.dart'; final router = GoRouter( routes: [ GoRoute( path: '/', builder: (_, __) => const ProductsPage(), ), GoRoute( path: '/product/:id', builder: (_, state) => ProductDetailPage( id: int.parse(state.pathParameters['id']!), ), ), ], );

Сборка

flutter build apk --release # Android APK flutter build appbundle --release # Play Store flutter build ios --release # iOS (нужен Mac) flutter build web --release --wasm # Web с WASM flutter build macos --release flutter build windows --release flutter build linux --release

Подводные камни

  • Claude любит Provider (v4). В CLAUDE.md: «Riverpod 2.x, не provider package».
  • build_runner после каждого @freezed класса. Без него _$Product не существует.
  • iOS сборка только с Mac. Или через Codemagic/Bitrise.
  • Hot reload ломается при изменении enum/freezed. Нужен full restart.

Как попробовать

1. flutter create + pub add зависимостей 2. CLAUDE.md 3. Попроси «список продуктов с Riverpod + Dio + Freezed» 4. flutter run — работает сразу на эмуляторе

Flutter + Claude Code — одна кодовая база на все платформы

Канал с гайдами и контентом по claude code, выкладываем новости (когда режут лимиты в 10 раз) и какие инструменты через claude реализуем для проектов, канал: https://t.me/claudedevolper

Начать дискуссию