@bovinphang/frontend-craft 2.5.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/.claude-plugin/marketplace.json +7 -3
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +77 -1
  4. package/CHANGELOG.zh-CN.md +77 -1
  5. package/CONTRIBUTING.md +15 -10
  6. package/CONTRIBUTING.zh-CN.md +15 -10
  7. package/README.md +69 -43
  8. package/README.openclaw.md +11 -9
  9. package/README.openclaw.zh-CN.md +11 -9
  10. package/README.zh-CN.md +69 -43
  11. package/agents/fec-typescript-reviewer.md +1 -1
  12. package/commands/fec-doc-sync.md +7 -6
  13. package/dist/bin/frontend-craft.js +30 -27
  14. package/docs/example-prompts.md +82 -69
  15. package/docs/ja-JP/README.md +110 -84
  16. package/docs/ko-KR/README.md +100 -74
  17. package/docs/project-structure.md +8 -4
  18. package/docs/runtimes/antigravity.md +1 -1
  19. package/docs/runtimes/augment.md +1 -1
  20. package/docs/runtimes/claude.md +16 -10
  21. package/docs/runtimes/claude.zh-CN.md +16 -10
  22. package/docs/runtimes/cline.md +1 -1
  23. package/docs/runtimes/codebuddy.md +1 -1
  24. package/docs/runtimes/codex.md +1 -1
  25. package/docs/runtimes/copilot.md +1 -1
  26. package/docs/runtimes/cursor.md +1 -1
  27. package/docs/runtimes/gemini.md +1 -1
  28. package/docs/runtimes/kilo.md +1 -1
  29. package/docs/runtimes/openclaw.md +1 -1
  30. package/docs/runtimes/opencode.md +1 -1
  31. package/docs/runtimes/qoder.md +1 -1
  32. package/docs/runtimes/trae.md +1 -1
  33. package/docs/runtimes/windsurf.md +1 -1
  34. package/docs/zh-CN/example-prompts.md +82 -69
  35. package/docs/zh-CN/project-structure.md +8 -4
  36. package/docs/zh-TW/README.md +88 -62
  37. package/openclaw.plugin.json +1 -1
  38. package/package.json +3 -3
  39. package/skills/eval_queries.json +179 -56
  40. package/skills/fec-accessibility-check/SKILL.md +1 -1
  41. package/skills/fec-alchemy/SKILL.md +74 -0
  42. package/skills/fec-alchemy/assets/absorption-plan-template.md +47 -0
  43. package/skills/fec-alchemy/assets/intake-template.md +55 -0
  44. package/skills/fec-alchemy/assets/review-checklist.md +31 -0
  45. package/skills/fec-alchemy/references/methodology.md +94 -0
  46. package/skills/fec-alchemy/references/originality-and-licensing.md +57 -0
  47. package/skills/fec-backend-requirements-handoff/SKILL.md +45 -0
  48. package/skills/fec-browser-storage/SKILL.md +1 -1
  49. package/skills/fec-canvas-threejs/SKILL.md +1 -1
  50. package/skills/fec-code-review/SKILL.md +11 -3
  51. package/skills/fec-data-fetching/SKILL.md +15 -15
  52. package/skills/fec-data-fetching/references/query-patterns.md +27 -1
  53. package/skills/fec-debug-framework/SKILL.md +14 -19
  54. package/skills/fec-debug-framework/references/report-template.md +58 -0
  55. package/skills/fec-doc-sync/SKILL.md +19 -17
  56. package/skills/fec-drawio-studio/SKILL.md +69 -0
  57. package/skills/fec-drawio-studio/data/THIRD_PARTY_NOTICES.md +10 -0
  58. package/skills/fec-drawio-studio/data/brand-icons.json +878 -0
  59. package/skills/fec-drawio-studio/data/shape-index.json.gz +0 -0
  60. package/skills/fec-drawio-studio/references/data-residency.md +27 -0
  61. package/skills/fec-drawio-studio/references/diagram-patterns.md +41 -0
  62. package/skills/fec-drawio-studio/references/layout-and-export.md +57 -0
  63. package/skills/fec-drawio-studio/references/troubleshooting.md +29 -0
  64. package/skills/fec-drawio-studio/references/xml-and-mermaid.md +54 -0
  65. package/skills/fec-drawio-studio/scripts/brand-symbols.mjs +99 -0
  66. package/skills/fec-drawio-studio/scripts/diagram-lint.mjs +143 -0
  67. package/skills/fec-drawio-studio/scripts/diagram-url.mjs +102 -0
  68. package/skills/fec-drawio-studio/scripts/layout-graph.mjs +107 -0
  69. package/skills/fec-drawio-studio/scripts/png-embed-fix.mjs +26 -0
  70. package/skills/fec-drawio-studio/scripts/scan-go-packages.mjs +36 -0
  71. package/skills/fec-drawio-studio/scripts/scan-js-modules.mjs +52 -0
  72. package/skills/fec-drawio-studio/scripts/scan-python-classes.mjs +30 -0
  73. package/skills/fec-drawio-studio/scripts/scan-python-modules.mjs +55 -0
  74. package/skills/fec-drawio-studio/scripts/scan-rust-modules.mjs +35 -0
  75. package/skills/fec-drawio-studio/scripts/scan-ts-modules.mjs +7 -0
  76. package/skills/fec-drawio-studio/scripts/shape-query.mjs +81 -0
  77. package/skills/fec-drawio-studio/scripts/studio-core.mjs +139 -0
  78. package/skills/fec-drawio-studio/styles/built-in/corporate.json +49 -0
  79. package/skills/fec-drawio-studio/styles/built-in/default.json +49 -0
  80. package/skills/fec-drawio-studio/styles/built-in/handdrawn.json +49 -0
  81. package/skills/fec-drawio-studio/styles/schema.json +112 -0
  82. package/skills/fec-e2e-testing/SKILL.md +5 -3
  83. package/skills/fec-e2e-testing/references/e2e-ci-reporting.md +62 -0
  84. package/skills/fec-e2e-testing/references/e2e-special-scenarios.md +52 -0
  85. package/skills/fec-e2e-testing/references/e2e-visual-regression.md +60 -0
  86. package/skills/fec-form-handling/SKILL.md +11 -11
  87. package/skills/fec-form-handling/references/advanced-form-patterns.md +34 -5
  88. package/skills/fec-image-generation/SKILL.md +56 -0
  89. package/skills/fec-image-generation/references/artifact-routing.md +80 -0
  90. package/skills/fec-image-generation/references/diagram-workflows.md +43 -0
  91. package/skills/fec-image-generation/references/png-qa-autofix.md +30 -0
  92. package/skills/fec-image-generation/scripts/png-qa.mjs +431 -0
  93. package/skills/fec-implement-from-design/SKILL.md +9 -2
  94. package/skills/fec-legacy-to-modern-migration/SKILL.md +29 -163
  95. package/skills/fec-legacy-to-modern-migration/references/migration-execution-checklist.md +110 -0
  96. package/skills/fec-legacy-to-modern-migration/references/migration-strategy-and-mapping.md +48 -0
  97. package/skills/fec-legacy-web-standard/SKILL.md +1 -1
  98. package/skills/fec-list-virtualization/SKILL.md +3 -3
  99. package/skills/fec-list-virtualization/references/virtualization-patterns.md +32 -4
  100. package/skills/fec-motion-interaction/SKILL.md +7 -0
  101. package/skills/fec-nextjs-project-standard/SKILL.md +7 -1
  102. package/skills/fec-performance-optimization/SKILL.md +9 -1
  103. package/skills/fec-performance-optimization/references/framework-performance-patterns.md +38 -0
  104. package/skills/fec-performance-optimization/references/report-template.md +59 -0
  105. package/skills/fec-pwa-implementation/SKILL.md +3 -4
  106. package/skills/fec-react-project-standard/SKILL.md +12 -4
  107. package/skills/fec-react-project-standard/references/react-performance-patterns.md +35 -0
  108. package/skills/fec-react-project-standard/references/react-project-structure.md +197 -0
  109. package/skills/fec-react-project-standard/references/react-quality-patterns.md +131 -0
  110. package/skills/fec-react-project-standard/references/react-runtime-patterns.md +293 -0
  111. package/skills/fec-refactor-clean/SKILL.md +4 -1
  112. package/skills/fec-refactor-clean/references/report-template.md +42 -0
  113. package/skills/fec-responsive-layout/references/responsive-layout-patterns.md +11 -0
  114. package/skills/fec-security-review/SKILL.md +3 -3
  115. package/skills/fec-source-driven-development/SKILL.md +26 -0
  116. package/skills/fec-state-management/SKILL.md +1 -1
  117. package/skills/fec-storybook-component-doc/SKILL.md +2 -2
  118. package/skills/fec-tailwind-design-system/references/tailwind-system-patterns.md +5 -1
  119. package/skills/fec-typescript-project-standard/SKILL.md +54 -0
  120. package/skills/{fec-typescript-type-safety → fec-typescript-project-standard}/references/type-safety-patterns.md +1 -1
  121. package/skills/{fec-typescript-type-safety/SKILL.md → fec-typescript-project-standard/references/type-safety.md} +1 -10
  122. package/skills/fec-ui-design/SKILL.md +26 -8
  123. package/skills/fec-ui-design/data/style-archetypes.json +40 -0
  124. package/skills/fec-ui-design/data/ux-quality-rules.json +35 -0
  125. package/skills/fec-ui-design/references/design-intelligence.md +66 -6
  126. package/skills/fec-ui-design/references/pre-delivery-checklist.md +6 -0
  127. package/skills/fec-ui-design/scripts/design-system.mjs +119 -1
  128. package/skills/fec-validation-fix/SKILL.md +5 -2
  129. package/skills/fec-validation-fix/references/report-template.md +43 -0
  130. package/skills/fec-vue3-project-standard/SKILL.md +12 -3
  131. package/skills/fec-vue3-project-standard/references/vue3-composables-routing.md +163 -0
  132. package/skills/fec-vue3-project-standard/references/vue3-performance-patterns.md +13 -0
  133. package/skills/fec-vue3-project-standard/references/vue3-project-structure.md +177 -0
  134. package/skills/fec-vue3-project-standard/references/vue3-state-api-quality.md +216 -0
  135. package/skills/fec-web-video-presentation/SKILL.md +61 -0
  136. package/skills/fec-web-video-presentation/data/starter-themes.json +59 -0
  137. package/skills/fec-web-video-presentation/references/chapter-craft.md +37 -0
  138. package/skills/fec-web-video-presentation/references/content-plan.md +38 -0
  139. package/skills/fec-web-video-presentation/references/recording-and-audio.md +33 -0
  140. package/skills/fec-web-video-presentation/references/theme-system.md +36 -0
  141. package/skills/fec-web-video-presentation/scripts/create-video-presentation.mjs +430 -0
  142. package/skills/fec-web-workers/SKILL.md +3 -4
  143. package/skills/metadata.json +381 -168
  144. package/skills/relations.json +136 -25
  145. package/templates/shared/rules/fec-ci-cd.md +20 -108
  146. package/templates/shared/rules/fec-design-system.md +47 -223
  147. package/templates/shared/rules/fec-error-handling.md +35 -179
  148. package/templates/shared/rules/fec-i18n.md +43 -91
  149. package/templates/shared/rules/fec-refactoring.md +4 -0
  150. package/templates/shared/rules/fec-rendering-patterns.md +28 -171
  151. package/templates/shared/rules/fec-responsive-design.md +34 -211
  152. package/templates/shared/rules/fec-state-management.md +41 -144
  153. package/templates/shared/rules/fec-typescript.md +47 -290
  154. package/skills/fec-e2e-testing/references/e2e-advanced.md +0 -176
  155. package/skills/fec-react-project-standard/references/react-project-details.md +0 -642
  156. package/skills/fec-vue3-project-standard/references/vue3-project-details.md +0 -547
