Claude Code para iteración UI en Flutter: un flujo práctico
Claude Code para iteración UI en Flutter: un bucle práctico para convertir historias de usuario en árboles de widgets, estado y navegación manteniendo los cambios modulares y fáciles de revisar.

El problema: iteración rápida de UI que no se convierte en caos
El trabajo rápido de UI en Flutter suele empezar bien. Ajustas un layout, añades un botón, mueves un campo y la pantalla mejora con rapidez. El problema aparece tras unas rondas, cuando la velocidad se convierte en un montón de cambios que nadie quiere revisar.
Los equipos suelen tropezar con los mismos fallos:
- El árbol de widgets crece sin plan, así que un cambio "pequeño" fuerza ediciones en muchos archivos.
- El estado se ata al código UI, haciendo las reconstrucciones impredecibles y los bugs más difíciles de rastrear.
- La lógica de navegación queda dispersa (un push aquí, un pop allá) hasta que los flujos dejan de coincidir con cómo los usuarios realmente se mueven por la app.
- Los nombres derivan, los componentes se duplican y nadie está seguro de cuál es el widget "real".
- Los diffs se hacen enormes, los revisores hojean, los problemas se cuelan y aparecen regresiones más tarde.
Una gran causa es el enfoque de "un gran prompt": describe la característica completa, pide el conjunto completo de pantallas y aceptas una salida grande. El asistente intenta ayudar, pero toca demasiadas partes del código a la vez. Eso hace que los cambios sean desordenados, difíciles de revisar y riesgosos de fusionar.
Un bucle repetible lo arregla obligando a la claridad y limitando la radio del impacto. En lugar de "construye la feature", haz esto repetidamente: elige una historia de usuario, genera la porción mínima de UI que la pruebe, añade solo el estado necesario para esa porción y luego cablea la navegación para una ruta. Cada pasada se mantiene lo bastante pequeña para revisar, y los errores son fáciles de revertir.
El objetivo aquí es un flujo práctico para convertir historias de usuario en pantallas concretas, manejo de estado y flujos de navegación sin perder el control. Hecho bien, terminas con piezas UI modulares, diffs más pequeños y menos sorpresas cuando cambian los requisitos.
Convierte las historias de usuario en una especificación UI clara que puedas construir
Las historias de usuario están escritas para humanos, no para árboles de widgets. Antes de generar nada, convierte la historia en una pequeña especificación UI que describa el comportamiento visible. "Hecho" debe ser comprobable: qué puede ver el usuario, qué puede tocar y qué confirmar, no si el diseño "se siente moderno".
Una forma simple de mantener el alcance concreto es dividir la historia en cuatro cubos:
- Pantallas: qué cambia, qué permanece igual.
- Componentes: qué piezas UI nuevas aparecen y dónde viven.
- Estados: loading, success, error, empty y qué muestra cada uno.
- Eventos: taps, swipes, pull-to-refresh, navegación atrás, reintentos.
Si la historia sigue nebulosa, responde estas preguntas en lenguaje llano:
- ¿Qué pantallas cambian y cuáles se mantienen?
- ¿Qué componentes nuevos aparecen y dónde pertenecen?
- ¿Qué estados existen y qué muestra cada uno?
- ¿Qué eventos conducen a los cambios de estado?
- ¿Cuál es la comprobación de aceptación que puedes hacer en 30 segundos tras ejecutar la app?
Añade restricciones temprano porque guían cada elección de layout: básicos del tema (colores, espaciado, tipografía), responsividad (primero móvil en vertical, luego anchos de tablet) y mínimos de accesibilidad como tamaño de objetivo táctil, escalado de texto legible y etiquetas significativas para iconos.
Finalmente, decide qué es estable y qué es flexible para no hacer churn en la base de código. Los items estables son cosas de las que dependen otras features, como nombres de rutas, modelos de datos y APIs existentes. Los items flexibles son más seguros de iterar, como la estructura del layout, microcopy y la composición exacta de widgets.
Ejemplo: "Como usuario, puedo guardar un ítem en Favoritos desde la pantalla de detalle." Una especificación UI construible podría ser:
- La pantalla de detalle muestra un icono de marcador.
- Al tocarlo, alterna el estado guardado.
- Mientras guarda, muestra un pequeño indicador de progreso.
- En fallo, muestra un error inline con una acción Reintentar.
- La navegación permanece igual (sin rutas nuevas).
Eso es suficiente para construir, revisar e iterar sin adivinar.
Configura el bucle de iteración para que los diffs se mantengan pequeños
Los diffs pequeños no significan trabajar más lento. Hacen que cada cambio de UI sea fácil de revisar, fácil de deshacer y difícil de romper. La regla más simple: una pantalla o una interacción por iteración.
Elige un slice estrecho antes de empezar. "Añadir un estado vacío a la pantalla Orders" es un buen slice. "Rehacer todo el flujo Orders" no lo es. Apunta a un diff que un compañero pueda entender en un minuto.
Una estructura de carpetas estable también ayuda a contener los cambios. Un layout simple, feature-first, evita que disperses widgets y rutas por la app:
lib/
features/
orders/
screens/
widgets/
state/
routes.dart
Mantén los widgets pequeños y compuestos. Cuando un widget tiene entradas y salidas claras, puedes cambiar layout sin tocar la lógica de estado, y cambiar estado sin reescribir la UI. Prefiere widgets que reciban valores simples y callbacks, no estado global.
Un bucle que se mantiene revisable:
- Escribe una especificación UI de 3 a 6 líneas para el slice (qué aparece, qué hacen los taps, cómo luce loading/error).
- Genera o edita solo los archivos mínimos necesarios (a menudo una pantalla y uno o dos widgets).
- Ejecuta la pantalla y luego haz una pasada de limpieza (nombres, espaciado, eliminar props no usadas).
- Haz commit con un mensaje que coincida con el slice.
Ponte una regla estricta: cada cambio debe ser fácil de revertir o aislar. Evita refactors incidentales mientras iteras una pantalla. Si detectas problemas no relacionados, apúntalos y arréglalos en un commit separado.
Si tu herramienta soporta snapshots y rollback, usa cada slice como un punto de snapshot. Algunas plataformas vibe-coding como Koder.ai incluyen snapshots y rollback, que pueden hacer la experimentación más segura cuando pruebas un cambio UI audaz.
Un hábito más que calma las primeras iteraciones: prefiere añadir widgets nuevos en lugar de editar compartidos. Los componentes compartidos son donde los cambios pequeños se vuelven grandes diffs.
Paso a paso: genera un árbol de widgets desde una historia de usuario
El trabajo UI rápido se mantiene seguro cuando separas pensar de teclear. Empieza obteniendo un plan claro del árbol de widgets antes de generar código.
-
Pide solo un esquema del árbol de widgets. Quieres nombres de widgets, jerarquía y qué muestra cada parte. Nada de código todavía. Aquí detectas estados faltantes, pantallas vacías y elecciones de layout extrañas mientras todo sigue barato de cambiar.
-
Pide un desglose de componentes con responsabilidades. Mantén cada widget enfocado: un widget renderiza el header, otro la lista, otro maneja empty/error. Si algo necesita estado más tarde, anótalo ahora pero no lo implementes todavía.
-
Genera el scaffold de la pantalla y widgets estateless. Comienza con un único archivo de pantalla con contenido placeholder y TODOs claros. Mantén las entradas explícitas (parámetros del constructor) para que puedas enchufar estado real después sin reescribir el árbol.
-
Haz una pasada separada para estilos y detalles de layout: espaciado, tipografía, theming y comportamiento responsive. Trata el estilado como un diff propio para que las revisiones sigan simples.
Un patrón de prompt que funciona
Pon restricciones al inicio para que el asistente no invente UI que no puedas enviar:
- Dispositivos objetivo (solo teléfono, también tablet, orientación)
- Restricciones de diseño (Material 3, colores del tema existente, reglas de espaciado)
- Expectativas de navegación (comportamiento atrás, deep links si los hay)
- Criterios de aceptación (qué debe ser visible y pulsable)
- Límites del código existente (qué archivos/widgets deben permanecer, convenciones de nombres)
Ejemplo concreto: la historia es "Como usuario, puedo revisar mis elementos guardados y eliminar uno." Pide un árbol de widgets que incluya una app bar, una lista con filas de ítem y un estado vacío. Luego solicita un desglose como SavedItemsScreen, SavedItemTile, EmptySavedItems. Solo después, genera el scaffold con widgets estateless y datos ficticios, y finalmente añade estilo (divider, padding y un botón claro de eliminar) en una pasada separada.
Añade manejo de estado sin inflar el código UI
La iteración UI se rompe cuando cada widget empieza a tomar decisiones. Mantén el árbol de widgets tonto: debe leer estado y renderizar, no contener reglas de negocio.
Comienza nombrando los estados en palabras sencillas. La mayoría de features necesitan más que "loading" y "done":
- Loading (primera carga o refresco)
- Empty (sin datos aún)
- Error (request fallido, permiso denegado)
- Success (datos listos)
- Entrada parcial (formulario iniciado pero no válido)
Luego lista eventos que pueden cambiar el estado: taps, submit de formulario, pull-to-refresh, navegación atrás, retry y "usuario editó un campo." Hacer esto desde el inicio evita suposiciones más adelante.
Mantén el estado separado de los widgets
Elige un enfoque de estado por feature y aférrate a él. El objetivo no es "el mejor patrón", sino diffs consistentes.
Para una pantalla pequeña, un controlador simple (como ChangeNotifier o ValueNotifier) suele ser suficiente. Pon la lógica en un solo sitio:
- Entradas: eventos desde la UI (submit, refresh, edit)
- Salida: un único objeto de estado que la UI pueda renderizar
- Efectos secundarios: llamadas a APIs y solicitudes de navegación
Antes de añadir código, escribe las transiciones de estado en frases. Ejemplo para una pantalla de login:
"Cuando el usuario toca Sign in: poner Loading. Si el email es inválido: quedarse en Entrada parcial y mostrar un mensaje inline. Si la contraseña es incorrecta: poner Error con mensaje y habilitar Retry. Si tiene éxito: poner Success y navegar a Home."
Luego genera el código Dart mínimo que coincida con esas frases. Las revisiones siguen simples porque puedes comparar el diff con las reglas.
Añade reglas comprobables para inputs inválidos
Haz la validación explícita. Decide qué ocurre cuando los inputs son inválidos:
- ¿Bloqueas el submit o lo permites y muestras errores?
- ¿Qué campos muestran errores y cuándo?
- ¿La navegación atrás descarta la entrada parcial o la conserva?
Cuando esas respuestas están escritas, tu UI se mantiene limpia y el código de estado pequeño.
Diseña flujos de navegación que coincidan con el comportamiento real del usuario
La buena navegación empieza como un mapa pequeño, no como un montón de rutas. Para cada historia de usuario, escribe cuatro momentos: dónde entra el usuario, el paso más probable siguiente, cómo cancelar y qué significa "atrás" (volver a la pantalla anterior o a un estado seguro).
Empieza con un mapa de rutas, luego fija qué viaja entre pantallas
Un mapa de rutas simple debería responder las preguntas que suelen causar rework:
- Entrada: qué pantalla se abre primero y desde dónde (pestaña, notificación, deep link)
- Siguiente: la ruta principal hacia adelante tras la acción primaria
- Cancelar: dónde cae el usuario si abandona el flujo
- Atrás: si atrás está permitido y qué debe preservar
- Fallback: a dónde ir si faltan datos requeridos
Luego define los parámetros que se pasan entre pantallas. Sé explícito: IDs (productId, orderId), filtros (rango de fechas, estado) y datos en borrador (un formulario parcialmente completado). Si omites esto, acabarás metiendo estado en singletons globales o reconstruyendo pantallas para "encontrar" contexto.
Planea deep links y patrones de "retornar un resultado"
Los deep links importan aunque no los lances el primer día. Decide qué ocurre cuando un usuario entra a mitad de flujo: ¿puedes cargar datos faltantes o debes redirigir a una pantalla de entrada segura?
También decide qué pantallas deben retornar resultados. Ejemplo: una pantalla "Select Address" retorna un addressId y la pantalla de checkout se actualiza sin un refresh completo. Mantén la forma del resultado pequeña y tipada para que los cambios sean fáciles de revisar.
Antes de codificar, señala casos límite: cambios no guardados (mostrar diálogo de confirmación), autenticación requerida (pausar y reanudar tras login) y datos faltantes o eliminados (mostrar error y una salida clara).
Haz que los cambios UI sean revisables y modulares
Cuando iteras rápido, el verdadero riesgo no es la UI "equivocada." Es la UI irrevisable. Si un compañero no puede decir qué cambió, por qué y qué permaneció estable, cada siguiente iteración se vuelve más lenta.
Una regla que ayuda: fija las interfaces primero y luego permite mover los internos. Estabiliza props públicas de widgets (entradas), pequeños modelos UI y argumentos de rutas. Una vez nombrados y tipados, puedes remodelar el árbol de widgets sin romper el resto de la app.
Prefiere costuras pequeñas y estables
Pide un plan amigable con diffs antes de generar código. Quieres un plan que diga qué archivos cambiarán y cuáles deben permanecer intactos. Eso mantiene las revisiones focalizadas y previene refactors accidentales que cambien comportamiento.
Patrones que mantienen diffs pequeños:
- Mantén widgets públicos delgados: aceptan solo los datos y callbacks que necesitan, y evita alcanzar singletons.
- Mueve reglas de negocio fuera de widgets temprano: pon decisiones en un controlador o view model, y la UI renderiza estado.
- Cuando una pieza UI deja de cambiar cada hora, extráela a un widget reutilizable con una API clara y tipada.
- Mantén los argumentos de ruta explícitos (un objeto argumento suele ser más limpio que muchos campos opcionales).
- Añade un breve changelog en la descripción del PR: qué cambió, por qué y qué probar.
Un ejemplo concreto que a los revisores les gusta
Supón la historia "Como comprador, puedo editar mi dirección de envío desde el checkout." Bloquea los args de la ruta primero: CheckoutArgs(cartId, shippingAddressId) permanece estable. Luego itera dentro de la pantalla. Cuando el layout se estabilice, divide en AddressForm, AddressSummary y SaveBar.
Si cambia el manejo de estado (por ejemplo, la validación se mueve del widget a un CheckoutController), la revisión sigue legible: los archivos UI cambian mayormente en renderizado, mientras el controller muestra el cambio de lógica en un solo lugar.
Errores comunes y trampas al iterar con un asistente AI
La forma más rápida de enlentecerse es pedir al asistente que cambie todo a la vez. Si un commit toca layout, estado y navegación, los revisores no saben qué rompió y revertir se complica.
Un hábito más seguro es una intención por iteración: dibuja el árbol de widgets, luego cablea el estado, luego conecta la navegación.
Errores que generan código desordenado
Un problema común es dejar que el código generado invente un patrón nuevo en cada pantalla. Si una página usa Provider, la siguiente usa setState y la tercera introduce un controlador personalizado, la app se vuelve inconsistente rápido. Elige un pequeño conjunto de patrones y aplícalos.
Otro error es poner trabajo asíncrono directamente dentro de build(). Puede parecer bien en una demo rápida, pero provoca llamadas repetidas en rebuilds, parpadeos y bugs difíciles de rastrear. Mueve la llamada a initState(), un view model o un controlador dedicado, y mantén build() enfocado en renderizar.
Los nombres son una trampa silenciosa. Código que compila pero lee Widget1, data2 o temp hace los refactors futuros dolorosos. Nombres claros también ayudan al asistente a producir mejores cambios de seguimiento porque la intención es obvia.
Guardrails que previenen lo peor:
- Cambia una de: layout, estado o navegación por iteración
- Reutiliza el mismo patrón de estado en la feature
- No llamadas de red o DB dentro de
build() - Renombra placeholders antes de añadir más funcionalidad
- Prefiere extraer widgets sobre añadir más anidación
La trampa de la anidación
Un arreglo visual típico es añadir otro Container, Padding, Align y SizedBox hasta que quede bien. Después de unas pasadas, el árbol se vuelve ilegible.
Si un botón está desalineado, primero prueba a quitar wrappers, usar un único widget de layout padre o extraer un widget pequeño con sus propias restricciones.
Ejemplo: una pantalla de checkout donde el precio total salta al cargar. Un asistente podría envolver la fila de precio en más widgets para "estabilizarla". Una solución más limpia es reservar espacio con un placeholder de carga simple manteniendo la estructura de la fila sin cambios.
Lista rápida antes de hacer commit en la siguiente iteración UI
Antes de commitear, haz una pasada de dos minutos que verifique el valor al usuario y te proteja de regresiones sorpresivas. El objetivo no es la perfección, es asegurarte de que esta iteración sea fácil de revisar, probar y deshacer.
Checklist previo al commit
Lee la historia de usuario una vez, luego verifica estos puntos contra la app en ejecución (o al menos contra un widget test simple):
- El árbol de widgets coincide con la historia: elementos clave de los criterios de aceptación existen y son visibles. Texto, botones y espacios vacíos se sienten intencionales.
- Todos los estados son alcanzables: Loading, Error y Empty no están solo esbozados en código. Puedes activar cada uno (incluso con una bandera debug temporal) y tiene un aspecto aceptable.
- La navegación y el comportamiento atrás tienen sentido: Atrás vuelve a la pantalla esperada, los diálogos se cierran correctamente y los deep links (si se usan) aterrizan en un lugar sensato.
- Los diffs se mantienen pequeños y con dueño: Los cambios se limitan a un pequeño conjunto de archivos con responsabilidad clara. No refactors incidentales.
- Rollback limpio: Si reviertes este commit, otras pantallas siguen compilando y ejecutándose. Elimina flags temporales o assets placeholder que puedan romper más tarde.
Una comprobación de realidad rápida: si añadiste una pantalla de Order details nueva, deberías poder (1) abrirla desde la lista, (2) ver un spinner de carga, (3) simular un error, (4) ver una orden vacía y (5) pulsar atrás para volver a la lista sin saltos raros.
Si tu flujo soporta snapshots y rollback, toma un snapshot antes de cambios UI mayores. Algunas plataformas como Koder.ai lo soportan y ayudan a iterar más rápido sin poner en riesgo la rama principal.
Un ejemplo realista: de la historia de usuario a pantallas en tres iteraciones
Historia: "Como comprador, puedo explorar ítems, abrir una página de detalle, guardar un ítem en favoritos y luego ver mis favoritos." La meta es pasar de palabras a pantallas en tres pasos pequeños y revisables.
Iteración 1: céntrate solo en la pantalla de lista de exploración. Crea un árbol de widgets suficiente para renderizar pero no ligado a datos reales: un Scaffold con un AppBar, un ListView de filas placeholder y UI clara para loading y empty. Mantén el estado simple: loading (muestra un CircularProgressIndicator), empty (mensaje corto y quizá un botón Reintentar) y ready (muestra la lista).
Iteración 2: añade la pantalla de detalle y la navegación. Sé explícito: onTap hace push de una ruta y pasa un objeto de parámetros pequeño (por ejemplo: item id, title). Empieza la página de detalle en modo solo lectura con título, descripción placeholder y un botón de Favorito. La idea es cumplir la historia: lista -> detalle -> atrás, sin flujos extra.
Iteración 3: introduce actualizaciones de estado de Favoritos y feedback UI. Añade una fuente única de verdad para favoritos (aunque sea en memoria) y conéctala a ambas pantallas. Tocar Favorito actualiza el icono inmediatamente y muestra una confirmación pequeña (como un SnackBar). Luego añade una pantalla Favorites que lea el mismo estado y maneje el estado vacío.
Un diff revisable típicamente parece así:
browse_list_screen.dart: árbol de widgets más UI loading/empty/readyitem_details_screen.dart: layout y acepta parámetros de navegaciónfavorites_store.dart: holder mínimo de estado y métodos de actualizaciónapp_routes.dart: rutas y helpers de navegación tipadosfavorites_screen.dart: lee estado y muestra empty/list UI
Si un archivo se convierte en "el lugar donde pasa todo", divídelo antes de seguir. Archivos pequeños con nombres claros aceleran la siguiente iteración y la hacen más segura.
Siguientes pasos: hacer que el bucle sea repetible entre features
Si el flujo solo funciona cuando estás "en la zona", se romperá cuando cambies de pantalla o un compañero toque la feature. Haz el bucle un hábito escribiéndolo y poniendo guardrails alrededor del tamaño del cambio.
Crea una plantilla de prompt reutilizable
Usa una plantilla de equipo para que cada iteración comience con las mismas entradas y produzca el mismo tipo de salida. Manténla corta pero específica:
- Historia de usuario + criterios de aceptación (qué significa "hecho")
- Restricciones UI (sistema de diseño, espaciado, componentes a reutilizar)
- Reglas de estado (dónde vive el estado, qué puede ser local vs compartido)
- Reglas de navegación (rutas, deep links, comportamiento atrás)
- Reglas de salida (archivos a tocar, tests a actualizar, qué explicar en el diff)
Esto reduce las probabilidades de que el asistente invente nuevos patrones a mitad de feature.
Define qué es "pequeño" para que los diffs sean predecibles
Elige una definición de pequeño que sea fácil de aplicar en la revisión de código. Por ejemplo, limita cada iteración a un número reducido de archivos y separa refactors UI de cambios de comportamiento.
Un conjunto simple de reglas:
- No más de 3 a 5 archivos cambiados por iteración
- Una nueva widget o un paso de navegación por iteración
- No introducir un nuevo enfoque de gestión de estado a mitad del bucle
- Cada cambio debe compilar y ejecutarse antes de la siguiente iteración
Añade puntos de control para poder deshacer un mal paso rápidamente. Como mínimo, etiqueta commits o guarda checkpoints locales antes de refactors mayores. Si tu flujo soporta snapshots y rollback, úsalos agresivamente.
Si quieres un flujo basado en chat que genere y refine apps Flutter de extremo a extremo, Koder.ai incluye un modo de planificación que te ayuda a revisar un plan y los cambios de archivo esperados antes de aplicarlos.
Preguntas frecuentes
¿Cómo mantengo una iteración de UI en Flutter lo bastante pequeña para revisar?
Usa una especificación UI pequeña y comprobable primero. Escribe 3–6 líneas que cubran:
- Qué aparece (widgets/componentes clave)
- Qué hace el tap (una interacción principal)
- Cómo se ven loading/error/empty
- Cómo verificarlo en 30 segundos
Luego construye solo ese slice (a menudo una pantalla + 1–2 widgets).
¿Cuál es la mejor forma de convertir una historia de usuario en una especificación UI construible?
Convierte la historia en cuatro cubos:
- Pantallas: qué cambia y qué permanece igual
- Componentes: widgets nuevos y dónde viven
- Estados: loading, empty, error, success (qué muestra cada uno)
- Eventos: taps, back, retry, refresh, ediciones de formulario
Si no puedes describir la comprobación de aceptación rápidamente, la historia todavía está demasiado difusa para un diff limpio.
¿Qué debo pedir primero a un asistente AI: código o estructura?
Empieza generando solo un esquema del árbol de widgets (nombres + jerarquía + qué muestra cada parte). Nada de código.
Después pide un desglose de responsabilidades de componentes (qué posee cada widget).
Solo entonces, genera el scaffold estateless con entradas explícitas (valores + callbacks), y haz el estilo en una pasada separada.
¿Por qué el enfoque de “un gran prompt” suele crear diffs desordenados?
Trátalo como una regla dura: una intención por iteración.
- Iteración A: árbol/layout
- Iteración B: enlace de estado
- Iteración C: enlace de navegación
Si un solo commit cambia layout, estado y rutas juntos, los revisores no sabrán qué causó un bug y revertir será complejo.
¿Cómo añado estado sin inflar el código de los widgets?
Mantén los widgets “tontos”: deben renderizar estado, no decidir reglas de negocio.
Un por defecto práctico:
- Crea un controlador/view-model que gestione eventos y trabajo asíncrono
- Expón un único objeto de estado (loading/empty/error/success)
- La UI lee el estado y llama callbacks (retry, submit, toggle)
Evita llamadas asíncronas dentro de build()—provocan llamadas repetidas en rebuilds.
¿Qué estados UI debería planear para la mayoría de pantallas?
Define estados y transiciones en lenguaje claro antes de codificar.
Patrón ejemplo:
- Loading: muestra spinner/skeleton
- Empty: muestra mensaje + acción (como Retry)
- Error: muestra error inline + Retry
- Success: renderiza contenido
Luego lista eventos que mueven entre ellos (refresh, retry, submit, edit). El código es más fácil de comparar con las reglas escritas.
¿Cómo evito que los flujos de navegación queden dispersos e inconsistentes?
Escribe un pequeño “mapa de flujo” para la historia:
- Entrada: de dónde viene el usuario
- Siguiente: paso principal hacia adelante
- Cancelar: dónde aterrizan si abandonan
- Atrás: qué se preserva o descarta
- Fallback: qué pasa si faltan datos necesarios
También fija qué viaja entre pantallas (IDs, filtros, datos en borrador) para no esconder contexto en singletons globales.
¿Qué estructura de carpetas ayuda a mantener los cambios UI contenidos?
Por defecto, usa carpetas organizadas por feature para que los cambios se mantengan contenidos. Por ejemplo:
lib/features/<feature>/screens/lib/features/<feature>/widgets/lib/features/<feature>/state/lib/features/<feature>/routes.dart
Mantén cada iteración enfocada en una carpeta de feature y evita refactors accidentales en otras partes.
¿Cómo hago mi UI Flutter más modular sin sobre-ingeniería?
Una regla simple: estabiliza interfaces, no internos.
- Mantén las props públicas de widgets pequeñas y tipadas
- Prefiere pasar valores + callbacks sobre leer estado global
- Argumentos de rutas explícitos (frecuentemente un único objeto args)
- Extrae un widget cuando deja de cambiar cada hora
A los revisores les importa que entradas/salidas se mantengan estables aunque la disposición cambie.
¿Cuál es una rápida lista de verificación previa al commit para una iteración UI segura?
Haz un chequeo rápido de dos minutos:
- ¿Puedes activar loading, empty, error, success y lucen aceptables?
- ¿El atrás vuelve donde esperas (sin saltos extraños)?
- ¿Cambiaron solo un pequeño conjunto de archivos con responsabilidad clara?
- ¿Hay flags temporales/placeholder que puedan romper después?
Si tu flujo lo permite (por ejemplo snapshots/rollback), toma un snapshot antes de un refactor mayor para poder revertir con seguridad.