Claude Code для Flutter: сценарии генерации экранов и навигации, простые правила управления состоянием и приемы, чтобы прототип быстро стал поддерживаемым.

Хаос обычно начинается не с Flutter, а с гонки за первым результатом. Вы просите ассистента накидать 3-5 экранов, быстро соединяете их кнопками, добавляете пару заглушек данных - и через вечер уже страшно трогать код.
Первое, что ломается, это навигация. Сначала хватает пары Navigator.push, потом появляются условия, возвраты, экраны с параметрами, и внезапно непонятно, откуда пользователь сюда попал и куда должен вернуться. В прототипе это выглядит так: одна и та же карточка открывается разными путями, а логика переходов размазана по кнопкам в разных местах.
Второй источник проблем - состояние. Пока данные фейковые, вы держите всё в setState и передаёте параметры через конструкторы. Но как только появляется загрузка, фильтры или авторизация, UI начинает дергаться: одно поле обновилось, другое нет, а часть логики живёт прямо в виджетах. Самая частая ошибка - смешать несколько подходов сразу: где-то setState, где-то глобальные переменные, где-то случайный ChangeNotifier.
Третье - дубли и расползание папок. Генерация ускоряет старт, но без правил плодит почти одинаковые виджеты: две версии кнопки, три «похожих» карточки, четыре экрана с разными отступами. Через неделю никто не помнит, какой файл главный.
Перед первым запросом к ассистенту ответьте на три вопроса:
Если это проговорить заранее, ассистенту проще генерировать не просто «картинки из виджетов», а структуру, которую реально поддерживать.
Быстрый прототип чаще всего разваливается не из-за кода, а из-за требований, которые меняются на ходу. Перед тем как просить Claude Code для Flutter сгенерировать экраны, зафиксируйте небольшой, но четкий «контракт»: какие экраны точно будут, какая дизайн-база используется, какие данные считаются правдоподобными.
Почти в любом приложении всплывает один и тот же набор сценариев: список, детали, создание/редактирование, профиль, настройки. Если обозначить это сразу, генерация будет точнее, а навигация не превратится в мешанину.
Дальше задайте базовые правила UI, чтобы не получить «зоопарк» виджетов: Material 3 или нет, палитра и типографика по умолчанию, нужен ли темный режим, будет ли локализация (хотя бы ru/en), нужна ли адаптивность под узкие/широкие экраны. Даже одна строка про это в запросе заметно повышает консистентность.
Наконец, определите минимальный набор сущностей и данных. Не надо проектировать всю базу - достаточно 1-2 ключевых сущностей и нескольких полей, которые делают экраны «живыми». Например, для приложения задач: Task(id, title, description, status, dueDate, assigneeName). Тогда список показывает title и статус, детали - описание и дедлайн, форма - те же поля, настройки - тему и язык.
Если вы работаете в TakProsto, удобно описывать сущности и поля в planning mode: потом проще генерировать экраны в одном стиле и не переписывать половину UI из-за мелких правок.
Прототипы в Flutter разваливаются не из-за «сложного кода», а из-за вопросов «куда положить файл» и «как назвать экран». Если заранее зафиксировать скелет, генерация начинает попадать в нужные места, а не плодить дубли.
Самый понятный вариант - структура по фичам. Тогда каждый кусок приложения живёт рядом со своими экранами, состоянием и данными, и его проще выкинуть или довести до продукта.
Минимальная базовая структура:
Внутри каждой фичи держите одинаковые папки: ui (экраны и виджеты), state (логика состояния), data (репозитории, модели, моки). Даже если сейчас нет «настоящего» бэкенда, data с моками сразу задаёт границы.
Дальше - правила именования. Они нужны не для красоты, а чтобы генератор не создавал ScreenA, ScreenB и «final2.dart».
Чтобы каждый новый экран был предсказуемым, держите простой шаблон: сам экран (UI), модель состояния (loading/ready/error), зависимости (что нужно получить из репозитория), тестовые данные (мок-ответ или заглушка). Тогда добавление экрана становится повторяемым шагом.
Хороший запрос для генерации экрана начинается не с виджетов, а со смысла: зачем экран нужен и что пользователь должен сделать. Если вы пишете в Claude Code для Flutter (или в любом чат-генераторе), дайте модели контекст так, чтобы она могла принять верные решения, а не угадывать.
Описывайте экран через четыре опоры: цель, входные данные, состояния, ограничения.
userId, объект товара, режим create/edit).Чтобы не генерировать по одному экрану, задавайте сценарий цепочкой. Например: список -> детали -> редактирование. Так вы сразу согласуете модели, параметры между экранами, доступные действия и точку возврата.
Перед отправкой запроса проверьте, что в нем есть:
Полезный приём - просить не только экраны, но и заготовки для поддержки: пустые состояния, скелетоны, общие компоненты (например, AppScaffold, PrimaryButton, ErrorView). Это резко снижает копипасту, когда прототип начинает расти.
Пример формулировки (подходит и для TakProsto.ai, и для других чат-инструментов):
Сгенерируй 3 экрана Flutter: ProductsList, ProductDetails, ProductEdit.
Цель: просмотр каталога, карточки товара и редактирование.
Навигация: List -> Details(productId) -> Edit(productId), после сохранения вернуться на Details.
Состояния:
- loading: показать skeleton
- empty: текст "Товаров пока нет" и кнопка "Добавить"
- error: ErrorView с кнопкой "Повторить"
Данные: пока мок-репозиторий, без реального API.
Переиспользование: общий AppScaffold, PrimaryButton, ErrorView.
Валидация в Edit: название обязательно, цена > 0.
Такой запрос даёт структуру сразу на несколько экранов и оставляет меньше места для хаоса, когда прототип начинает расти.
Проблемы в прототипах чаще всего начинаются с навигации: где-то пушим по строке, где-то по имени, а где-то экран сам решает, куда идти дальше. Через пару дней вы уже боитесь трогать переходы, потому что «всё держится на честном слове».
Правило простое: выберите один стиль и держитесь его. В Flutter это обычно означает: либо go_router, либо Navigator 2.0, либо классический Navigator 1.0. Для быстрого прототипа часто выбирают go_router, но важнее не инструмент, а единые правила. Если вы генерируете код с помощью Claude Code для Flutter, зафиксируйте выбор сразу и просите генерировать только в этом стиле.
Начните с простой карты приложения и не усложняйте раньше времени:
Эта карта помогает заранее решить два вопроса: где «точка входа» и как не сломать back-навигацию при табах.
Второе правило: навигация должна жить в одном модуле, а экраны не должны знать строки маршрутов. Экран не должен делать context.go('/profile/123'). Пусть он вызывает понятное действие: openProfile(userId).
Практичный приём: один файл (или класс) с маршрутами и один слой-обёртка для переходов. Тогда при смене структуры путей вы правите одно место, а не десятки экранов.
Самый быстрый способ превратить прототип в кашу - хранить логику прямо в виджетах. Простое правило: UI ничего не решает. Он только показывает состояние и отправляет события (нажали кнопку, обновили список, ввели текст). Всё остальное живёт вне экрана: загрузка данных, валидация, обработка ошибок.
Выберите один уровень сложности и держите его по всему приложению. При генерации кода это критично: модель легко начинает «подмешивать» разные стили.
Обычно хватает такой договоренности:
setState - только для локального UI (переключатель, выбранная вкладка, раскрытие карточки).Когда подход один, исправлять и дополнять проще: новый экран копирует структуру старого, а не изобретает свою.
Договоритесь об одном наборе состояний для любых экранов. Например:
initial (еще ничего не делали)loading (идет запрос)success (есть данные)empty (данных нет, но это норма)error (есть ошибка и текст для пользователя)Практика: экран каталога всегда рисует один и тот же шаблон. loading показывает скелетон, empty предлагает действие, error даёт кнопку «Повторить». Бизнес-логика решает, что именно произошло. UI аккуратно отображает результат.
Частая причина, почему прототип невозможно развивать: экран сам решает, откуда брать данные, как их хранить и как показывать. Даже если вы используете Claude Code для Flutter, держите правило: UI только рисует и отправляет события, а данные живут отдельно.
Минимальная схема для прототипа: источник данных (API или фейк) отдаёт DTO, репозиторий решает, откуда брать данные, а маппинг превращает DTO в модели, удобные для экрана. Тогда вы сможете заменить фейковый источник на настоящий, не переписывая виджеты.
Чтобы не утонуть в деталях, держите границы ответственности:
Фейковый источник данных делайте максимально похожим на будущий контракт. Например, храните фикстуры в виде списка Map (как будто это ответ сервера), а не готовых UI-моделей. Сегодня экран получает данные из FakeCatalogDataSource, завтра вы меняете реализацию на ApiCatalogDataSource, а репозиторий и экран остаются прежними.
Простой тест: если вы можете удалить весь слой UI и при этом репозиторий всё ещё «умеет» отдавать данные, слои разделены нормально.
Самая быстрая дорога к хаосу - копировать один и тот же виджет из экрана в экран и править мелочи руками. Через неделю у вас будет пять почти одинаковых кнопок, три варианта отступов и два оттенка одного цвета, а правка начнёт занимать больше времени, чем генерация.
Если вы используете Claude Code для Flutter, просите выносить повторяющиеся куски в компоненты сразу. «Потом» обычно не наступает. Хороший сигнал, что пора выделять компонент: вы видите один и тот же блок второй раз (карточка товара, поле поиска, строка профиля).
Сначала зафиксируйте минимальный набор компонентов, которые встречаются почти в каждом приложении:
Дальше включите правило: никаких хардкодных цветов, размеров и отступов в экранах. Держите дизайн-токены в одном месте: ThemeData, ColorScheme, TextTheme, а для расстояний и радиусов - простая структура вроде AppSpacing и AppRadii.
Пример: вы сделали 5 экранов, и заказчик просит «чуть больше воздуха» и другой акцентный цвет. Если отступы и цвета захардкожены, вы будете выискивать их по всему проекту. Если же в экранах стоят только AppSpacing.m и theme.colorScheme.primary, правка занимает минуты.
Ещё мелочь, которая экономит часы: договоритесь о правилах именования компонентов (AppButton, AppTextField) и складывайте их в одну папку. Тогда генерация новых экранов опирается на одни и те же «кирпичики».
Главная ловушка генерации: код появляется быстро, а правила у проекта не появляются вовсе. В результате прототип работает сегодня, но завтра любое изменение ломает пол-экрана.
Самые частые проблемы:
setState, на другом Provider, на третьем Riverpod или BLoC. Становится непонятно, где источник правды и кто отвечает за загрузку, ошибки и кэш.Отдельная боль - слишком умные абстракции раньше времени. Генератор может предложить универсальные BaseScreen, уровни наследования и фабрики на все случаи. Для прототипа это чаще лишнее.
Проверьте себя:
Если вы используете Claude Code для Flutter, добавляйте эти правила прямо в запрос: генерация будет чуть более дисциплинированной, и поддержка не превратится в ручной ремонт каждый день.
Перед тем как добавлять новые экраны, остановитесь на 10 минут и проверьте базовые вещи. Это скучно, зато потом не придется переписывать половину прототипа, когда появятся реальные данные и новые сценарии.
Сначала пройдитесь по навигации. Должна быть единая схема: где маршруты объявлены, как именуются, откуда делаются переходы. Если часть переходов живёт в кнопках, часть - в обработчиках событий, а часть - в «магических» строках, переименования начнут ломать экраны.
Дальше проверьте состояния каждого экрана. Даже в прототипе у UI обычно есть минимум три ветки: загрузка, пусто и ошибка. Если их нет, вы позже начнете «долепливать» состояния на ходу и получите разный подход на разных экранах.
Теперь - переиспользование. Если вы видите два похожих блока верстки по 15-20 строк, лучше вынести их в компонент с понятными параметрами.
Короткий контрольный список:
Если вы генерите экраны через Claude Code для Flutter, добавляйте этот список в конец запроса: попросите использовать вашу схему маршрутов, предусмотреть состояния и не дублировать компоненты.
Представим простое приложение задач: список, карточка задачи, создание, фильтры, настройки. Цель вечера - получить живой прототип с понятной навигацией и одним способом управления состоянием. Каждый следующий шаг должен уменьшать хаос, а не добавлять новые подходы.
Сами экраны:
Чтобы не получить кашу, разбейте генерацию на 4 итерации и после каждой фиксируйте изменения.
После каждой итерации задавайте ассистенту вопросы, которые заставляют его чистить код, а не разрастать его.
Такой прототип удобно переносить в платформу вроде TakProsto: вы генерируете по шагам, проверяете руками, а потом экспортируете исходники Flutter и сохраняете контроль над структурой проекта.
Чтобы прототип не превратился в набор случайных экранов, держите короткий документ на 1-2 страницы. Его цель - чтобы вы и генератор работали по одной схеме, даже через неделю.
Достаточно зафиксировать четыре вещи: какие экраны нужны, как между ними переходят, где хранится состояние, и откуда берутся данные (моки, локальная БД, API). Например: «Экран каталога открывает карточку, карточка может добавить в избранное, избранное видно в профиле, состояние избранного живет в одном месте и переживает перезапуск приложения».
Полезно завести отдельный файл с правилами проекта и обновлять его перед каждой новой генерацией. Так снижается шанс, что вам сгенерируют второй роутер, новый стиль кнопок или ещё один способ хранить loading.
Что стоит держать в правилах под рукой:
Если нужен вариант, где прототипы собираются через чат с возможностью деплоя и экспорта исходников, можно посмотреть TakProsto (takprosto.ai) как рабочий процесс для Flutter, веба и мобильных приложений.
Перед тем как генерировать следующую порцию кода, задайте себе три вопроса: что добавляем, какие состояния появятся, и какие маршруты изменятся. Этот маленький ритуал обычно экономит часы правок, особенно при работе с Claude Code для Flutter. "}