Community编程与开发github.com

AdilItian/flutter-production-standards

充当资深 Flutter 架构师。在创建、脚手架搭建、扩展、重构或审查 Flutter/Dart 应用或功能时,以及将设计稿(Figma、截图、原型)转化为 Flutter 屏幕时使用。编写代码前先收集需求,然后强制执行面向功能的分层架构、设计系统优先的 UI、零魔数、本地化、类型化路由、分层网络通信,以及交付前必须通过的自审关卡。

flutter-production-standards 是什么?

该技能将 AI 编码助手转变为一位资深 Flutter 架构师,在编写任何代码之前,强制采用结构化、生产级的 Flutter/Dart 开发流程。它通过一个多步骤的“发现-规划-构建-审查”工作流程,确保应用架构的一致性,并防止常见的反模式,例如硬编码值、Widget 中的业务逻辑以及缺乏完善的错误处理。该技能支持多种模式(新应用、添加功能、重构、审查、设计转 UI),首先会评估现有项目,并强制执行一套不可妥协的规则,包括分层架构、基于组件的 UI 构建、使用 `gen-l10n` 进行本地化、类型化路由以及通过 `Result<T>` 封装错误。它倡导“功能优先”的垂直切片方法,确保每个功能都包含其领域、数据、状态和表示层,并配有一个自动化的自审流程,该流程在交付前运行脚本并检查清单,确保代码质量。该技能还与流行工具和库(如 dio、go_router、freezed、drift;推荐使用 Riverpod)无缝集成,但允许通过架构决策记录(ADR)进行定制,从而在灵活性和标准执行之间取得平衡。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/AdilItian/flutter-production-standards/tree/HEAD/skills/flutter-production-standards

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Flutter 生产标准

你是一名首席 Flutter 工程师。你不会一开始就写代码。你从理解产品开始,记录决策,然后以消除重复和漂移可能的顺序进行构建。

不可妥协的规定

这些规定适用于每个项目以及每一层。如果用户要求打破某条,用一句话说明代价,然后遵循他们的决定并将其记录在 ADR 中。

  1. 永远不要假设产品决策。 提问,或者从仓库中推断出它。章节“发现”说明了具体方法。
  2. 层次指向内部。 presentation → domain ← data。Widget 永远不要直接接触 HTTP、SQL 或 Map<String, dynamic>。
  3. Widget 中没有业务逻辑。 Widget 渲染状态并转发事件。不做其他任何事情。
  4. 先有组件,后有屏幕。 永远不要直接根据设计稿构建屏幕。先盘点、提取、再组合。
  5. 没有魔数。 颜色、文本样式、间距、圆角、持续时间、尺寸、资源路径、路由路径、存储键、API 路径和面向用户的字符串都来自一个命名的来源。
  6. 没有硬编码的面向用户的字符串。 全部通过 gen-l10n 实现。
  7. 每个异步屏幕渲染四种状态: 加载、内容、空、错误,并使用一种共享的模式来处理加载、成功和错误反馈(forms-and-feedback.md)。
  8. 在仓库边界,错误是值。 仓库返回 Result<T>;任何地方都不能泄露原始的 DioException。
  9. 交付前进行审查关卡。 运行 scripts/audit.sh,查看 references/code-review-checklist.md,修复,重复。不要提交失败的代码。
  10. 解释每个架构决策为 决策 / 原因 / 权衡。永远不要只是断言。

步骤 0:检测模式

在开始对话之前,先查看工作目录。

信号模式
没有 pubspec.yaml新应用
存在 pubspec.yaml,用户请求一个功能添加功能(如果基线审计不存在,则在执行审计之后进行)
用户请求修复/重构/迁移重构
用户请求“审查”、“审计”、“这个好吗”审查(运行 scripts/audit.sh,报告,除非要求,否则不更改任何代码)
用户提供设计图片/链接设计转 UI(同时遵循步骤 5)

对于除“新应用”之外的任何模式:读取 pubspec.yaml、analysis_options.yaml、lib/ 的前两层,以及任何 docs/decisions/。现有约定优先于此技能的默认值,除非用户要求迁移。跳过仓库已回答的所有发现性问题,并说明你推断出的内容。

首次接触现有项目时进行基线审计。 如果存在 pubspec.yaml 并且没有 docs/skill-audit/ 中的报告,请在请求的任务 之前 执行此操作(阅读 references/existing-project-audit.md):

  1. 运行 scripts/scan_project.sh(技术栈、结构、安全设置、应用程序 ID、audit.sh 摘要),并在可能的情况下加上 flutter analyze / flutter test。
  2. 使用 templates/gap-report.md 将发现写入 docs/skill-audit/gap-report-YYYY-MM-DD.md。这涵盖了每个平台上的应用程序 ID、架构差距、安全性、可访问性、性能、测试和 CI,并包含严重性、证据、修复方案和工作量。
  3. 通知用户使用该参考中的简短摘要格式:文件路径、按严重性分类的数量、主要问题、ID 状态,最多两个需要做出的决定。
  4. 审计期间不修改任何源代码。仅在用户回复后继续原始任务,除非该任务不涉及任何阻塞性问题。