@@ -70,5 +70,45 @@
70
70
  "tokens": { "radius": "8-16px", "shadow": "soft", "density": "low-medium" },
71
71
  "bestFor": ["wellness", "beauty", "lifestyle", "care services"],
72
72
  "avoid": ["pastel contrast failures", "vague atmospheric imagery over real services"]
73
+ },
74
+ {
75
+ "id": "editorial-premium",
76
+ "keywords": ["premium", "luxury", "fashion", "magazine", "launch", "campaign"],
77
+ "description": "Image-led composition, restrained copy, high-contrast typography, and deliberate negative space.",
78
+ "tokens": { "radius": "0-8px", "shadow": "minimal", "density": "low-medium" },
79
+ "bestFor": ["brand launches", "premium ecommerce", "editorial landing pages", "portfolio features"],
80
+ "avoid": ["beige luxury defaults without brand evidence", "serif decoration that weakens readability", "hero copy that pushes the CTA below the first viewport"]
81
+ },
82
+ {
83
+ "id": "industrial-brutalist",
84
+ "keywords": ["industrial", "brutalist", "mechanical", "terminal", "tactical", "blueprint"],
85
+ "description": "Visible grids, hard edges, strong type scale contrast, and utilitarian metadata used with clear purpose.",
86
+ "tokens": { "radius": "0-2px", "shadow": "none", "density": "medium-high" },
87
+ "bestFor": ["technical portfolios", "developer tools", "editorial experiments", "telemetry interfaces"],
88
+ "avoid": ["regulated consumer flows", "tiny all-caps body copy", "decorative terminal chrome without real information"]
89
+ },
90
+ {
91
+ "id": "minimal-utilitarian",
92
+ "keywords": ["utilitarian", "document", "linear", "notion", "workspace", "minimalist"],
93
+ "description": "Quiet document-like surfaces, precise structure, low ornament, and typography doing most of the hierarchy work.",
94
+ "tokens": { "radius": "4-8px", "shadow": "none-low", "density": "medium" },
95
+ "bestFor": ["SaaS settings", "docs", "team workspaces", "productivity tools"],
96
+ "avoid": ["empty white expanses with no task priority", "low-contrast gray on gray", "identical flat cards for every section"]
97
+ },
98
+ {
99
+ "id": "image-led-landing",
100
+ "keywords": ["landing", "website", "hero", "visual", "image-led", "marketing"],
101
+ "description": "A clear conversion path carried by real or generated media, varied section structure, and inspectable visual assets.",
102
+ "tokens": { "radius": "contextual", "shadow": "media-dependent", "density": "low-medium" },
103
+ "bestFor": ["marketing sites", "product pages", "event pages", "agency sites"],
104
+ "avoid": ["text plus gradient-only hero", "fake screenshots", "repeating left-text/right-image sections", "CTA labels that wrap on desktop"]
105
+ },
106
+ {
107
+ "id": "brand-system-board",
108
+ "keywords": ["brand", "brandkit", "identity", "logo", "guidelines", "visual system"],
109
+ "description": "Presentation-grid identity boards that show logo logic, palette, typography, applications, and visual world coherently.",
110
+ "tokens": { "radius": "system-defined", "shadow": "presentation-dependent", "density": "medium" },
111
+ "bestFor": ["brand exploration", "identity systems", "design direction handoff", "visual language proposals"],
112
+ "avoid": ["random moodboards", "generic logos", "panels that do not explain the brand idea"]
73
113
  }
