cfsa-antigravity 1.0.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 (378) hide show
  1. package/bin/cli.mjs +324 -0
  2. package/package.json +34 -0
  3. package/template/.agent/instructions/commands.md +48 -0
  4. package/template/.agent/instructions/patterns.md +61 -0
  5. package/template/.agent/instructions/structure.md +29 -0
  6. package/template/.agent/instructions/tech-stack.md +43 -0
  7. package/template/.agent/instructions/workflow.md +41 -0
  8. package/template/.agent/kit-sync.md +15 -0
  9. package/template/.agent/rules/boundary-not-placeholder.md +146 -0
  10. package/template/.agent/rules/completion-checklist.md +48 -0
  11. package/template/.agent/rules/decision-classification.md +103 -0
  12. package/template/.agent/rules/extensibility.md +47 -0
  13. package/template/.agent/rules/question-vs-command.md +81 -0
  14. package/template/.agent/rules/security-first.md +43 -0
  15. package/template/.agent/rules/specificity-standards.md +54 -0
  16. package/template/.agent/rules/tdd-contract-first.md +57 -0
  17. package/template/.agent/rules/vertical-slices.md +42 -0
  18. package/template/.agent/skill-library/MANIFEST.md +480 -0
  19. package/template/.agent/skill-library/README.md +38 -0
  20. package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
  21. package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
  22. package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
  23. package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
  24. package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
  25. package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
  26. package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
  27. package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
  28. package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
  29. package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
  30. package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
  31. package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
  32. package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
  33. package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
  34. package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
  35. package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
  36. package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
  37. package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
  38. package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
  39. package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
  40. package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
  41. package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
  42. package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
  43. package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
  44. package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
  45. package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
  46. package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
  47. package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
  48. package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
  49. package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
  50. package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
  51. package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
  52. package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
  53. package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
  54. package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
  55. package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
  56. package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
  57. package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
  58. package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
  59. package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
  60. package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
  61. package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
  62. package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
  63. package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
  64. package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
  65. package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
  66. package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
  67. package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
  68. package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
  69. package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
  70. package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
  71. package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
  72. package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
  73. package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
  74. package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
  75. package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
  76. package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
  77. package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
  78. package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
  79. package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
  80. package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
  81. package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
  82. package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
  83. package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
  84. package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
  85. package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
  86. package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
  87. package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
  88. package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
  89. package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
  90. package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
  91. package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
  92. package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
  93. package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
  94. package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
  95. package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
  96. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
  97. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
  98. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
  99. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
  100. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
  101. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
  102. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
  103. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
  104. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
  105. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
  106. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
  107. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
  108. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
  109. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
  110. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
  111. package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
  112. package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
  113. package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
  114. package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
  115. package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
  116. package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
  117. package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
  118. package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
  119. package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
  120. package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
  121. package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
  122. package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
  123. package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
  124. package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
  125. package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
  126. package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
  127. package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
  128. package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
  129. package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
  130. package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
  131. package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
  132. package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
  133. package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
  134. package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
  135. package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
  136. package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
  137. package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
  138. package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
  139. package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
  140. package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
  141. package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
  142. package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
  143. package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
  144. package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
  145. package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
  146. package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
  147. package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
  148. package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
  149. package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
  150. package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
  151. package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
  152. package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
  153. package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
  154. package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
  155. package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
  156. package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
  157. package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
  158. package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
  159. package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
  160. package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
  161. package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
  162. package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
  163. package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
  164. package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
  165. package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
  166. package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
  167. package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
  168. package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
  169. package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
  170. package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
  171. package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
  172. package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
  173. package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
  174. package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
  175. package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
  176. package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
  177. package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
  178. package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
  179. package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
  180. package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
  181. package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
  182. package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
  183. package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
  184. package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
  185. package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
  186. package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
  187. package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
  188. package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
  189. package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
  190. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
  191. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
  192. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
  193. package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
  194. package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
  195. package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
  196. package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
  197. package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
  198. package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
  199. package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
  200. package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
  201. package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
  202. package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
  203. package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
  204. package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
  205. package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
  206. package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
  207. package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
  208. package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
  209. package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
  210. package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
  211. package/template/.agent/skills/accessibility/SKILL.md +522 -0
  212. package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
  213. package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
  214. package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
  215. package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
  216. package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
  217. package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  218. package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
  219. package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
  220. package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
  221. package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
  222. package/template/.agent/skills/api-versioning/SKILL.md +420 -0
  223. package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
  224. package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
  225. package/template/.agent/skills/brainstorming/SKILL.md +236 -0
  226. package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
  227. package/template/.agent/skills/clean-code/SKILL.md +94 -0
  228. package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
  229. package/template/.agent/skills/concise-planning/SKILL.md +68 -0
  230. package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
  231. package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
  232. package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
  233. package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
  234. package/template/.agent/skills/design-direction/SKILL.md +45 -0
  235. package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
  236. package/template/.agent/skills/find-skills/SKILL.md +145 -0
  237. package/template/.agent/skills/git-advanced/SKILL.md +972 -0
  238. package/template/.agent/skills/git-workflow/SKILL.md +420 -0
  239. package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
  240. package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
  241. package/template/.agent/skills/migration-management/SKILL.md +384 -0
  242. package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
  243. package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
  244. package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
  245. package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
  246. package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
  247. package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
  248. package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
  249. package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
  250. package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
  251. package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
  252. package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
  253. package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
  254. package/template/.agent/skills/prd-templates/SKILL.md +88 -0
  255. package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
  256. package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
  257. package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
  258. package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
  259. package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
  260. package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
  261. package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
  262. package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
  263. package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
  264. package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
  265. package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
  266. package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
  267. package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
  268. package/template/.agent/skills/prompt-engineer/README.md +659 -0
  269. package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
  270. package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
  271. package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
  272. package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
  273. package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
  274. package/template/.agent/skills/session-continuity/SKILL.md +730 -0
  275. package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
  276. package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
  277. package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
  278. package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
  279. package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
  280. package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
  281. package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
  282. package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
  283. package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
  284. package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
  285. package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
  286. package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
  287. package/template/.agent/skills/skill-creator/README.md +270 -0
  288. package/template/.agent/skills/skill-creator/SKILL.md +590 -0
  289. package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
  290. package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
  291. package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
  292. package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
  293. package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
  294. package/template/.agent/skills/spec-writing/SKILL.md +110 -0
  295. package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
  296. package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
  297. package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  298. package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
  299. package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
  300. package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
  301. package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
  302. package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
  303. package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
  304. package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
  305. package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
  306. package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
  307. package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
  308. package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
  309. package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
  310. package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
  311. package/template/.agent/skills/technical-writer/SKILL.md +242 -0
  312. package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
  313. package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
  314. package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
  315. package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
  316. package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
  317. package/template/.agent/workflows/audit-ambiguity.md +64 -0
  318. package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
  319. package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
  320. package/template/.agent/workflows/bootstrap-agents.md +66 -0
  321. package/template/.agent/workflows/create-prd-architecture.md +119 -0
  322. package/template/.agent/workflows/create-prd-compile.md +138 -0
  323. package/template/.agent/workflows/create-prd-design-system.md +135 -0
  324. package/template/.agent/workflows/create-prd-security.md +113 -0
  325. package/template/.agent/workflows/create-prd-stack.md +91 -0
  326. package/template/.agent/workflows/create-prd.md +168 -0
  327. package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
  328. package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
  329. package/template/.agent/workflows/decompose-architecture.md +111 -0
  330. package/template/.agent/workflows/evolve-contract.md +98 -0
  331. package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
  332. package/template/.agent/workflows/evolve-feature-classify.md +116 -0
  333. package/template/.agent/workflows/evolve-feature.md +56 -0
  334. package/template/.agent/workflows/ideate-discover.md +144 -0
  335. package/template/.agent/workflows/ideate-extract.md +129 -0
  336. package/template/.agent/workflows/ideate-validate.md +117 -0
  337. package/template/.agent/workflows/ideate.md +113 -0
  338. package/template/.agent/workflows/implement-slice-setup.md +113 -0
  339. package/template/.agent/workflows/implement-slice-tdd.md +198 -0
  340. package/template/.agent/workflows/implement-slice.md +50 -0
  341. package/template/.agent/workflows/plan-phase.md +202 -0
  342. package/template/.agent/workflows/propagate-decision-apply.md +135 -0
  343. package/template/.agent/workflows/propagate-decision-scan.md +147 -0
  344. package/template/.agent/workflows/propagate-decision.md +56 -0
  345. package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
  346. package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
  347. package/template/.agent/workflows/remediate-pipeline.md +55 -0
  348. package/template/.agent/workflows/resolve-ambiguity.md +82 -0
  349. package/template/.agent/workflows/sync-kit.md +209 -0
  350. package/template/.agent/workflows/update-architecture-map.md +74 -0
  351. package/template/.agent/workflows/validate-phase.md +219 -0
  352. package/template/.agent/workflows/verify-infrastructure.md +207 -0
  353. package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
  354. package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
  355. package/template/.agent/workflows/write-architecture-spec.md +63 -0
  356. package/template/.agent/workflows/write-be-spec-classify.md +165 -0
  357. package/template/.agent/workflows/write-be-spec-write.md +98 -0
  358. package/template/.agent/workflows/write-be-spec.md +76 -0
  359. package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
  360. package/template/.agent/workflows/write-fe-spec-write.md +94 -0
  361. package/template/.agent/workflows/write-fe-spec.md +71 -0
  362. package/template/AGENTS.md +176 -0
  363. package/template/GEMINI.md +177 -0
  364. package/template/docs/README.md +187 -0
  365. package/template/docs/audits/.gitkeep +0 -0
  366. package/template/docs/audits/README.md +10 -0
  367. package/template/docs/plans/.gitkeep +0 -0
  368. package/template/docs/plans/README.md +21 -0
  369. package/template/docs/plans/be/.gitkeep +0 -0
  370. package/template/docs/plans/be/README.md +11 -0
  371. package/template/docs/plans/fe/.gitkeep +0 -0
  372. package/template/docs/plans/fe/README.md +11 -0
  373. package/template/docs/plans/ia/.gitkeep +0 -0
  374. package/template/docs/plans/ia/README.md +17 -0
  375. package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
  376. package/template/docs/plans/ia/deep-dives/README.md +5 -0
  377. package/template/docs/plans/phases/.gitkeep +0 -0
  378. package/template/docs/plans/phases/README.md +11 -0