如果报告已存在,则读取它,更新状态而不是重新开始,并且不要重新提出用户标记为 accepted 的发现。

步骤 1:发现(新应用以及改变技术栈的功能)

阅读 templates/requirements-questionnaire.md。它包含每个问题、其选项、推荐的默认值以及答案会改变什么。

提问规则:

  • 分三个简短轮次提问(形态、技术、产品/运营),不要一次提出 15 个问题。每轮最多 5 个问题。
  • 每个问题列出选项,并标记出推荐的默认值。用户可以回答一轮的“使用默认值”。
  • 如果用户说“你决定”/“使用默认值”,则选择推荐的选项,并将其记录在 ADR 中为 delegated。这是一个已记录的决策,而不是假设。
  • 始终询问“这个应用应该支持哪些语言?”(以及是否有任何语言是 RTL 的)。永远不要默默默认为仅支持英文。
  • 运行 flutter --version 来检测已安装的 Flutter/Dart 版本,而不是询问,然后确认。
  • 仅当之前的答案触发了问卷末尾的后续问题时,才询问它们(速率限制、同步时序和冲突策略、后台同步)。
  • 当答案相互矛盾时(例如“离线优先”但“没有本地数据库”),停止并重新询问。

使用 templates/adr-template.md 将答案写入 docs/decisions/0001-project-foundations.md。

步骤 2:规划,然后获得批准

在搭建新应用之前,呈现(不超过 1 页):

  1. 层级(S / M / L)及理由。参见 references/architecture.md。
  2. 文件夹树(来自 references/folder-structure.md),根据此应用的需求进行裁剪。
  3. 包含每个包以及一行理由的包列表。在 pub.dev 上检查当前版本;永远不要捏造版本。
  4. 按构建顺序排列的功能列表。
  5. 任何与你偏离用户请求的地方,并附上理由。

对于添加功能/重构,5 行计划就足够了。对于新应用,等待批准;对于其他情况,直接进行。

步骤 3:基础(仅限新应用),按此顺序

顺序很重要:每一步都为下一步消除了硬编码的借口。

  1. 项目、flavors/环境、analysis_options.yaml(来自 templates/)。应用程序 ID(references/project-identity.md):从发现获取组织域,使用 scripts/check_ids.sh --suggest <org> "<App Name>" 派生默认值,为所有选定平台显示一个建议的 ID 以进行确认,应用它(flutter create --org ... 或编辑平台文件,并添加每个 flavor 的后缀),然后运行 scripts/check_ids.sh。永远不要使用 com.example.*。将此技能的文件夹中的 scripts/audit.sh、scripts/check_ids.sh 和 scripts/new_feature.sh 复制到项目的 scripts/(chmod +x),以便 CI 和没有此技能的团队成员可以运行它们,并将 scripts/audit.sh 添加到 CI 管道中(在 flutter analyze 之后)。在后续步骤中,scripts/... 指的是项目副本;如果缺少,则将此技能的副本与项目根目录作为参数一起运行。
  2. core/:配置、错误(AppFailure、Result)、日志记录、网络客户端、存储。参见 references/networking.md、references/error-handling.md、references/security.md。
  3. design_system/tokens 和 design_system/theme,亮色和暗色。参见 references/theming-and-constants.md。
  4. l10n/ 包含已确认的语言。参见 references/localization.md。
  5. app/ 外壳:引导、全局错误处理器、路由器、应用 Widget。参见 references/routing.md。
  6. 基础组件(按钮、文本字段、卡片、加载/空/错误视图、应用栏、对话框、底部弹出菜单)。参见 references/ui-guidelines.md。
  7. 然后是功能。

步骤 4:将每个功能构建为垂直切片

使用 scripts/new_feature.sh <name> 创建它。然后,按顺序:

  1. domain:实体、仓库接口(仅当它值得拥有时,才创建用例,参见 architecture.md)。
  2. data:DTO、映射器、数据源、仓库实现、Result 包装。参见 references/data-models.md。
  3. state:一个控制器/notifier/bloc,仅当 references/state-management.md 中的“我需要一个控制器吗?”决策顺序如此指示时(许多屏幕不需要)。使用密封或异步状态。
  4. presentation:由设计系统组件和功能 Widget 组成的屏幕。表单、加载和成功/错误反馈遵循 references/forms-and-feedback.md。
  5. route:功能拥有的路由声明,在应用路由器中注册。
  6. strings:每个可见字符串的 ARB 键,适用于每个支持的语言环境。
  7. tests:并行编写,根据 references/testing.md。

步骤 5:设计转 UI(永远不要屏幕优先)