74
114
  ]
@@ -52,5 +52,40 @@
52
52
  "priority": "medium",
53
53
  "checks": ["Chart type matches data question", "Units and legends are visible", "Data has text/table fallback", "Color is supplemented by shape or labels"],
54
54
  "avoid": ["Pie charts for many categories", "Color-only series distinction"]
55
+ },
56
+ {
57
+ "category": "first-viewport",
58
+ "label": "First viewport",
59
+ "priority": "high",
60
+ "checks": ["Hero or workspace fits common laptop heights", "Primary CTA or task entry is visible without scrolling", "Desktop navigation stays on one line", "The next section leaves a readable cue when the page is promotional"],
61
+ "avoid": ["Oversized top padding", "Hero copy pushing actions below the fold", "Two-line desktop nav"]
62
+ },
63
+ {
64
+ "category": "cta-quality",
65
+ "label": "CTA quality",
66
+ "priority": "high",
67
+ "checks": ["CTA text contrast meets WCAG AA", "Primary CTA label stays on one line at desktop", "Each CTA intent uses one consistent label", "Ghost buttons remain visible over media backgrounds"],
68
+ "avoid": ["White text on light buttons", "Multiple contact labels for the same action", "Transparent buttons over busy imagery"]
69
+ },
70
+ {
71
+ "category": "section-variety",
72
+ "label": "Section variety",
73
+ "priority": "medium",
74
+ "checks": ["Adjacent sections use distinct layout jobs", "Bento cell count matches real content", "Feature grids have clear visual priority", "Small uppercase eyebrow labels are used sparingly"],
75
+ "avoid": ["Three equal cards as the default rhythm", "Three or more zigzag sections in a row", "Empty bento cells for decoration"]
76
+ },
77
+ {
78
+ "category": "media-authenticity",
79
+ "label": "Media authenticity",
80
+ "priority": "high",
81
+ "checks": ["Visual pages use real or generated assets with a clear role", "Product pages show inspectable product or state", "Screenshots represent real UI or are labeled as concepts", "Images reserve aspect ratio and have meaningful alt text when informative"],
82
+ "avoid": ["Text-only promotional pages", "Fake dashboard rectangles", "Blurred stock atmosphere as the main subject"]
83
+ },
84
+ {
85
+ "category": "state-completeness",
86
+ "label": "State completeness",
87
+ "priority": "critical",
88
+ "checks": ["Loading shape matches final layout", "Empty states include a useful next action", "Errors are recoverable and close to the source", "Selected, invalid, disabled, hover, focus, and reduced-motion states are covered"],
89
+ "avoid": ["Generic spinners everywhere", "Empty states that only say no data", "Disabled controls communicated only by opacity"]
55
90
  }
56
91
  ]
@@ -5,12 +5,71 @@
5
5
  ## 决策流程
6
6
 