@@ -0,0 +1,1107 @@
1
+ ---
2
+ name: react-composition-patterns
3
+ description: "Comprehensive React composition and component design guide covering compound components, render props, custom hooks, explicit variants, lifting state, slot-based composition, polymorphic components, controlled vs uncontrolled patterns, provider pattern, state machines, form patterns, modal management, and list/item patterns. Use when designing component APIs, building reusable UI libraries, or structuring complex component hierarchies."
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # React Composition Patterns
8
+
9
+ ## 1. Philosophy
10
+
11
+ Component composition is about **building complex UIs from simple, reusable pieces without tight coupling**. The goal is an API that is obvious to consumers, flexible enough for real-world use cases, and impossible to misuse.
12
+
13
+ **Key principles**:
14
+ - Composition over configuration. Prefer children and slots over giant prop objects.
15
+ - Explicit over implicit. A component with 5 clear variants beats one with 15 boolean props.
16
+ - Inversion of control. Let the consumer decide layout and behavior, not the component.
17
+ - Single responsibility. Each component does one thing. Compose them for complex behavior.
18
+ - Type safety. Component APIs must be fully typed so misuse is a compile error, not a runtime bug.
19
+
20
+ ---
21
+
22
+ ## 2. Compound Components
23
+
24
+ Compound components share implicit state through React Context. The parent manages the state; children read from it. This gives consumers full control over layout and ordering while keeping behavior centralized.
25
+
26
+ ### Basic Pattern
27
+
28
+ ```tsx
29
+ import { createContext, useContext, useState, type ReactNode } from "react";
30
+
31
+ // 1. Create context for shared state
32
+ interface AccordionContextValue {
33
+ openItems: Set<string>;
34
+ toggle: (id: string) => void;
35
+ }
36
+
37
+ const AccordionContext = createContext<AccordionContextValue | null>(null);
38
+
39
+ function useAccordion() {
40
+ const context = useContext(AccordionContext);
41
+ if (!context) {
42
+ throw new Error("Accordion.Item must be used within an Accordion");
43
+ }
44
+ return context;
45
+ }
46
+
47
+ // 2. Parent component manages state
48
+ function Accordion({
49
+ children,
50
+ multiple = false,
51
+ }: {
52
+ children: ReactNode;
53
+ multiple?: boolean;
54
+ }) {
55
+ const [openItems, setOpenItems] = useState<Set<string>>(new Set());
56
+
57
+ function toggle(id: string) {
58
+ setOpenItems((prev) => {
59
+ const next = new Set(multiple ? prev : []);
60
+ if (prev.has(id)) {
61
+ next.delete(id);
62
+ } else {
63
+ next.add(id);
64
+ }
65
+ return next;
66
+ });
67
+ }
68
+
69
+ return (
70
+ <AccordionContext.Provider value={{ openItems, toggle }}>
71
+ <div role="region">{children}</div>
72
+ </AccordionContext.Provider>
73
+ );
74
+ }
75
+
76
+ // 3. Child components read shared state
77
+ function AccordionItem({
78
+ id,
79
+ title,
80
+ children,
81
+ }: {
82
+ id: string;
83
+ title: string;
84
+ children: ReactNode;
85
+ }) {
86
+ const { openItems, toggle } = useAccordion();
87
+ const isOpen = openItems.has(id);
88
+
89
+ return (
90
+ <div>
91
+ <button
92
+ onClick={() => toggle(id)}
93
+ aria-expanded={isOpen}
94
+ aria-controls={`accordion-panel-${id}`}
95
+ >
96
+ {title}
97
+ </button>
98
+ {isOpen && (
99
+ <div id={`accordion-panel-${id}`} role="region">
100
+ {children}
101
+ </div>
102
+ )}
103
+ </div>
104
+ );
105
+ }
106
+
107
+ // 4. Attach as static properties
108
+ Accordion.Item = AccordionItem;
109
+
110
+ // 5. Usage -- consumer controls layout and ordering
111
+ <Accordion multiple>
112
+ <Accordion.Item id="faq-1" title="What is this?">
113
+ <p>A compound component example.</p>
114
+ </Accordion.Item>
115
+ <Accordion.Item id="faq-2" title="Why use this pattern?">
116
+ <p>Flexible layout with shared state.</p>
117
+ </Accordion.Item>
118
+ </Accordion>
119
+ ```
120
+
121
+ ### When to Use Compound Components
122
+
123
+ | Use When | Do Not Use When |
124
+ |----------|-----------------|
125
+ | Multiple sub-components share state | A single component with a few props suffices |
126
+ | Consumer needs layout control | The layout is always the same |
127
+ | The parent-child relationship is semantic | Components are unrelated |
128
+ | You want to avoid prop drilling | A simple callback prop would work |
129
+
130
+ ---
131
+
132
+ ## 3. Render Props and Children-as-Function
133
+
134
+ Render props pass rendering control to the consumer via a function. Use this when the component owns behavior but the consumer owns the visual output.
135
+
136
+ ```tsx
137
+ interface MouseTrackerProps {
138
+ children: (position: { x: number; y: number }) => ReactNode;
139
+ }
140
+
141
+ function MouseTracker({ children }: MouseTrackerProps) {
142
+ const [position, setPosition] = useState({ x: 0, y: 0 });
143
+
144
+ return (
145
+ <div onMouseMove={(e) => setPosition({ x: e.clientX, y: e.clientY })}>
146
+ {children(position)}
147
+ </div>
148
+ );
149
+ }
150
+
151
+ // Usage -- consumer decides what to render
152
+ <MouseTracker>
153
+ {({ x, y }) => (
154
+ <div>
155
+ Mouse is at ({x}, {y})
156
+ </div>
157
+ )}
158
+ </MouseTracker>
159
+ ```
160
+
161
+ ### Modern Alternative: Custom Hooks
162
+
163
+ Render props are largely replaced by custom hooks. Prefer hooks unless you need to inject behavior into the JSX tree itself.
164
+
165
+ ```tsx
166
+ // Prefer this
167
+ function useMousePosition() {
168
+ const [position, setPosition] = useState({ x: 0, y: 0 });
169
+
170
+ useEffect(() => {
171
+ function handleMove(e: MouseEvent) {
172
+ setPosition({ x: e.clientX, y: e.clientY });
173
+ }
174
+ window.addEventListener("mousemove", handleMove);
175
+ return () => window.removeEventListener("mousemove", handleMove);
176
+ }, []);
177
+
178
+ return position;
179
+ }
180
+
181
+ // Usage
182
+ function Component() {
183
+ const { x, y } = useMousePosition();
184
+ return <div>Mouse at ({x}, {y})</div>;
185
+ }
186
+ ```
187
+
188
+ ---
189
+
190
+ ## 4. Custom Hooks for Logic Extraction
191
+
192
+ Custom hooks extract reusable stateful logic from components. The component handles rendering; the hook handles behavior.
193
+
194
+ ```tsx
195
+ // hooks/use-async.ts
196
+ import { useState, useCallback } from "react";
197
+
198
+ interface AsyncState<T> {
199
+ data: T | null;
200
+ error: Error | null;
201
+ loading: boolean;
202
+ }
203
+
204
+ export function useAsync<T>(asyncFunction: () => Promise<T>) {
205
+ const [state, setState] = useState<AsyncState<T>>({
206
+ data: null,
207
+ error: null,
208
+ loading: false,
209
+ });
210
+
211
+ const execute = useCallback(async () => {
212
+ setState({ data: null, error: null, loading: true });
213
+ try {
214
+ const data = await asyncFunction();
215
+ setState({ data, error: null, loading: false });
216
+ return data;
217
+ } catch (error) {
218
+ const err = error instanceof Error ? error : new Error(String(error));
219
+ setState({ data: null, error: err, loading: false });
220
+ throw err;
221
+ }
222
+ }, [asyncFunction]);
223
+
224
+ return { ...state, execute };
225
+ }
226
+
227
+ // Usage
228
+ function UserProfile({ userId }: { userId: string }) {
229
+ const fetchUser = useCallback(() => api.getUser(userId), [userId]);
230
+ const { data: user, loading, error, execute } = useAsync(fetchUser);
231
+
232
+ useEffect(() => { execute(); }, [execute]);
233
+
234
+ if (loading) return <Skeleton />;
235
+ if (error) return <ErrorDisplay error={error} onRetry={execute} />;
236
+ if (!user) return null;
237
+ return <ProfileCard user={user} />;
238
+ }
239
+ ```
240
+
241
+ ### Hook Composition
242
+
243
+ Hooks compose naturally. Build complex behavior from simple hooks.
244
+
245
+ ```tsx
246
+ function useDebounce<T>(value: T, delay: number): T {
247
+ const [debounced, setDebounced] = useState(value);
248
+
249
+ useEffect(() => {
250
+ const timer = setTimeout(() => setDebounced(value), delay);
251
+ return () => clearTimeout(timer);
252
+ }, [value, delay]);
253
+
254
+ return debounced;
255
+ }
256
+
257
+ function useSearch(query: string) {
258
+ const debouncedQuery = useDebounce(query, 300);
259
+ const fetchResults = useCallback(
260
+ () => api.search(debouncedQuery),
261
+ [debouncedQuery]
262
+ );
263
+ return useAsync(fetchResults);
264
+ }
265
+ ```
266
+
267
+ ---
268
+
269
+ ## 5. Explicit Variants Over Conditional Rendering
270
+
271
+ When a component has multiple visual modes, use explicit variant components instead of piling boolean props onto one component.
272
+
273
+ ```tsx
274
+ // BAD: Boolean props create an exponential combination space
275
+ <Button
276
+ primary
277
+ outline
278
+ small
279
+ loading
280
+ iconOnly
281
+ disabled
282
+ />
283
+ // How many combinations is this? 2^6 = 64. Are they all valid?
284
+
285
+ // GOOD: Explicit variants with a discriminated union
286
+ type ButtonVariant = "primary" | "secondary" | "outline" | "ghost" | "destructive";
287
+ type ButtonSize = "sm" | "md" | "lg" | "icon";
288
+
289
+ interface ButtonProps {
290
+ variant?: ButtonVariant;
291
+ size?: ButtonSize;
292
+ loading?: boolean;
293
+ disabled?: boolean;
294
+ children: ReactNode;
295
+ }
296
+
297
+ function Button({
298
+ variant = "primary",
299
+ size = "md",
300
+ loading = false,
301
+ disabled = false,
302
+ children,
303
+ }: ButtonProps) {
304
+ return (
305
+ <button
306
+ className={cn(variantStyles[variant], sizeStyles[size])}
307
+ disabled={disabled || loading}
308
+ >
309
+ {loading && <Spinner size={size} />}
310
+ {children}
311
+ </button>
312
+ );
313
+ }
314
+ ```
315
+
316
+ ### Separate Components for Separate Concerns
317
+
318
+ ```tsx
319
+ // BAD: One component with conditional rendering for every case
320
+ function Card({ type, ...props }: { type: "user" | "product" | "article" }) {
321
+ if (type === "user") return <div>...</div>;
322
+ if (type === "product") return <div>...</div>;
323
+ if (type === "article") return <div>...</div>;
324
+ }
325
+
326
+ // GOOD: Separate components sharing a common base
327
+ function CardBase({ children, className }: { children: ReactNode; className?: string }) {
328
+ return <div className={cn("rounded-lg border p-4", className)}>{children}</div>;
329
+ }
330
+
331
+ function UserCard({ user }: { user: User }) {
332
+ return (
333
+ <CardBase>
334
+ <Avatar src={user.avatar} />
335
+ <h3>{user.name}</h3>
336
+ </CardBase>
337
+ );
338
+ }
339
+
340
+ function ProductCard({ product }: { product: Product }) {
341
+ return (
342
+ <CardBase>
343
+ <img src={product.image} alt={product.name} />
344
+ <h3>{product.name}</h3>
345
+ <p>{product.price}</p>
346
+ </CardBase>
347
+ );
348
+ }
349
+ ```
350
+
351
+ ---
352
+
353
+ ## 6. Lifting State Up
354
+
355
+ When two sibling components need to share state, lift the state to their closest common parent.
356
+
357
+ ```tsx
358
+ // Problem: FilterBar and ResultsList both need the filter state
359
+ // Solution: Lift state to the parent
360
+
361
+ function SearchPage() {
362
+ const [filters, setFilters] = useState<Filters>({
363
+ category: "all",
364
+ sortBy: "relevance",
365
+ query: "",
366
+ });
367
+
368
+ return (
369
+ <div className="grid grid-cols-[250px_1fr]">
370
+ <FilterBar filters={filters} onFiltersChange={setFilters} />
371
+ <ResultsList filters={filters} />
372
+ </div>
373
+ );
374
+ }
375
+
376
+ // FilterBar only knows about its own UI concerns
377
+ function FilterBar({
378
+ filters,
379
+ onFiltersChange,
380
+ }: {
381
+ filters: Filters;
382
+ onFiltersChange: (filters: Filters) => void;
383
+ }) {
384
+ return (
385
+ <aside>
386
+ <select
387
+ value={filters.category}
388
+ onChange={(e) =>
389
+ onFiltersChange({ ...filters, category: e.target.value })
390
+ }
391
+ >
392
+ <option value="all">All</option>
393
+ <option value="books">Books</option>
394
+ </select>
395
+ </aside>
396
+ );
397
+ }
398
+
399
+ // ResultsList only knows about displaying results
400
+ function ResultsList({ filters }: { filters: Filters }) {
401
+ const results = useFilteredResults(filters);
402
+ return (
403
+ <ul>
404
+ {results.map((r) => (
405
+ <li key={r.id}>{r.title}</li>
406
+ ))}
407
+ </ul>
408
+ );
409
+ }
410
+ ```
411
+
412
+ ---
413
+
414
+ ## 7. Slot-Based Composition
415
+
416
+ Slots let consumers inject content into specific positions within a component. Use named props for slots instead of relying on children ordering.
417
+
418
+ ```tsx
419
+ interface PageLayoutProps {
420
+ header: ReactNode;
421
+ sidebar: ReactNode;
422
+ children: ReactNode;
423
+ footer?: ReactNode;
424
+ }
425
+
426
+ function PageLayout({ header, sidebar, children, footer }: PageLayoutProps) {
427
+ return (
428
+ <div className="min-h-screen grid grid-rows-[auto_1fr_auto]">
429
+ <header>{header}</header>
430
+ <div className="grid grid-cols-[250px_1fr]">
431
+ <aside>{sidebar}</aside>
432
+ <main>{children}</main>
433
+ </div>
434
+ {footer && <footer>{footer}</footer>}
435
+ </div>
436
+ );
437
+ }
438
+
439
+ // Usage -- consumer fills each slot
440
+ <PageLayout
441
+ header={<NavBar />}
442
+ sidebar={<SideMenu />}
443
+ footer={<FooterLinks />}
444
+ >
445
+ <DashboardContent />
446
+ </PageLayout>
447
+ ```
448
+
449
+ ### Slot Pattern with Default Content
450
+
451
+ ```tsx
452
+ interface DialogProps {
453
+ title: ReactNode;
454
+ description?: ReactNode;
455
+ actions?: ReactNode;
456
+ children: ReactNode;
457
+ }
458
+
459
+ function Dialog({ title, description, actions, children }: DialogProps) {
460
+ return (
461
+ <div role="dialog" aria-labelledby="dialog-title">
462
+ <div id="dialog-title">{title}</div>
463
+ {description && <div>{description}</div>}
464
+ <div>{children}</div>
465
+ <div className="flex justify-end gap-2">
466
+ {actions ?? <button>Close</button>}
467
+ </div>
468
+ </div>
469
+ );
470
+ }
471
+ ```
472
+
473
+ ---
474
+
475
+ ## 8. Polymorphic Components (as Prop)
476
+
477
+ Polymorphic components let consumers change the rendered HTML element while preserving the component's styling and behavior.
478
+
479
+ ```tsx
480
+ import { type ElementType, type ComponentPropsWithoutRef } from "react";
481
+
482
+ type TextProps<T extends ElementType = "span"> = {
483
+ as?: T;
484
+ size?: "sm" | "md" | "lg";
485
+ weight?: "normal" | "medium" | "bold";
486
+ children: ReactNode;
487
+ } & Omit<ComponentPropsWithoutRef<T>, "as" | "size" | "weight" | "children">;
488
+
489
+ function Text<T extends ElementType = "span">({
490
+ as,
491
+ size = "md",
492
+ weight = "normal",
493
+ children,
494
+ className,
495
+ ...props
496
+ }: TextProps<T>) {
497
+ const Component = as || "span";
498
+
499
+ return (
500
+ <Component
501
+ className={cn(
502
+ sizeMap[size],
503
+ weightMap[weight],
504
+ className
505
+ )}
506
+ {...props}
507
+ >
508
+ {children}
509
+ </Component>
510
+ );
511
+ }
512
+
513
+ // Usage -- same styling, different elements
514
+ <Text as="h1" size="lg" weight="bold">Page Title</Text>
515
+ <Text as="p" size="md">Body paragraph</Text>
516
+ <Text as="label" size="sm" htmlFor="email">Email</Text>
517
+ <Text as="a" href="/about" size="sm">About</Text>
518
+ ```
519
+
520
+ ---
521
+
522
+ ## 9. Controlled vs Uncontrolled Components
523
+
524
+ A component is **controlled** when the parent owns its state. It is **uncontrolled** when it manages its own state internally. Good APIs support both.
525
+
526
+ ```tsx
527
+ interface ToggleProps {
528
+ // Controlled mode
529
+ checked?: boolean;
530
+ onChange?: (checked: boolean) => void;
531
+ // Uncontrolled mode
532
+ defaultChecked?: boolean;
533
+ // Shared
534
+ label: string;
535
+ disabled?: boolean;
536
+ }
537
+
538
+ function Toggle({
539
+ checked: controlledChecked,
540
+ onChange,
541
+ defaultChecked = false,
542
+ label,
543
+ disabled = false,
544
+ }: ToggleProps) {
545
+ // Internal state for uncontrolled mode
546
+ const [internalChecked, setInternalChecked] = useState(defaultChecked);
547
+
548
+ // Determine which mode we are in
549
+ const isControlled = controlledChecked !== undefined;
550
+ const isChecked = isControlled ? controlledChecked : internalChecked;
551
+
552
+ function handleChange() {
553
+ if (disabled) return;
554
+
555
+ const nextChecked = !isChecked;
556
+
557
+ if (!isControlled) {
558
+ setInternalChecked(nextChecked);
559
+ }
560
+
561
+ onChange?.(nextChecked);
562
+ }
563
+
564
+ return (
565
+ <button
566
+ role="switch"
567
+ aria-checked={isChecked}
568
+ aria-label={label}
569
+ disabled={disabled}
570
+ onClick={handleChange}
571
+ >
572
+ <span className={isChecked ? "translate-x-5" : "translate-x-0"} />
573
+ </button>
574
+ );
575
+ }
576
+
577
+ // Uncontrolled -- component manages its own state
578
+ <Toggle label="Dark mode" defaultChecked />
579
+
580
+ // Controlled -- parent owns the state
581
+ const [isDark, setIsDark] = useState(false);
582
+ <Toggle label="Dark mode" checked={isDark} onChange={setIsDark} />
583
+ ```
584
+
585
+ ---
586
+
587
+ ## 10. Provider Pattern
588
+
589
+ The Provider pattern uses Context to inject dependencies (services, configuration, theme) deep into the component tree without prop drilling.
590
+
591
+ ```tsx
592
+ // contexts/feature-flags.tsx
593
+ import { createContext, useContext, type ReactNode } from "react";
594
+
595
+ interface FeatureFlags {
596
+ newDashboard: boolean;
597
+ betaSearch: boolean;
598
+ darkMode: boolean;
599
+ }
600
+
601
+ const FeatureFlagContext = createContext<FeatureFlags | null>(null);
602
+
603
+ export function FeatureFlagProvider({
604
+ flags,
605
+ children,
606
+ }: {
607
+ flags: FeatureFlags;
608
+ children: ReactNode;
609
+ }) {
610
+ return (
611
+ <FeatureFlagContext.Provider value={flags}>
612
+ {children}
613
+ </FeatureFlagContext.Provider>
614
+ );
615
+ }
616
+
617
+ export function useFeatureFlag(flag: keyof FeatureFlags): boolean {
618
+ const context = useContext(FeatureFlagContext);
619
+ if (!context) {
620
+ throw new Error("useFeatureFlag must be used within FeatureFlagProvider");
621
+ }
622
+ return context[flag];
623
+ }
624
+
625
+ // Usage in a component
626
+ function Dashboard() {
627
+ const showNewDashboard = useFeatureFlag("newDashboard");
628
+
629
+ if (showNewDashboard) {
630
+ return <NewDashboard />;
631
+ }
632
+ return <LegacyDashboard />;
633
+ }
634
+ ```
635
+
636
+ ### Avoid Overusing Context
637
+
638
+ Context triggers re-renders for all consumers when the value changes. Split contexts by update frequency.
639
+
640
+ ```tsx
641
+ // BAD: One giant context that changes frequently
642
+ const AppContext = createContext({
643
+ user: null,
644
+ theme: "light",
645
+ notifications: [],
646
+ mousePosition: { x: 0, y: 0 }, // changes 60fps
647
+ });
648
+
649
+ // GOOD: Split by update frequency
650
+ const UserContext = createContext<User | null>(null); // rarely changes
651
+ const ThemeContext = createContext<Theme>("light"); // rarely changes
652
+ const NotificationContext = createContext<Notification[]>([]); // sometimes changes
653
+ // mousePosition should be a hook, not context
654
+ ```
655
+
656
+ ---
657
+
658
+ ## 11. State Machines for Complex UI
659
+
660
+ When a component has many states with specific transition rules, use a state machine instead of multiple booleans.
661
+
662
+ ```tsx
663
+ // Without state machine -- boolean soup
664
+ const [isLoading, setIsLoading] = useState(false);
665
+ const [isError, setIsError] = useState(false);
666
+ const [isSuccess, setIsSuccess] = useState(false);
667
+ const [isRetrying, setIsRetrying] = useState(false);
668
+ // What happens when isLoading AND isError are both true?
669
+
670
+ // With a state machine -- impossible states are impossible
671
+ type UploadState =
672
+ | { status: "idle" }
673
+ | { status: "selecting" }
674
+ | { status: "uploading"; progress: number }
675
+ | { status: "success"; url: string }
676
+ | { status: "error"; message: string };
677
+
678
+ type UploadAction =
679
+ | { type: "SELECT_FILE" }
680
+ | { type: "START_UPLOAD" }
681
+ | { type: "PROGRESS"; progress: number }
682
+ | { type: "COMPLETE"; url: string }
683
+ | { type: "FAIL"; message: string }
684
+ | { type: "RESET" };
685
+
686
+ function uploadReducer(state: UploadState, action: UploadAction): UploadState {
687
+ switch (state.status) {
688
+ case "idle":
689
+ if (action.type === "SELECT_FILE") return { status: "selecting" };
690
+ return state;
691
+ case "selecting":
692
+ if (action.type === "START_UPLOAD") return { status: "uploading", progress: 0 };
693
+ if (action.type === "RESET") return { status: "idle" };
694
+ return state;
695
+ case "uploading":
696
+ if (action.type === "PROGRESS") return { status: "uploading", progress: action.progress };
697
+ if (action.type === "COMPLETE") return { status: "success", url: action.url };
698
+ if (action.type === "FAIL") return { status: "error", message: action.message };
699
+ return state;
700
+ case "success":
701
+ if (action.type === "RESET") return { status: "idle" };
702
+ return state;
703
+ case "error":
704
+ if (action.type === "START_UPLOAD") return { status: "uploading", progress: 0 };
705
+ if (action.type === "RESET") return { status: "idle" };
706
+ return state;
707
+ default:
708
+ return state;
709
+ }
710
+ }
711
+
712
+ function FileUploader() {
713
+ const [state, dispatch] = useReducer(uploadReducer, { status: "idle" });
714
+
715
+ // Each status has exactly one UI representation
716
+ switch (state.status) {
717
+ case "idle":
718
+ return <button onClick={() => dispatch({ type: "SELECT_FILE" })}>Upload</button>;
719
+ case "selecting":
720
+ return <FileSelector onSelect={() => dispatch({ type: "START_UPLOAD" })} />;
721
+ case "uploading":
722
+ return <ProgressBar progress={state.progress} />;
723
+ case "success":
724
+ return <SuccessMessage url={state.url} onReset={() => dispatch({ type: "RESET" })} />;
725
+ case "error":
726
+ return <ErrorMessage message={state.message} onRetry={() => dispatch({ type: "START_UPLOAD" })} />;
727
+ }
728
+ }
729
+ ```
730
+
731
+ ### XState for Complex Machines
732
+
733
+ For multi-step wizards, workflows, or anything with parallel states, use XState.
734
+
735
+ ```tsx
736
+ import { createMachine, assign } from "xstate";
737
+ import { useMachine } from "@xstate/react";
738
+
739
+ const checkoutMachine = createMachine({
740
+ id: "checkout",
741
+ initial: "cart",
742
+ context: { items: [], address: null, payment: null },
743
+ states: {
744
+ cart: { on: { PROCEED: "address" } },
745
+ address: {
746
+ on: {
747
+ SET_ADDRESS: { actions: assign({ address: (_, event) => event.data }) },
748
+ PROCEED: { target: "payment", guard: "hasAddress" },
749
+ BACK: "cart",
750
+ },
751
+ },
752
+ payment: {
753
+ on: {
754
+ SET_PAYMENT: { actions: assign({ payment: (_, event) => event.data }) },
755
+ SUBMIT: "processing",
756
+ BACK: "address",
757
+ },
758
+ },
759
+ processing: {
760
+ invoke: {
761
+ src: "processOrder",
762
+ onDone: "confirmation",
763
+ onError: "error",
764
+ },
765
+ },
766
+ confirmation: { type: "final" },
767
+ error: { on: { RETRY: "processing" } },
768
+ },
769
+ });
770
+ ```
771
+
772
+ ---
773
+
774
+ ## 12. Form Component Patterns
775
+
776
+ ### Field Component Pattern
777
+
778
+ Encapsulate label, input, error, and description into a reusable Field component.
779
+
780
+ ```tsx
781
+ interface FieldProps {
782
+ label: string;
783
+ error?: string;
784
+ description?: string;
785
+ required?: boolean;
786
+ children: ReactNode;
787
+ }
788
+
789
+ function Field({ label, error, description, required, children }: FieldProps) {
790
+ const id = useId();
791
+
792
+ return (
793
+ <div className="space-y-1">
794
+ <label htmlFor={id} className="text-sm font-medium">
795
+ {label}
796
+ {required && <span className="text-red-500 ml-1" aria-hidden="true">*</span>}
797
+ </label>
798
+ {cloneElement(children as React.ReactElement, {
799
+ id,
800
+ "aria-describedby": description ? `${id}-desc` : undefined,
801
+ "aria-invalid": !!error,
802
+ })}
803
+ {description && (
804
+ <p id={`${id}-desc`} className="text-xs text-muted-foreground">
805
+ {description}
806
+ </p>
807
+ )}
808
+ {error && (
809
+ <p role="alert" className="text-xs text-red-500">
810
+ {error}
811
+ </p>
812
+ )}
813
+ </div>
814
+ );
815
+ }
816
+
817
+ // Usage
818
+ <Field label="Email" error={errors.email} required>
819
+ <input type="email" name="email" />
820
+ </Field>
821
+ ```
822
+
823
+ ### Multi-Step Form Pattern
824
+
825
+ ```tsx
826
+ interface Step {
827
+ id: string;
828
+ title: string;
829
+ component: React.ComponentType<StepProps>;
830
+ validate: (data: FormData) => Record<string, string> | null;
831
+ }
832
+
833
+ function MultiStepForm({ steps }: { steps: Step[] }) {
834
+ const [currentStep, setCurrentStep] = useState(0);
835
+ const [formData, setFormData] = useState<Record<string, unknown>>({});
836
+
837
+ const StepComponent = steps[currentStep].component;
838
+
839
+ function handleNext(stepData: Record<string, unknown>) {
840
+ const errors = steps[currentStep].validate(stepData);
841
+ if (errors) return errors;
842
+
843
+ setFormData((prev) => ({ ...prev, ...stepData }));
844
+ if (currentStep < steps.length - 1) {
845
+ setCurrentStep((prev) => prev + 1);
846
+ }
847
+ return null;
848
+ }
849
+
850
+ return (
851
+ <div>
852
+ <StepIndicator steps={steps} current={currentStep} />
853
+ <StepComponent
854
+ data={formData}
855
+ onNext={handleNext}
856
+ onBack={() => setCurrentStep((prev) => Math.max(0, prev - 1))}
857
+ />
858
+ </div>
859
+ );
860
+ }
861
+ ```
862
+
863
+ ---
864
+
865
+ ## 13. Modal and Dialog Management
866
+
867
+ ### Portal-Based Modal
868
+
869
+ ```tsx
870
+ import { createPortal } from "react-dom";
871
+ import { useEffect, useRef } from "react";
872
+
873
+ function Modal({
874
+ open,
875
+ onClose,
876
+ children,
877
+ }: {
878
+ open: boolean;
879
+ onClose: () => void;
880
+ children: ReactNode;
881
+ }) {
882
+ const previousFocus = useRef<HTMLElement | null>(null);
883
+
884
+ useEffect(() => {
885
+ if (open) {
886
+ previousFocus.current = document.activeElement as HTMLElement;
887
+ // Trap focus inside modal
888
+ } else {
889
+ previousFocus.current?.focus();
890
+ }
891
+ }, [open]);
892
+
893
+ // Close on Escape
894
+ useEffect(() => {
895
+ if (!open) return;
896
+ function handleKeyDown(e: KeyboardEvent) {
897
+ if (e.key === "Escape") onClose();
898
+ }
899
+ document.addEventListener("keydown", handleKeyDown);
900
+ return () => document.removeEventListener("keydown", handleKeyDown);
901
+ }, [open, onClose]);
902
+
903
+ if (!open) return null;
904
+
905
+ return createPortal(
906
+ <div className="fixed inset-0 z-50 flex items-center justify-center">
907
+ <div className="fixed inset-0 bg-black/50" onClick={onClose} aria-hidden="true" />
908
+ <div role="dialog" aria-modal="true" className="relative bg-white rounded-lg p-6">
909
+ {children}
910
+ </div>
911
+ </div>,
912
+ document.body
913
+ );
914
+ }
915
+ ```
916
+
917
+ ### Declarative Modal Management
918
+
919
+ ```tsx
920
+ // hooks/use-modal.ts
921
+ function useModal() {
922
+ const [isOpen, setIsOpen] = useState(false);
923
+
924
+ const modal = useMemo(
925
+ () => ({
926
+ isOpen,
927
+ open: () => setIsOpen(true),
928
+ close: () => setIsOpen(false),
929
+ toggle: () => setIsOpen((prev) => !prev),
930
+ props: { open: isOpen, onClose: () => setIsOpen(false) },
931
+ }),
932
+ [isOpen]
933
+ );
934
+
935
+ return modal;
936
+ }
937
+
938
+ // Usage
939
+ function UserList() {
940
+ const deleteModal = useModal();
941
+ const [selectedUser, setSelectedUser] = useState<User | null>(null);
942
+
943
+ function handleDelete(user: User) {
944
+ setSelectedUser(user);
945
+ deleteModal.open();
946
+ }
947
+
948
+ return (
949
+ <div>
950
+ {users.map((user) => (
951
+ <UserRow key={user.id} user={user} onDelete={() => handleDelete(user)} />
952
+ ))}
953
+ <ConfirmDialog
954
+ {...deleteModal.props}
955
+ title="Delete User"
956
+ description={`Are you sure you want to delete ${selectedUser?.name}?`}
957
+ onConfirm={() => deleteUser(selectedUser!.id)}
958
+ />
959
+ </div>
960
+ );
961
+ }
962
+ ```
963
+
964
+ ---
965
+
966
+ ## 14. List and Item Patterns
967
+
968
+ ### Consistent List API
969
+
970
+ ```tsx
971
+ interface ListProps<T> {
972
+ items: T[];
973
+ renderItem: (item: T, index: number) => ReactNode;
974
+ keyExtractor: (item: T) => string;
975
+ emptyState?: ReactNode;
976
+ loading?: boolean;
977
+ loadingSkeleton?: ReactNode;
978
+ }
979
+
980
+ function List<T>({
981
+ items,
982
+ renderItem,
983
+ keyExtractor,
984
+ emptyState,
985
+ loading,
986
+ loadingSkeleton,
987
+ }: ListProps<T>) {
988
+ if (loading && loadingSkeleton) return <>{loadingSkeleton}</>;
989
+ if (items.length === 0 && emptyState) return <>{emptyState}</>;
990
+
991
+ return (
992
+ <ul role="list">
993
+ {items.map((item, index) => (
994
+ <li key={keyExtractor(item)}>{renderItem(item, index)}</li>
995
+ ))}
996
+ </ul>
997
+ );
998
+ }
999
+
1000
+ // Usage
1001
+ <List
1002
+ items={users}
1003
+ keyExtractor={(user) => user.id}
1004
+ renderItem={(user) => <UserCard user={user} />}
1005
+ emptyState={<EmptyState message="No users found" />}
1006
+ loading={isLoading}
1007
+ loadingSkeleton={<UserListSkeleton count={5} />}
1008
+ />
1009
+ ```
1010
+
1011
+ ### Selectable List Pattern
1012
+
1013
+ ```tsx
1014
+ function useSelection<T>(
1015
+ items: T[],
1016
+ keyExtractor: (item: T) => string
1017
+ ) {
1018
+ const [selectedKeys, setSelectedKeys] = useState<Set<string>>(new Set());
1019
+
1020
+ const toggleItem = useCallback((item: T) => {
1021
+ const key = keyExtractor(item);
1022
+ setSelectedKeys((prev) => {
1023
+ const next = new Set(prev);
1024
+ if (next.has(key)) {
1025
+ next.delete(key);
1026
+ } else {
1027
+ next.add(key);
1028
+ }
1029
+ return next;
1030
+ });
1031
+ }, [keyExtractor]);
1032
+
1033
+ const selectAll = useCallback(() => {
1034
+ setSelectedKeys(new Set(items.map(keyExtractor)));
1035
+ }, [items, keyExtractor]);
1036
+
1037
+ const clearSelection = useCallback(() => {
1038
+ setSelectedKeys(new Set());
1039
+ }, []);
1040
+
1041
+ const isSelected = useCallback(
1042
+ (item: T) => selectedKeys.has(keyExtractor(item)),
1043
+ [selectedKeys, keyExtractor]
1044
+ );
1045
+
1046
+ return {
1047
+ selectedKeys,
1048
+ selectedCount: selectedKeys.size,
1049
+ toggleItem,
1050
+ selectAll,
1051
+ clearSelection,
1052
+ isSelected,
1053
+ isAllSelected: selectedKeys.size === items.length && items.length > 0,
1054
+ };
1055
+ }
1056
+ ```
1057
+
1058
+ ---
1059
+
1060
+ ## 15. Anti-Patterns
1061
+
1062
+ ### NEVER
1063
+
1064
+ - Use boolean props for mutually exclusive states (`isPrimary` and `isSecondary` on the same component)
1065
+ - Deeply nest context providers when a single provider with composed state would work
1066
+ - Use `cloneElement` to inject props when composition or render props are clearer
1067
+ - Build "God components" with 20+ props -- decompose into compound components
1068
+ - Store UI state in global state management (Redux, Zustand) -- use local state or context
1069
+ - Create wrapper components that just pass all props through to a child
1070
+ - Use `children` for multiple unrelated slots -- use named props instead
1071
+ - Couple component logic to a specific data fetching library
1072
+
1073
+ ### ALWAYS
1074
+
1075
+ - Provide TypeScript types for all component props
1076
+ - Include `children` in the type when the component accepts arbitrary content
1077
+ - Use `ReactNode` for slot types (not `JSX.Element` or `React.ReactElement`)
1078
+ - Make components work in both controlled and uncontrolled modes when sensible
1079
+ - Throw descriptive errors when compound component children are used outside their parent
1080
+ - Test components in isolation with different prop combinations
1081
+ - Document which props are required vs optional with TypeScript
1082
+ - Use discriminated unions for variant props instead of string unions when variants have different data shapes
1083
+
1084
+ ---
1085
+
1086
+ ## 16. Decision Guide
1087
+
1088
+ ```
1089
+ +----------------------------+
1090
+ | Need shared implicit state |
1091
+ | across siblings? |
1092
+ +-----------+----------------+
1093
+ YES | NO
1094
+ +-----------v---+ +---v-------------------+
1095
+ | Compound | | Need layout control |
1096
+ | Components | | for consumer? |
1097
+ +---------------+ +---+-------------------+
1098
+ YES | NO
1099
+ +-------v------+ +--v-----------------+
1100
+ | Slot-based | | Need to share |
1101
+ | Composition | | logic, not UI? |
1102
+ +--------------+ +--+-----------------+
1103
+ YES | NO
1104
+ +-------v------+ +--v-----------+
1105
+ | Custom Hook | | Simple Props |
1106
+ +--------------+ +--------------+
1107
+ ```