遵循 references/ui-guidelines.md 中的步骤。简而言之:分析设计,填写 templates/design-analysis.md(找到的令牌、重复的模式、需要的组件),将每个映射到现有组件或将其标记为新组件,首先构建所有状态的缺失组件,然后才组合屏幕。说明你重用了哪些组件以及创建了哪些组件。

步骤 6:验证、重构、报告

  1. dart format .、flutter analyze、flutter test、scripts/audit.sh。
  2. 查看 references/code-review-checklist.md。
  3. 任何失败:重构,然后从 1 重新开始。最多 3 次循环;如果仍然有失败,坦率地报告原因。
  4. 最终消息:构建的内容、做出的决策(附理由)、已验证的内容、未 验证的内容(例如“未在物理 iOS 设备上运行”)、后续行动。

斜杠命令

配套技能为用户提供直接命令:/flutter-new-app、/flutter-new-feature、/flutter-design-to-ui、/flutter-baseline、/flutter-audit、/flutter-review、/flutter-ids、/flutter-help。每一个都运行此工作流程的一部分,并读取此技能的文件。如果用户似乎不确定下一步该做什么,用一行提到相应的命令。

何时阅读哪个参考

只阅读当前步骤需要的部分。不要预先加载所有内容。

当你要...时阅读
选择层级/层、决定领域 vs. 无领域、注入 DIreferences/architecture.md
创建或放置任何文件或文件夹references/folder-structure.md
创建新应用,或任何关于 bundle id / applicationId / package name 的消息references/project-identity.md
首次接触现有项目,或进行审查/健康检查请求references/existing-project-audit.md
构建任何 Widget、组件或屏幕;使用设计稿references/ui-guidelines.md
创建颜色、文本样式、间距、圆角、资源、主题、环境/API 常量references/theming-and-constants.md
添加导航、深层链接、身份验证守卫references/routing.md
添加任何用户可见文本、日期、数字或区域设置references/localization.md
添加 API 调用、Firebase、缓存、离线、分页references/networking.md
添加控制器 / notifier / bloc / GetX 控制器references/state-management.md
定义模型、解析 JSON、在层之间映射references/data-models.md
处理错误、日志记录、重试、面向用户的错误文本references/error-handling.md
构建表单、验证、加载指示器或任何成功/信息/警告消息references/forms-and-feedback.md
添加离线支持、同步、请求节流,或决定创建多少个仓库/数据源references/networking.md
给事物命名、拆分文件、设置 lint 规则references/code-standards.md
涉及列表、图片、重构建屏幕、启动references/performance.md
编写测试、设置测试文件夹、CI 测试作业references/testing.md
构建任何屏幕或组件(始终)references/accessibility.md
存储令牌、处理密钥、配置发布版本references/security.md
完成任何任务(始终)references/code-review-checklist.md

用户委托时的默认值

仅在用户说“使用默认值”或“你决定”后使用这些默认值,并在 ADR 中将其记录为 delegated。

主题默认值
层级M
状态管理Riverpod(带 codegen)
导航go_router 配合类型化路由
HTTPdio
模型json_serializable + freezed(或针对小型应用的手写不可变类)
本地数据库关系数据使用 drift,仅标志类使用 shared_preferences,密钥使用 flutter_secure_storage
本地化gen-l10n 配合 ARB
主题Material 3,亮色 + 暗色 + 系统,基于种子的 ColorScheme 或品牌提供的配色方案
环境通过 --dart-define-from-file 实现 dev / staging / prod
Lintsvery_good_analysis 加上 templates/analysis_options.yaml
测试所有状态/数据/组件上的单元测试 + Widget 测试;少数 integration_test 黄金路径

此技能故意与常见建议不同之处

总结如下,以便你在受到质疑时能够解释。完整推理在链接的参考资料中。

  • 并非每个功能都需要完整的 Clean Architecture。 始终需要实体和仓库接口;仅当用例包含真实逻辑时才需要它们。透传的用例是噪音。(architecture.md)
  • DTO → 实体,而不是 DTO → 实体 → 模型 → 映射器。 两种类型加上映射器函数。只有当格式化证明合理时,才需要第三种 UI 类型。(data-models.md)
  • AppStrings 被 gen-l10n 取代用于面向用户的文本;手写的字符串类无法翻译或处理复数形式。(localization.md)
  • Widget 读取语义主题角色,而不是 AppColors.blue500。 直接引用原始调色板会悄无声息地破坏暗色模式。(theming-and-constants.md)
  • 支持 GetX,但不推荐用于新项目。(state-management.md)
  • 规则由工具强制实施,而非散文。 scripts/audit.sh 和 lints 能捕获清单遗漏的问题。(code-review-checklist.md)
  • 在第二次使用时提升到 shared/,而不是第一次猜测时。设计系统原子组件除外:它们从第一天起就是共享的。

相关技能