7
7
  1. 提取关键词:产品类型、用户、场景、主要任务、内容密度、品牌语气、技术栈。
8
- 2. 匹配产品规则:从 `data/product-rules.json` 选择最接近的类别,记录推荐结构、风险和反模式。
9
- 3. 选择风格原型:从 `data/style-archetypes.json` 选择 1 个主风格和最多 1 个辅助风格,避免风格拼贴。
10
- 4. 建立 token 方向:定义主色、强调色、背景、前景、边框、危险色和 focus ring 的语义角色。
11
- 5. 选择字体情绪:不要只选“好看的字体”,要说明标题和正文各自承担的语气与可读性。
12
- 6. 判断数据表达:趋势用折线/面积,比较用柱状,构成少量类别可用环图,流程用漏斗/步骤,明细必须保留表格替代。
13
- 7. 输出反模式:每个设计建议必须附带“不要做什么”,避免落入通用模板。
8
+ 2. 写出设计读取:页面类型、受众、主任务、品牌约束和可信赖感来源。
9
+ 3. 匹配产品规则:从 `data/product-rules.json` 选择最接近的类别,记录推荐结构、风险和反模式。
10
+ 4. 选择风格原型:从 `data/style-archetypes.json` 选择 1 个主风格和最多 1 个辅助风格,避免风格拼贴。
11
+ 5. 设定设计拨盘:视觉张力、动效强度、信息密度、媒体真实性、内容说服力都用 1-10 表达,并随页面类型变化。
12
+ 6. 建立 token 方向:定义主色、强调色、背景、前景、边框、危险色和 focus ring 的语义角色。
13
+ 7. 选择字体情绪:不要只选“好看的字体”,要说明标题和正文各自承担的语气与可读性。
14
+ 8. 判断数据表达:趋势用折线/面积,比较用柱状,构成少量类别可用环图,流程用漏斗/步骤,明细必须保留表格替代。
15
+ 9. 输出反模式和质量门禁:每个设计建议必须附带“不要做什么”,并根据页面类型补充首屏、CTA、媒体真实性、section 变化和状态完整度检查。
16
+
17
+ ## 方向 Advisor
18
+
19
+ 当用户只说“好看一点”“给几个方向”“我也不知道什么风格”且没有权威设计稿时,不要连续追问泛泛口味问题。先给 3 个差异明显的方向,让用户能判断取舍。
20
+
21
+ 每个方向必须包含:
22
+
23
+ - 适用场景:为什么适合当前产品、受众和任务。
24
+ - 视觉锚点:信息结构、真实媒体、数据形态、材质、字体性格、空间组织或交互节奏。
25
+ - 关键 token:主色、强调色、背景、字体情绪、圆角/边框/阴影倾向。
26
+ - 避免项:这个方向最容易滑向的模板化错误。
27
+
28
+ 三个方向应来自不同设计逻辑,例如:
29
+
30
+ - 信息架构型:高密度、理性、数据优先,适合 B2B、运营、金融、工程工具。
31
+ - 编辑叙事型:版式、留白、强文字层级,适合品牌故事、内容产品、作品集。
32
+ - 产品实证型:真实截图、对象、状态、流程证据优先,适合 SaaS、硬件、开发者工具。
33
+ - 表现实验型:强动效、空间感、生成视觉,适合发布页、活动页、艺术/创意项目。
34
+ - 温暖人本型:低攻击性色彩、可亲近插画或真实人物,适合教育、健康、生活方式。
35
+
36
+ 用户选择方向后,再把它落成设计系统和页面结构;不要把 3 个方向拼贴成一个混杂系统。
37
+
38
+ ## 真实资产优先
39
+
40
+ 品牌或产品相关 UI 的识别度来自真实资产,而不是颜色猜测。优先级:
41
+
42
+ 1. Logo、产品图、真实 UI 截图、实体照片、品牌应用图。
43
+ 2. 项目内已有 icon、组件、数据状态、图表和截图。
44
+ 3. 为当前任务生成的专用资产。
45
+ 4. 明确标记的结构化 placeholder。
46
+
47
+ 不要用 CSS 轮廓、通用插画、假截图或远程占位图替代用户需要识别的主体。缺少关键资产时,先标记资产缺口并给替代路线;若 logo 或主体产品是首屏识别核心,应暂停确认或改为不依赖品牌识别的结构方案。
48
+
49
+ ## v0 校准
50
+
51
+ 视觉风险高、方向不明确或页面影响面较大时,先交付一个可看的 v0,而不是一次性做完整页面。
52
+
53
+ v0 应包含:
54
+
55
+ - 核心布局、首屏层级、主要 token 和一个关键模块。
56
+ - 明确 placeholder 和资产缺口。
57
+ - 1-2 个可替换方向点,例如密度、色彩温度或媒体策略。
58
+ - 不包含完整状态矩阵、所有内容细节或生产级动效。
59
+
60
+ v0 通过后再补齐组件、状态、响应式和交互动效。
61
+
62
+ ## 设计 Critique
63
+
64
+ 当用户要求“评审 UI”“好不好看”“再高级一点”或交付前需要自检时,按 5 个维度输出具体问题,而不是只给主观形容:
65
+
66
+ - 方向一致性:视觉选择是否服务设计读取和产品任务。
67
+ - 层级与扫描:首屏、标题、CTA、数据、状态是否有清楚主次。
68
+ - 工艺质量:间距、对齐、色彩数量、文字换行、圆角/边框/阴影是否稳定。
69
+ - 功能完整度:loading、empty、error、disabled、hover、focus、selected 是否覆盖。
70
+ - 原创性与识别度:是否摆脱通用渐变、三卡片、假截图、无主体 hero。
71
+
72
+ 输出应按严重程度给出可执行修复,不评价设计者本人。
14
73
 
15
74
  ## 何时运行生成器
16
75
 
@@ -29,6 +88,7 @@ node skills/fec-ui-design/scripts/design-system.mjs "fintech analytics dashboard
29
88
  ## 输出必须回答
30
89
 
31
90
  - 这个界面的主任务是什么?
91
+ - 设计读取和五个设计拨盘分别是什么?
32
92
  - 推荐哪种页面结构或工作区结构?
33
93
  - 视觉锚点是什么,为什么贴合业务?
34
94
  - 主风格、字体、色彩、动效分别服务什么目标?
@@ -11,6 +11,9 @@
11
11
  ## 高优先级
12
12
 
13
13
  - 首屏:工具型界面直接展示核心工作区,不用营销 hero 替代功能。
14
+ - 首屏:营销、作品集和品牌页在常见小笔记本高度内显示主体、CTA 和下一屏线索。
15
+ - CTA:按钮文案在桌面端不换行,对比度合格,同一意图使用一致标签。
16
+ - 导航:桌面端保持单行,移动端折叠后仍能到达主要路径。
14
17
  - 响应式:375px、768px、1024px、1440px 无水平溢出、遮挡或文本截断。
15
18
  - 性能:图片有尺寸或 aspect-ratio;非首屏图片懒加载;列表过大时虚拟化。
16
19
  - 动效:只动画 transform/opacity,尊重 `prefers-reduced-motion`。
@@ -27,6 +30,9 @@
27
30
  ## 反模式
28
31
 
29
32
  - 用装饰光斑、紫色渐变、卡片堆叠掩盖信息结构不足。
33
+ - 连续三段以上复用三卡片、左右交错、split header 或同一种 reveal 动效。
34
+ - 视觉型页面只有文字和渐变,没有真实产品、真实状态、品牌应用或可检查媒体。
35
+ - Bento 用空格子补构图,或 feature grid 每个格子同权重、同背景、同节奏。
30
36
  - hover 导致布局位移。
31
37
  - `transition: all`、`will-change: all`。
32
38
  - 低对比灰字、无意义透明度、单一色相界面。
@@ -67,6 +67,14 @@ import { fileURLToPath } from "node:url";
67
67
  * project: string;
68
68
  * page: string;
69
69
  * query: string;
70
+ * designRead: string;
71
+ * designDials: {
72
+ * visualTension: number;
73
+ * motionIntensity: number;
74
+ * informationDensity: number;
75
+ * mediaAuthenticity: number;
76
+ * contentPersuasion: number;
77
+ * };
70
78
  * product: { id: string; label: string; pattern: string; risks: string[] };
71
79
  * style: { id: string; label: string; usage: string | undefined; risks: string[] };
72
80
  * tokens: { color: string; typography: string; space: string; components: string[] };
@@ -230,6 +238,7 @@ function buildRecommendation(args) {
230
238
  const tokens = tokenize([query, args.project, args.page, args.stack].filter(Boolean).join(" "));
231
239
  const product = chooseProduct(tokens);
232
240
  const style = chooseStyle(tokens, product);
241
+ const designDials = deriveDesignDials(tokens, product, style);
233
242
  const checklist = chooseChecklist(tokens, product);
234
243
  const stackGuidance = chooseStack(args.stack, tokens);
235
244
  const pattern = product.pattern ?? product.patterns?.[0] ?? "Task-first interface with explicit states and durable visual hierarchy";
@@ -238,6 +247,8 @@ function buildRecommendation(args) {
238
247
  project: args.project || titleCase(query),
239
248
  page: args.page || "",
240
249
  query,
250
+ designRead: renderDesignRead(product, style, designDials),
251
+ designDials,
241
252
  product: {
242
253
  id: product.id,
243
254
  label: product.label ?? labelFromId(product.id),
@@ -312,11 +323,17 @@ function chooseStyle(tokens, product) {
312
323
  * @returns {ChecklistGroup[]}
313
324
  */
314
325
  function chooseChecklist(tokens, product) {
315
- const priority = new Set(["accessibility", "interaction", "layout", "typography", "animation"]);
326
+ const priority = new Set(["accessibility", "interaction", "layout", "typography", "animation", "state-completeness"]);
316
327
  if (product.id === "data-dashboard" || tokens.has("dashboard") || tokens.has("chart")) priority.add("charts");
317
328
  if (tokens.has("form") || tokens.has("booking") || tokens.has("checkout")) priority.add("forms");
318
329
  if (tokens.has("mobile") || tokens.has("app")) priority.add("navigation");
319
330
  if (tokens.has("performance") || tokens.has("canvas") || tokens.has("three")) priority.add("performance");
331
+ if (isPromotional(tokens, product)) {
332
+ priority.add("first-viewport");
333
+ priority.add("cta-quality");
334
+ priority.add("section-variety");
335
+ priority.add("media-authenticity");
336
+ }
320
337
 
321
338
  return uxQualityRules
322
339
  .filter((rule) => {
@@ -333,6 +350,96 @@ function chooseChecklist(tokens, product) {
333
350
  });
334
351
  }
335
352
 
353
+ /**
354
+ * @param {Set<string>} tokens
355
+ * @param {ProductRule} product
356
+ * @param {StyleArchetype} style
357
+ * @returns {Recommendation["designDials"]}
358
+ */
359
+ function deriveDesignDials(tokens, product, style) {
360
+ /** @type {Recommendation["designDials"]} */
361
+ const dials = {
362
+ visualTension: 5,
363
+ motionIntensity: 3,
364
+ informationDensity: 5,
365
+ mediaAuthenticity: 5,
366
+ contentPersuasion: 5,
367
+ };
368
+
369
+ if (["data-dashboard", "saas", "fintech", "healthcare"].includes(product.id)) {
370
+ dials.visualTension = 3;
371
+ dials.motionIntensity = product.id === "saas" ? 3 : 2;
372
+ dials.informationDensity = product.id === "data-dashboard" ? 8 : 6;
373
+ dials.mediaAuthenticity = 4;
374
+ dials.contentPersuasion = 4;
375
+ }
376
+
377
+ if (["ecommerce", "creative", "wellness"].includes(product.id) || isPromotional(tokens, product)) {
378
+ dials.visualTension = product.id === "creative" ? 8 : 7;
379
+ dials.motionIntensity = product.id === "creative" ? 6 : 5;
380
+ dials.informationDensity = 4;
381
+ dials.mediaAuthenticity = 8;
382
+ dials.contentPersuasion = 8;
383
+ }
384
+
385
+ if (product.id === "gaming" || style.id === "immersive") {
386
+ dials.visualTension = 8;
387
+ dials.motionIntensity = 7;
388
+ dials.informationDensity = 6;
389
+ dials.mediaAuthenticity = 7;
390
+ dials.contentPersuasion = 5;
391
+ }
392
+
393
+ if (["minimal", "minimal-utilitarian"].includes(style.id)) {
394
+ dials.visualTension = Math.min(dials.visualTension, 4);
395
+ dials.motionIntensity = Math.min(dials.motionIntensity, 3);
396
+ }
397
+
398
+ if (["editorial-premium", "image-led-landing", "brand-system-board"].includes(style.id)) {
399
+ dials.visualTension = Math.max(dials.visualTension, 7);
400
+ dials.mediaAuthenticity = Math.max(dials.mediaAuthenticity, 8);
401
+ dials.contentPersuasion = Math.max(dials.contentPersuasion, 7);
402
+ }
403
+
404
+ if (tokens.has("regulated") || tokens.has("public") || tokens.has("government") || tokens.has("accessibility")) {
405
+ dials.visualTension = Math.min(dials.visualTension, 3);
406
+ dials.motionIntensity = Math.min(dials.motionIntensity, 2);
407
+ dials.informationDensity = Math.max(dials.informationDensity, 5);
408
+ }
409
+
410
+ return dials;
411
+ }
412
+
413
+ /**
414
+ * @param {ProductRule} product
415
+ * @param {StyleArchetype} style
416
+ * @param {Recommendation["designDials"]} dials
417
+ * @returns {string}
418
+ */
419
+ function renderDesignRead(product, style, dials) {
420
+ return [
421
+ `Reading this as ${product.label ?? labelFromId(product.id)} work`,
422
+ `with a ${style.label ?? labelFromId(style.id)} visual direction`,
423
+ `and dial targets ${dials.visualTension}/${dials.motionIntensity}/${dials.informationDensity}/${dials.mediaAuthenticity}/${dials.contentPersuasion}`,
424
+ ].join(", ");
425
+ }
426
+
427
+ /**
428
+ * @param {Set<string>} tokens
429
+ * @param {ProductRule} product
430
+ * @returns {boolean}
431
+ */
432
+ function isPromotional(tokens, product) {
433
+ return product.id === "creative"
434
+ || product.id === "ecommerce"
435
+ || tokens.has("landing")
436
+ || tokens.has("marketing")
437
+ || tokens.has("portfolio")
438
+ || tokens.has("brand")
439
+ || tokens.has("website")
440
+ || tokens.has("hero");
441
+ }
442
+
336
443
  /**
337
444
  * @param {string} stack
338
445
  * @param {Set<string>} tokens
@@ -364,10 +471,19 @@ function renderMarkdown(model) {
364
471
  const lines = [
365
472
  `# Design System Recommendation: ${model.project}`,
366
473
  "",
474
+ `- Design read: ${model.designRead}`,
367
475
  `- Product category: ${model.product.label} (${model.product.id})`,
368
476
  `- Recommended pattern: ${model.product.pattern}`,
369
477
  `- Style archetype: ${model.style.label} (${model.style.id})`,
370
478
  "",
479
+ "## Design Dials",
480
+ "",
481
+ `- Visual tension: ${model.designDials.visualTension}/10`,
482
+ `- Motion intensity: ${model.designDials.motionIntensity}/10`,
483
+ `- Information density: ${model.designDials.informationDensity}/10`,
484
+ `- Media authenticity: ${model.designDials.mediaAuthenticity}/10`,
485
+ `- Content persuasion: ${model.designDials.contentPersuasion}/10`,
486
+ "",
371
487
  "## Token Direction",
372
488
  "",
373
489
  `- Color: ${model.tokens.color}`,
@@ -416,10 +532,12 @@ function renderPageOverride(model) {
416
532
  "## Page Intent",
417
533
  "",
418
534
  `Use the Master direction, then adapt layout and component density for ${pageName}. Keep overrides narrow and delete any rule that merely repeats the Master.`,
535
+ `Design read: ${model.designRead}.`,
419
536
  "",
420
537
  "## Override Strategy",
421
538
  "",
422
539
  `- Primary pattern: ${model.product.pattern}`,
540
+ `- Dials: visual ${model.designDials.visualTension}/10, motion ${model.designDials.motionIntensity}/10, density ${model.designDials.informationDensity}/10, media ${model.designDials.mediaAuthenticity}/10, persuasion ${model.designDials.contentPersuasion}/10`,
423
541
  `- Visual emphasis: ${model.style.usage}`,
424
542
  `- Chart behavior: ${model.chart}`,
425
543
  "",
@@ -31,7 +31,7 @@ description: Use when running existing project validation commands and fixing fa
31
31
  - 对 CI 专属失败记录 Node 版本、包管理器、环境变量、路径大小写和工作目录差异。
32
32
  - 修复测试时优先修产品代码或测试等待方式,不用删除断言掩盖真实回归。
33
33
 
34
- ## 强约束
34
+ ## Constraints
35
35
 
36
36
  - 不要盲目关闭规则来消除报错
37
37
  - 除非有明确理由,不要为了通过检查而降低类型安全
@@ -40,9 +40,12 @@ description: Use when running existing project validation commands and fixing fa
40
40
  - 不要删除失败测试来让验证通过
41
41
  - 不要只运行失败命令的片段就声称整体验证通过
42
42
 
43
+ ## 详细参考
44
+
45
+ 撰写验证修复报告时,加载 [references/report-template.md](references/report-template.md)。
46
+
43
47
  ## Expected Output
44
48
 
45
49
  - lint / type-check / test / build 等验证命令全部通过
46
50
  - 失败项已修复或给出明确原因和后续行动
47
51
  - 修复报告保存为 `reports/validation-fix-YYYY-MM-DD-HHmmss.md`
48
- - 报告包含命令状态表、问题根因、修复说明、变更文件和剩余风险
@@ -0,0 +1,43 @@
1
+ # 验证修复报告模板
2
+
3
+ ```markdown
4
+ # 验证修复报告
5
+
6
+ > 生成时间: YYYY-MM-DD HH:mm
7
+ > 验证范围: lint / type-check / test / build / CI
8
+
9
+ ## 命令状态表
10
+
11
+ | 命令 | 初始状态 | 修复后状态 | 备注 |
12
+ | --- | --- | --- | --- |
13
+ | `npm run type-check` | 失败 / 通过 / 未运行 | 失败 / 通过 / 未运行 | ... |
14
+
15
+ ## 失败摘要
16
+
17
+ - 最早出现且会级联的错误
18
+ - 受影响文件、错误类型和关键日志
19
+ - 是否属于 CI 专属、测试环境、依赖版本或 flaky 问题
20
+
21
+ ## 根因
22
+
23
+ - 确认的根本原因
24
+ - 支持该结论的输出、日志或复现证据
25
+
26
+ ## 修复内容
27
+
28
+ - 修改的文件和行为
29
+ - 为什么没有通过关闭规则、删除断言或降低类型安全来规避失败
30
+
31
+ ## 验证结果
32
+
33
+ - 重新执行的命令
34
+ - 命令输出摘要
35
+ - 是否仍有失败项
36
+
37
+ ## 剩余风险
38
+
39
+ - 未覆盖的验证命令
40
+ - 仍需用户决策或外部环境确认的问题
41
+ ```
42
+
43
+ 验证修复完成后,将报告保存到 `reports/validation-fix-YYYY-MM-DD-HHmmss.md`,并告知用户报告路径。
@@ -19,11 +19,17 @@ description: Use when designing or reviewing Vue 3 + TypeScript project structur
19
19
  4. 输出时补齐状态归属、API 层、错误处理、样式隔离和专项 skill 分流。
20
20
  5. 页面和模块要有可恢复错误 UI;全局 `errorHandler`、`onErrorCaptured`、请求错误映射和路由错误页分工明确。
21
21
  6. Tailwind token/variant 或响应式布局需求应分流到对应专项 skill,避免把样式系统规则塞进 Vue 组件规范。
22
- 5. 状态归属复杂时先做状态清单;DTO、公共 props 或泛型 composable 复杂时先收敛 TypeScript 类型契约。
22
+ 7. 状态归属复杂时先做状态清单;DTO、公共 props、泛型 composable 或 `tsconfig` 边界复杂时,先使用 TypeScript 项目规范流程收敛跨框架类型契约。
23
+ 8. 设计可复用 composable 时明确输入是否支持 plain value、ref、computed 或 getter;测试 Vue 组件时覆盖 Pinia、Router、Teleport、Suspense 和 async setup 的常见边界。
23
24
 
24
- ## Detailed References
25
+ ## 详细参考
25
26
 
26
- 需要具体 Vue 3 项目结构、组件模式、Composables、slots、Provide/Inject、路由、Pinia、API 层、错误处理、指令、样式、TypeScript、测试、性能或审查清单时,加载 [references/vue3-project-details.md](references/vue3-project-details.md)。
27
+ 按需要加载更细的参考文件:
28
+
29
+ - 项目目录、组件分层、组件规范、注释和 TypeScript:加载 [references/vue3-project-structure.md](references/vue3-project-structure.md)。
30
+ - Composables、slots、Provide/Inject 和路由组织:加载 [references/vue3-composables-routing.md](references/vue3-composables-routing.md)。
31
+ - Pinia、API 层、错误处理、指令、样式、测试、反模式和输出检查清单:加载 [references/vue3-state-api-quality.md](references/vue3-state-api-quality.md)。
32
+ - Vue 项目规范层面的轻量性能约定:加载 [references/vue3-performance-patterns.md](references/vue3-performance-patterns.md)。
27
33
 
28
34
  ## Constraints
29
35
 
@@ -36,6 +42,8 @@ description: Use when designing or reviewing Vue 3 + TypeScript project structur
36
42
  - 避免在 `v-for` 中使用 `v-if`(提取为 computed 过滤)
37
43
  - 禁止直接从 feature 内部深层路径导入,绕过 `index.ts`
38
44
  - 不用全局错误处理吞掉组件内可恢复的 API、表单或权限错误。
45
+ - 不把函数型参数误当 getter 自动调用;composable 参数若可能是回调,应避免使用 getter 型输入约定。
46
+ - 不依赖快照作为 Vue 组件唯一断言;异步组件、Teleport 和 Pinia 场景要有用户可见行为断言。
39
47
 
40
48
  ## Expected Output
41
49
 
@@ -47,3 +55,4 @@ description: Use when designing or reviewing Vue 3 + TypeScript project structur
47
55
  - API 调用有类型约束和统一错误处理
48
56
  - 样式使用 scoped 隔离,关键行为有测试覆盖
49
57
  - 文件结构与项目约定一致(pages / features / components 分离)
58
+ - 可复用 composable 的输入响应性、Pinia/Router 边界和异步组件测试策略已说明
@@ -0,0 +1,163 @@
1
+ # Vue 3 composables and routing patterns
2
+
3
+ ## Composables 规范
4
+
5
+ ### 设计原则
6
+
7
+ - 以 `use` 前缀命名
8
+ - 返回值使用对象,明确标注类型
9
+ - 内部处理 loading / error / data 三态
10
+ - 支持参数响应式(接受 `Ref` 或 getter)
11
+ - 库级 composable 要明确参数是否支持普通值、`Ref`、`computed` 或 getter,并在副作用内部解析最新值
12
+
13
+ ```typescript
14
+ export function useUserList(params: MaybeRef<QueryParams>) {
15
+ const data = ref<User[]>([]);
16
+ const loading = ref(false);
17
+ const error = ref<Error | null>(null);
18
+
19
+ async function fetch() {
20
+ loading.value = true;
21
+ error.value = null;
22
+ try {
23
+ const res = await getUserList(toValue(params));
24
+ data.value = res.list;
25
+ } catch (e) {
26
+ error.value = e as Error;
27
+ } finally {
28
+ loading.value = false;
29
+ }
30
+ }
31
+
32
+ watchEffect(() => {
33
+ fetch();
34
+ });
35
+
36
+ return {
37
+ data: readonly(data),
38
+ loading: readonly(loading),
39
+ error: readonly(error),
40
+ refetch: fetch,
41
+ };
42
+ }
43
+ ```
44
+
45
+ ### Composable 使用原则
46
+
47
+ - 返回 `readonly` 引用防止外部意外修改
48
+ - 数据请求场景优先使用 VueQuery / VueUse 等库(如项目已引入)
49
+ - `onUnmounted` 中清理定时器、事件监听等副作用
50
+ - 避免在 composable 中直接操作 DOM
51
+ - 只读输入可接受普通值、ref、computed 或 getter;需要双向写入的输入只接受可写 ref 或明确的 setter。
52
+ - 如果参数本身是回调、比较器或 predicate,不要把它设计成 getter 型输入,否则解析时可能误调用业务函数。
53
+
54
+ ### Vue Router / Pinia / 测试常见边界
55
+
56
+ - 路由参数变化不会重新创建同一个路由组件;依赖 `route.params` 的数据要 watch 明确字段,并处理取消和竞态。
57
+ - 导航守卫中避免旧式 `next()` 多分支重复调用;优先返回 `false`、重定向对象或抛出可处理错误。
58
+ - Pinia store 解构会丢失响应性时使用 `storeToRefs`;setup store 必须返回需要被外部追踪的 state、getter 和 action。
59
+ - UI 临时状态、表单输入、弹窗开关不进入全局 store;URL 查询、服务端缓存和本地组件状态先各归其位。
60
+ - Vue Test Utils 测试优先断言用户可见行为,不把快照作为唯一证明;异步更新使用 `await`、`flushPromises` 或框架推荐的等待方式。
61
+ - 测试使用 Pinia、Router、Teleport、Suspense、async setup 或 `defineAsyncComponent` 时,在测试夹具中显式安装插件、挂载目标容器并等待异步稳定。
62
+
63
+ ## Slots 与 Provide/Inject
64
+
65
+ ### Slots
66
+
67
+ - 用 `<slot>` 实现组件组合,而非过多 props
68
+ - 具名 slot 用于明确的布局区域
69
+ - 作用域 slot 传递数据给父组件自定义渲染
70
+
71
+ ```vue
72
+ <template>
73
+ <div class="card">
74
+ <div class="card-header">
75
+ <slot name="header">{{ title }}</slot>
76
+ </div>
77
+ <div class="card-body">
78
+ <slot :data="processedData" :loading="loading" />
79
+ </div>
80
+ </div>
81
+ </template>
82
+ ```
83
+
84
+ ### Provide/Inject
85
+
86
+ - 用于跨多层级的上下文共享(主题、配置、权限)
87
+ - 提供 InjectionKey 保证类型安全
88
+ - 不要用 provide/inject 替代 props 传递直接父子数据
89
+
90
+ ```typescript
91
+ // keys.ts
92
+ export const ThemeKey: InjectionKey<Ref<Theme>> = Symbol("theme");
93
+
94
+ // Provider.vue
95
+ provide(ThemeKey, theme);
96
+
97
+ // Consumer.vue
98
+ const theme = inject(ThemeKey);
99
+ ```
100
+
101
+ ## 路由规范
102
+
103
+ ### 路由组织
104
+
105
+ ```typescript
106
+ // app/router.ts
107
+ const routes: RouteRecordRaw[] = [
108
+ {
109
+ path: "/",
110
+ component: MainLayout,
111
+ children: [
112
+ {
113
+ path: "",
114
+ name: "Dashboard",
115
+ component: () => import("@/pages/Dashboard/DashboardPage.vue"),
116
+ },
117
+ {
118
+ path: "users",
119
+ name: "UserList",
120
+ component: () => import("@/pages/UserList/UserListPage.vue"),
121
+ },
122
+ {
123
+ path: "users/:id",
124
+ name: "UserDetail",
125
+ component: () => import("@/pages/UserDetail/UserDetailPage.vue"),
126
+ },
127
+ {
128
+ path: "settings",
129
+ name: "Settings",
130
+ component: () => import("@/pages/Settings/SettingsPage.vue"),
131
+ },
132
+ ],
133
+ },
134
+ {
135
+ path: "/login",
136
+ name: "Login",
137
+ component: () => import("@/pages/Login/LoginPage.vue"),
138
+ },
139
+ {
140
+ path: "/:pathMatch(.*)*",
141
+ name: "NotFound",
142
+ component: () => import("@/pages/NotFound.vue"),
143
+ },
144
+ ];
145
+ ```
146
+
147
+ ### 路由原则
148
+
149
+ - 路由配置集中管理,每个路由必须有 `name`
150
+ - 页面组件使用动态 `import()` 按需加载
151
+ - 权限控制使用路由守卫(`beforeEach`),而非在每个页面内判断
152
+ - URL 参数(分页、筛选、排序)与路由状态同步
153
+
154
+ ```typescript
155
+ // 导航守卫
156
+ router.beforeEach((to) => {
157
+ const authStore = useAuthStore();
158
+ if (to.meta.requiresAuth && !authStore.isLoggedIn) {
159
+ return { name: "Login", query: { redirect: to.fullPath } };
160
+ }
161
+ });
162
+ ```
163
+
@@ -0,0 +1,13 @@
1
+ # Vue 3 performance patterns
2
+
3
+ This file keeps lightweight Vue project-standard performance guidance. Use the frontend performance workflow when the task needs metrics, traces, profiles, bundle analysis, network evidence, or a formal performance report.
4
+
5
+ ## 性能
6
+
7
+ - 使用 `shallowRef` / `shallowReactive` 优化大型对象
8
+ - 大列表使用虚拟滚动
9
+ - 避免在 `v-for` 中使用 `v-if`(提取为 computed 过滤)
10
+ - 使用 `defineAsyncComponent` 懒加载重型组件
11
+ - `v-for` 必须有稳定的 `:key`
12
+ - 路由组件使用动态 `import()` 按需加载
13
+