compact-agent 1.1.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 (324) hide show
  1. package/README.md +394 -0
  2. package/bin/anycode.js +2 -0
  3. package/bin/crowcoder.js +19 -0
  4. package/bin/ecc-hooks.cjs +138 -0
  5. package/dist/agents.d.ts +17 -0
  6. package/dist/agents.js +1603 -0
  7. package/dist/agents.js.map +1 -0
  8. package/dist/api.d.ts +16 -0
  9. package/dist/api.js +115 -0
  10. package/dist/api.js.map +1 -0
  11. package/dist/autonomous-loops.d.ts +108 -0
  12. package/dist/autonomous-loops.js +526 -0
  13. package/dist/autonomous-loops.js.map +1 -0
  14. package/dist/codemaps.d.ts +53 -0
  15. package/dist/codemaps.js +325 -0
  16. package/dist/codemaps.js.map +1 -0
  17. package/dist/compaction.d.ts +30 -0
  18. package/dist/compaction.js +125 -0
  19. package/dist/compaction.js.map +1 -0
  20. package/dist/config.d.ts +5 -0
  21. package/dist/config.js +79 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/content-engine.d.ts +97 -0
  24. package/dist/content-engine.js +721 -0
  25. package/dist/content-engine.js.map +1 -0
  26. package/dist/cost-tracker.d.ts +49 -0
  27. package/dist/cost-tracker.js +150 -0
  28. package/dist/cost-tracker.js.map +1 -0
  29. package/dist/counter-button.d.ts +35 -0
  30. package/dist/counter-button.js +48 -0
  31. package/dist/counter-button.js.map +1 -0
  32. package/dist/counter.d.ts +21 -0
  33. package/dist/counter.js +31 -0
  34. package/dist/counter.js.map +1 -0
  35. package/dist/coverage.d.ts +23 -0
  36. package/dist/coverage.js +215 -0
  37. package/dist/coverage.js.map +1 -0
  38. package/dist/docs-sync.d.ts +23 -0
  39. package/dist/docs-sync.js +266 -0
  40. package/dist/docs-sync.js.map +1 -0
  41. package/dist/ecc.d.ts +41 -0
  42. package/dist/ecc.js +644 -0
  43. package/dist/ecc.js.map +1 -0
  44. package/dist/evaluation.d.ts +24 -0
  45. package/dist/evaluation.js +412 -0
  46. package/dist/evaluation.js.map +1 -0
  47. package/dist/export.d.ts +22 -0
  48. package/dist/export.js +109 -0
  49. package/dist/export.js.map +1 -0
  50. package/dist/git-workflow.d.ts +22 -0
  51. package/dist/git-workflow.js +197 -0
  52. package/dist/git-workflow.js.map +1 -0
  53. package/dist/hook-controls.d.ts +34 -0
  54. package/dist/hook-controls.js +90 -0
  55. package/dist/hook-controls.js.map +1 -0
  56. package/dist/hooks.d.ts +30 -0
  57. package/dist/hooks.js +130 -0
  58. package/dist/hooks.js.map +1 -0
  59. package/dist/html-parser.d.ts +18 -0
  60. package/dist/html-parser.js +101 -0
  61. package/dist/html-parser.js.map +1 -0
  62. package/dist/index.d.ts +12 -0
  63. package/dist/index.js +1230 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/learning.d.ts +35 -0
  66. package/dist/learning.js +238 -0
  67. package/dist/learning.js.map +1 -0
  68. package/dist/login.d.ts +37 -0
  69. package/dist/login.js +191 -0
  70. package/dist/login.js.map +1 -0
  71. package/dist/memory.d.ts +39 -0
  72. package/dist/memory.js +183 -0
  73. package/dist/memory.js.map +1 -0
  74. package/dist/model-router.d.ts +23 -0
  75. package/dist/model-router.js +145 -0
  76. package/dist/model-router.js.map +1 -0
  77. package/dist/modes.d.ts +17 -0
  78. package/dist/modes.js +217 -0
  79. package/dist/modes.js.map +1 -0
  80. package/dist/orchestration.d.ts +37 -0
  81. package/dist/orchestration.js +139 -0
  82. package/dist/orchestration.js.map +1 -0
  83. package/dist/package-detect.d.ts +36 -0
  84. package/dist/package-detect.js +529 -0
  85. package/dist/package-detect.js.map +1 -0
  86. package/dist/permissions.d.ts +25 -0
  87. package/dist/permissions.js +50 -0
  88. package/dist/permissions.js.map +1 -0
  89. package/dist/pm2-manager.d.ts +40 -0
  90. package/dist/pm2-manager.js +127 -0
  91. package/dist/pm2-manager.js.map +1 -0
  92. package/dist/query.d.ts +15 -0
  93. package/dist/query.js +278 -0
  94. package/dist/query.js.map +1 -0
  95. package/dist/refactor.d.ts +22 -0
  96. package/dist/refactor.js +226 -0
  97. package/dist/refactor.js.map +1 -0
  98. package/dist/retry.d.ts +20 -0
  99. package/dist/retry.js +88 -0
  100. package/dist/retry.js.map +1 -0
  101. package/dist/rules.d.ts +34 -0
  102. package/dist/rules.js +942 -0
  103. package/dist/rules.js.map +1 -0
  104. package/dist/schema.d.ts +23 -0
  105. package/dist/schema.js +12 -0
  106. package/dist/schema.js.map +1 -0
  107. package/dist/search-first.d.ts +17 -0
  108. package/dist/search-first.js +301 -0
  109. package/dist/search-first.js.map +1 -0
  110. package/dist/security.d.ts +10 -0
  111. package/dist/security.js +145 -0
  112. package/dist/security.js.map +1 -0
  113. package/dist/sessions.d.ts +21 -0
  114. package/dist/sessions.js +112 -0
  115. package/dist/sessions.js.map +1 -0
  116. package/dist/skill-create.d.ts +38 -0
  117. package/dist/skill-create.js +389 -0
  118. package/dist/skill-create.js.map +1 -0
  119. package/dist/skills.d.ts +34 -0
  120. package/dist/skills.js +161 -0
  121. package/dist/skills.js.map +1 -0
  122. package/dist/strategic-compaction.d.ts +24 -0
  123. package/dist/strategic-compaction.js +144 -0
  124. package/dist/strategic-compaction.js.map +1 -0
  125. package/dist/system-prompt.d.ts +3 -0
  126. package/dist/system-prompt.js +101 -0
  127. package/dist/system-prompt.js.map +1 -0
  128. package/dist/theme.d.ts +60 -0
  129. package/dist/theme.js +220 -0
  130. package/dist/theme.js.map +1 -0
  131. package/dist/tools/bash.d.ts +2 -0
  132. package/dist/tools/bash.js +49 -0
  133. package/dist/tools/bash.js.map +1 -0
  134. package/dist/tools/edit.d.ts +2 -0
  135. package/dist/tools/edit.js +76 -0
  136. package/dist/tools/edit.js.map +1 -0
  137. package/dist/tools/glob.d.ts +2 -0
  138. package/dist/tools/glob.js +54 -0
  139. package/dist/tools/glob.js.map +1 -0
  140. package/dist/tools/grep.d.ts +2 -0
  141. package/dist/tools/grep.js +64 -0
  142. package/dist/tools/grep.js.map +1 -0
  143. package/dist/tools/index.d.ts +5 -0
  144. package/dist/tools/index.js +27 -0
  145. package/dist/tools/index.js.map +1 -0
  146. package/dist/tools/list-dir.d.ts +2 -0
  147. package/dist/tools/list-dir.js +51 -0
  148. package/dist/tools/list-dir.js.map +1 -0
  149. package/dist/tools/read.d.ts +2 -0
  150. package/dist/tools/read.js +56 -0
  151. package/dist/tools/read.js.map +1 -0
  152. package/dist/tools/types.d.ts +45 -0
  153. package/dist/tools/types.js +2 -0
  154. package/dist/tools/types.js.map +1 -0
  155. package/dist/tools/web-fetch.d.ts +2 -0
  156. package/dist/tools/web-fetch.js +41 -0
  157. package/dist/tools/web-fetch.js.map +1 -0
  158. package/dist/tools/web-search.d.ts +27 -0
  159. package/dist/tools/web-search.js +139 -0
  160. package/dist/tools/web-search.js.map +1 -0
  161. package/dist/tools/write.d.ts +2 -0
  162. package/dist/tools/write.js +36 -0
  163. package/dist/tools/write.js.map +1 -0
  164. package/dist/types.d.ts +28 -0
  165. package/dist/types.js +57 -0
  166. package/dist/types.js.map +1 -0
  167. package/dist/users.d.ts +51 -0
  168. package/dist/users.js +193 -0
  169. package/dist/users.js.map +1 -0
  170. package/dist/verification.d.ts +73 -0
  171. package/dist/verification.js +269 -0
  172. package/dist/verification.js.map +1 -0
  173. package/dist/walkthrough.d.ts +10 -0
  174. package/dist/walkthrough.js +121 -0
  175. package/dist/walkthrough.js.map +1 -0
  176. package/package.json +58 -0
  177. package/resources/ecc/agents/architect.json +16 -0
  178. package/resources/ecc/agents/architect.md +212 -0
  179. package/resources/ecc/agents/build-error-resolver.json +17 -0
  180. package/resources/ecc/agents/build-error-resolver.md +116 -0
  181. package/resources/ecc/agents/chief-of-staff.json +17 -0
  182. package/resources/ecc/agents/chief-of-staff.md +153 -0
  183. package/resources/ecc/agents/code-reviewer.json +16 -0
  184. package/resources/ecc/agents/code-reviewer.md +238 -0
  185. package/resources/ecc/agents/database-reviewer.json +16 -0
  186. package/resources/ecc/agents/database-reviewer.md +92 -0
  187. package/resources/ecc/agents/doc-updater.json +16 -0
  188. package/resources/ecc/agents/doc-updater.md +108 -0
  189. package/resources/ecc/agents/e2e-runner.json +17 -0
  190. package/resources/ecc/agents/e2e-runner.md +109 -0
  191. package/resources/ecc/agents/go-build-resolver.json +17 -0
  192. package/resources/ecc/agents/go-build-resolver.md +96 -0
  193. package/resources/ecc/agents/go-reviewer.json +16 -0
  194. package/resources/ecc/agents/go-reviewer.md +77 -0
  195. package/resources/ecc/agents/harness-optimizer.json +15 -0
  196. package/resources/ecc/agents/harness-optimizer.md +34 -0
  197. package/resources/ecc/agents/loop-operator.json +16 -0
  198. package/resources/ecc/agents/loop-operator.md +36 -0
  199. package/resources/ecc/agents/planner.json +15 -0
  200. package/resources/ecc/agents/planner.md +212 -0
  201. package/resources/ecc/agents/python-reviewer.json +16 -0
  202. package/resources/ecc/agents/python-reviewer.md +99 -0
  203. package/resources/ecc/agents/refactor-cleaner.json +17 -0
  204. package/resources/ecc/agents/refactor-cleaner.md +87 -0
  205. package/resources/ecc/agents/security-reviewer.json +16 -0
  206. package/resources/ecc/agents/security-reviewer.md +109 -0
  207. package/resources/ecc/agents/tdd-guide.json +17 -0
  208. package/resources/ecc/agents/tdd-guide.md +93 -0
  209. package/resources/ecc/commands/add-language-rules.md +39 -0
  210. package/resources/ecc/commands/database-migration.md +36 -0
  211. package/resources/ecc/commands/feature-development.md +38 -0
  212. package/resources/ecc/prompts/build-fix.prompt.md +47 -0
  213. package/resources/ecc/prompts/code-review.prompt.md +56 -0
  214. package/resources/ecc/prompts/plan.prompt.md +52 -0
  215. package/resources/ecc/prompts/refactor.prompt.md +50 -0
  216. package/resources/ecc/prompts/security-review.prompt.md +70 -0
  217. package/resources/ecc/prompts/tdd.prompt.md +47 -0
  218. package/resources/ecc/rules/common-agents.md +53 -0
  219. package/resources/ecc/rules/common-coding-style.md +52 -0
  220. package/resources/ecc/rules/common-development-workflow.md +33 -0
  221. package/resources/ecc/rules/common-git-workflow.md +28 -0
  222. package/resources/ecc/rules/common-hooks.md +34 -0
  223. package/resources/ecc/rules/common-patterns.md +35 -0
  224. package/resources/ecc/rules/common-performance.md +59 -0
  225. package/resources/ecc/rules/common-security.md +33 -0
  226. package/resources/ecc/rules/common-testing.md +33 -0
  227. package/resources/ecc/rules/golang-coding-style.md +31 -0
  228. package/resources/ecc/rules/golang-hooks.md +16 -0
  229. package/resources/ecc/rules/golang-patterns.md +44 -0
  230. package/resources/ecc/rules/golang-security.md +33 -0
  231. package/resources/ecc/rules/golang-testing.md +30 -0
  232. package/resources/ecc/rules/kotlin-coding-style.md +39 -0
  233. package/resources/ecc/rules/kotlin-hooks.md +16 -0
  234. package/resources/ecc/rules/kotlin-patterns.md +50 -0
  235. package/resources/ecc/rules/kotlin-security.md +58 -0
  236. package/resources/ecc/rules/kotlin-testing.md +38 -0
  237. package/resources/ecc/rules/php-coding-style.md +25 -0
  238. package/resources/ecc/rules/php-hooks.md +21 -0
  239. package/resources/ecc/rules/php-patterns.md +23 -0
  240. package/resources/ecc/rules/php-security.md +24 -0
  241. package/resources/ecc/rules/php-testing.md +26 -0
  242. package/resources/ecc/rules/python-coding-style.md +42 -0
  243. package/resources/ecc/rules/python-hooks.md +19 -0
  244. package/resources/ecc/rules/python-patterns.md +39 -0
  245. package/resources/ecc/rules/python-security.md +30 -0
  246. package/resources/ecc/rules/python-testing.md +38 -0
  247. package/resources/ecc/rules/swift-coding-style.md +47 -0
  248. package/resources/ecc/rules/swift-hooks.md +20 -0
  249. package/resources/ecc/rules/swift-patterns.md +66 -0
  250. package/resources/ecc/rules/swift-security.md +33 -0
  251. package/resources/ecc/rules/swift-testing.md +45 -0
  252. package/resources/ecc/rules/typescript-coding-style.md +63 -0
  253. package/resources/ecc/rules/typescript-hooks.md +20 -0
  254. package/resources/ecc/rules/typescript-patterns.md +50 -0
  255. package/resources/ecc/rules/typescript-security.md +26 -0
  256. package/resources/ecc/rules/typescript-testing.md +16 -0
  257. package/resources/ecc/skills/agent-introspection-debugging/SKILL.md +152 -0
  258. package/resources/ecc/skills/agent-introspection-debugging/agents/openai.yaml +7 -0
  259. package/resources/ecc/skills/agent-sort/SKILL.md +214 -0
  260. package/resources/ecc/skills/agent-sort/agents/openai.yaml +7 -0
  261. package/resources/ecc/skills/api-design/SKILL.md +522 -0
  262. package/resources/ecc/skills/api-design/agents/openai.yaml +7 -0
  263. package/resources/ecc/skills/article-writing/SKILL.md +78 -0
  264. package/resources/ecc/skills/article-writing/agents/openai.yaml +7 -0
  265. package/resources/ecc/skills/backend-patterns/SKILL.md +597 -0
  266. package/resources/ecc/skills/backend-patterns/agents/openai.yaml +7 -0
  267. package/resources/ecc/skills/brand-voice/SKILL.md +96 -0
  268. package/resources/ecc/skills/brand-voice/agents/openai.yaml +7 -0
  269. package/resources/ecc/skills/brand-voice/references/voice-profile-schema.md +55 -0
  270. package/resources/ecc/skills/bun-runtime/SKILL.md +83 -0
  271. package/resources/ecc/skills/bun-runtime/agents/openai.yaml +7 -0
  272. package/resources/ecc/skills/coding-standards/SKILL.md +548 -0
  273. package/resources/ecc/skills/coding-standards/agents/openai.yaml +7 -0
  274. package/resources/ecc/skills/content-engine/SKILL.md +130 -0
  275. package/resources/ecc/skills/content-engine/agents/openai.yaml +7 -0
  276. package/resources/ecc/skills/crosspost/SKILL.md +110 -0
  277. package/resources/ecc/skills/crosspost/agents/openai.yaml +7 -0
  278. package/resources/ecc/skills/deep-research/SKILL.md +154 -0
  279. package/resources/ecc/skills/deep-research/agents/openai.yaml +7 -0
  280. package/resources/ecc/skills/dmux-workflows/SKILL.md +143 -0
  281. package/resources/ecc/skills/dmux-workflows/agents/openai.yaml +7 -0
  282. package/resources/ecc/skills/documentation-lookup/SKILL.md +89 -0
  283. package/resources/ecc/skills/documentation-lookup/agents/openai.yaml +7 -0
  284. package/resources/ecc/skills/e2e-testing/SKILL.md +325 -0
  285. package/resources/ecc/skills/e2e-testing/agents/openai.yaml +7 -0
  286. package/resources/ecc/skills/eval-harness/SKILL.md +235 -0
  287. package/resources/ecc/skills/eval-harness/agents/openai.yaml +7 -0
  288. package/resources/ecc/skills/everything-claude-code/SKILL.md +442 -0
  289. package/resources/ecc/skills/everything-claude-code/agents/openai.yaml +7 -0
  290. package/resources/ecc/skills/exa-search/SKILL.md +169 -0
  291. package/resources/ecc/skills/exa-search/agents/openai.yaml +7 -0
  292. package/resources/ecc/skills/fal-ai-media/SKILL.md +276 -0
  293. package/resources/ecc/skills/fal-ai-media/agents/openai.yaml +7 -0
  294. package/resources/ecc/skills/frontend-patterns/SKILL.md +647 -0
  295. package/resources/ecc/skills/frontend-patterns/agents/openai.yaml +7 -0
  296. package/resources/ecc/skills/frontend-slides/SKILL.md +183 -0
  297. package/resources/ecc/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  298. package/resources/ecc/skills/frontend-slides/agents/openai.yaml +7 -0
  299. package/resources/ecc/skills/investor-materials/SKILL.md +95 -0
  300. package/resources/ecc/skills/investor-materials/agents/openai.yaml +7 -0
  301. package/resources/ecc/skills/investor-outreach/SKILL.md +90 -0
  302. package/resources/ecc/skills/investor-outreach/agents/openai.yaml +7 -0
  303. package/resources/ecc/skills/market-research/SKILL.md +74 -0
  304. package/resources/ecc/skills/market-research/agents/openai.yaml +7 -0
  305. package/resources/ecc/skills/mcp-server-patterns/SKILL.md +66 -0
  306. package/resources/ecc/skills/mcp-server-patterns/agents/openai.yaml +7 -0
  307. package/resources/ecc/skills/mle-workflow/SKILL.md +346 -0
  308. package/resources/ecc/skills/mle-workflow/agents/openai.yaml +7 -0
  309. package/resources/ecc/skills/nextjs-turbopack/SKILL.md +43 -0
  310. package/resources/ecc/skills/nextjs-turbopack/agents/openai.yaml +7 -0
  311. package/resources/ecc/skills/product-capability/SKILL.md +140 -0
  312. package/resources/ecc/skills/product-capability/agents/openai.yaml +7 -0
  313. package/resources/ecc/skills/security-review/SKILL.md +494 -0
  314. package/resources/ecc/skills/security-review/agents/openai.yaml +7 -0
  315. package/resources/ecc/skills/strategic-compact/SKILL.md +102 -0
  316. package/resources/ecc/skills/strategic-compact/agents/openai.yaml +7 -0
  317. package/resources/ecc/skills/tdd-workflow/SKILL.md +409 -0
  318. package/resources/ecc/skills/tdd-workflow/agents/openai.yaml +7 -0
  319. package/resources/ecc/skills/verification-loop/SKILL.md +125 -0
  320. package/resources/ecc/skills/verification-loop/agents/openai.yaml +7 -0
  321. package/resources/ecc/skills/video-editing/SKILL.md +307 -0
  322. package/resources/ecc/skills/video-editing/agents/openai.yaml +7 -0
  323. package/resources/ecc/skills/x-api/SKILL.md +229 -0
  324. package/resources/ecc/skills/x-api/agents/openai.yaml +7 -0
@@ -0,0 +1,647 @@
1
+ ---
2
+ name: frontend-patterns
3
+ description: Frontend development patterns for React, Next.js, state management, performance optimization, and UI best practices.
4
+ ---
5
+
6
+ # Frontend Development Patterns
7
+
8
+ Modern frontend patterns for React, Next.js, and performant user interfaces.
9
+
10
+ ## When to Activate
11
+
12
+ - Building React components (composition, props, rendering)
13
+ - Managing state (useState, useReducer, Zustand, Context)
14
+ - Implementing data fetching (SWR, React Query, server components)
15
+ - Optimizing performance (memoization, virtualization, code splitting)
16
+ - Working with forms (validation, controlled inputs, Zod schemas)
17
+ - Handling client-side routing and navigation
18
+ - Building accessible, responsive UI patterns
19
+
20
+ ## Privacy and Data Boundaries
21
+
22
+ Frontend examples should use synthetic or domain-generic data. Do not collect, log, persist, or display credentials, access tokens, SSNs, health data, payment details, private emails, phone numbers, or other sensitive personal data unless the user explicitly requests a scoped implementation with appropriate validation, redaction, and access controls.
23
+
24
+ Avoid adding analytics, tracking pixels, third-party scripts, or external data sinks without explicit approval. When handling user data, prefer least-privilege APIs, client-side redaction before logging, and server-side validation for every boundary.
25
+
26
+ ## Component Patterns
27
+
28
+ ### Composition Over Inheritance
29
+
30
+ ```typescript
31
+ // PASS: GOOD: Component composition
32
+ interface CardProps {
33
+ children: React.ReactNode
34
+ variant?: 'default' | 'outlined'
35
+ }
36
+
37
+ export function Card({ children, variant = 'default' }: CardProps) {
38
+ return <div className={`card card-${variant}`}>{children}</div>
39
+ }
40
+
41
+ export function CardHeader({ children }: { children: React.ReactNode }) {
42
+ return <div className="card-header">{children}</div>
43
+ }
44
+
45
+ export function CardBody({ children }: { children: React.ReactNode }) {
46
+ return <div className="card-body">{children}</div>
47
+ }
48
+
49
+ // Usage
50
+ <Card>
51
+ <CardHeader>Title</CardHeader>
52
+ <CardBody>Content</CardBody>
53
+ </Card>
54
+ ```
55
+
56
+ ### Compound Components
57
+
58
+ ```typescript
59
+ interface TabsContextValue {
60
+ activeTab: string
61
+ setActiveTab: (tab: string) => void
62
+ }
63
+
64
+ const TabsContext = createContext<TabsContextValue | undefined>(undefined)
65
+
66
+ export function Tabs({ children, defaultTab }: {
67
+ children: React.ReactNode
68
+ defaultTab: string
69
+ }) {
70
+ const [activeTab, setActiveTab] = useState(defaultTab)
71
+
72
+ return (
73
+ <TabsContext.Provider value={{ activeTab, setActiveTab }}>
74
+ {children}
75
+ </TabsContext.Provider>
76
+ )
77
+ }
78
+
79
+ export function TabList({ children }: { children: React.ReactNode }) {
80
+ return <div className="tab-list">{children}</div>
81
+ }
82
+
83
+ export function Tab({ id, children }: { id: string, children: React.ReactNode }) {
84
+ const context = useContext(TabsContext)
85
+ if (!context) throw new Error('Tab must be used within Tabs')
86
+
87
+ return (
88
+ <button
89
+ className={context.activeTab === id ? 'active' : ''}
90
+ onClick={() => context.setActiveTab(id)}
91
+ >
92
+ {children}
93
+ </button>
94
+ )
95
+ }
96
+
97
+ // Usage
98
+ <Tabs defaultTab="overview">
99
+ <TabList>
100
+ <Tab id="overview">Overview</Tab>
101
+ <Tab id="details">Details</Tab>
102
+ </TabList>
103
+ </Tabs>
104
+ ```
105
+
106
+ ### Render Props Pattern
107
+
108
+ ```typescript
109
+ interface DataLoaderProps<T> {
110
+ url: string
111
+ children: (data: T | null, loading: boolean, error: Error | null) => React.ReactNode
112
+ }
113
+
114
+ export function DataLoader<T>({ url, children }: DataLoaderProps<T>) {
115
+ const [data, setData] = useState<T | null>(null)
116
+ const [loading, setLoading] = useState(true)
117
+ const [error, setError] = useState<Error | null>(null)
118
+
119
+ useEffect(() => {
120
+ fetch(url)
121
+ .then(res => res.json())
122
+ .then(setData)
123
+ .catch(setError)
124
+ .finally(() => setLoading(false))
125
+ }, [url])
126
+
127
+ return <>{children(data, loading, error)}</>
128
+ }
129
+
130
+ // Usage
131
+ <DataLoader<Market[]> url="/api/markets">
132
+ {(markets, loading, error) => {
133
+ if (loading) return <Spinner />
134
+ if (error) return <Error error={error} />
135
+ return <MarketList markets={markets!} />
136
+ }}
137
+ </DataLoader>
138
+ ```
139
+
140
+ ## Custom Hooks Patterns
141
+
142
+ ### State Management Hook
143
+
144
+ ```typescript
145
+ export function useToggle(initialValue = false): [boolean, () => void] {
146
+ const [value, setValue] = useState(initialValue)
147
+
148
+ const toggle = useCallback(() => {
149
+ setValue(v => !v)
150
+ }, [])
151
+
152
+ return [value, toggle]
153
+ }
154
+
155
+ // Usage
156
+ const [isOpen, toggleOpen] = useToggle()
157
+ ```
158
+
159
+ ### Async Data Fetching Hook
160
+
161
+ ```typescript
162
+ interface UseQueryOptions<T> {
163
+ onSuccess?: (data: T) => void
164
+ onError?: (error: Error) => void
165
+ enabled?: boolean
166
+ }
167
+
168
+ export function useQuery<T>(
169
+ key: string,
170
+ fetcher: () => Promise<T>,
171
+ options?: UseQueryOptions<T>
172
+ ) {
173
+ const [data, setData] = useState<T | null>(null)
174
+ const [error, setError] = useState<Error | null>(null)
175
+ const [loading, setLoading] = useState(false)
176
+
177
+ const refetch = useCallback(async () => {
178
+ setLoading(true)
179
+ setError(null)
180
+
181
+ try {
182
+ const result = await fetcher()
183
+ setData(result)
184
+ options?.onSuccess?.(result)
185
+ } catch (err) {
186
+ const error = err as Error
187
+ setError(error)
188
+ options?.onError?.(error)
189
+ } finally {
190
+ setLoading(false)
191
+ }
192
+ }, [fetcher, options])
193
+
194
+ useEffect(() => {
195
+ if (options?.enabled !== false) {
196
+ refetch()
197
+ }
198
+ }, [key, refetch, options?.enabled])
199
+
200
+ return { data, error, loading, refetch }
201
+ }
202
+
203
+ // Usage
204
+ const { data: markets, loading, error, refetch } = useQuery(
205
+ 'markets',
206
+ () => fetch('/api/markets').then(r => r.json()),
207
+ {
208
+ onSuccess: data => console.log('Fetched', data.length, 'markets'),
209
+ onError: err => console.error('Failed:', err)
210
+ }
211
+ )
212
+ ```
213
+
214
+ ### Debounce Hook
215
+
216
+ ```typescript
217
+ export function useDebounce<T>(value: T, delay: number): T {
218
+ const [debouncedValue, setDebouncedValue] = useState<T>(value)
219
+
220
+ useEffect(() => {
221
+ const handler = setTimeout(() => {
222
+ setDebouncedValue(value)
223
+ }, delay)
224
+
225
+ return () => clearTimeout(handler)
226
+ }, [value, delay])
227
+
228
+ return debouncedValue
229
+ }
230
+
231
+ // Usage
232
+ const [searchQuery, setSearchQuery] = useState('')
233
+ const debouncedQuery = useDebounce(searchQuery, 500)
234
+
235
+ useEffect(() => {
236
+ if (debouncedQuery) {
237
+ performSearch(debouncedQuery)
238
+ }
239
+ }, [debouncedQuery])
240
+ ```
241
+
242
+ ## State Management Patterns
243
+
244
+ ### Context + Reducer Pattern
245
+
246
+ ```typescript
247
+ interface State {
248
+ markets: Market[]
249
+ selectedMarket: Market | null
250
+ loading: boolean
251
+ }
252
+
253
+ type Action =
254
+ | { type: 'SET_MARKETS'; payload: Market[] }
255
+ | { type: 'SELECT_MARKET'; payload: Market }
256
+ | { type: 'SET_LOADING'; payload: boolean }
257
+
258
+ function reducer(state: State, action: Action): State {
259
+ switch (action.type) {
260
+ case 'SET_MARKETS':
261
+ return { ...state, markets: action.payload }
262
+ case 'SELECT_MARKET':
263
+ return { ...state, selectedMarket: action.payload }
264
+ case 'SET_LOADING':
265
+ return { ...state, loading: action.payload }
266
+ default:
267
+ return state
268
+ }
269
+ }
270
+
271
+ const MarketContext = createContext<{
272
+ state: State
273
+ dispatch: Dispatch<Action>
274
+ } | undefined>(undefined)
275
+
276
+ export function MarketProvider({ children }: { children: React.ReactNode }) {
277
+ const [state, dispatch] = useReducer(reducer, {
278
+ markets: [],
279
+ selectedMarket: null,
280
+ loading: false
281
+ })
282
+
283
+ return (
284
+ <MarketContext.Provider value={{ state, dispatch }}>
285
+ {children}
286
+ </MarketContext.Provider>
287
+ )
288
+ }
289
+
290
+ export function useMarkets() {
291
+ const context = useContext(MarketContext)
292
+ if (!context) throw new Error('useMarkets must be used within MarketProvider')
293
+ return context
294
+ }
295
+ ```
296
+
297
+ ## Performance Optimization
298
+
299
+ ### Memoization
300
+
301
+ ```typescript
302
+ // PASS: useMemo for expensive computations
303
+ const sortedMarkets = useMemo(() => {
304
+ return markets.sort((a, b) => b.volume - a.volume)
305
+ }, [markets])
306
+
307
+ // PASS: useCallback for functions passed to children
308
+ const handleSearch = useCallback((query: string) => {
309
+ setSearchQuery(query)
310
+ }, [])
311
+
312
+ // PASS: React.memo for pure components
313
+ export const MarketCard = React.memo<MarketCardProps>(({ market }) => {
314
+ return (
315
+ <div className="market-card">
316
+ <h3>{market.name}</h3>
317
+ <p>{market.description}</p>
318
+ </div>
319
+ )
320
+ })
321
+ ```
322
+
323
+ ### Code Splitting & Lazy Loading
324
+
325
+ ```typescript
326
+ import { lazy, Suspense } from 'react'
327
+
328
+ // PASS: Lazy load heavy components
329
+ const HeavyChart = lazy(() => import('./HeavyChart'))
330
+ const ThreeJsBackground = lazy(() => import('./ThreeJsBackground'))
331
+
332
+ export function Dashboard() {
333
+ return (
334
+ <div>
335
+ <Suspense fallback={<ChartSkeleton />}>
336
+ <HeavyChart data={data} />
337
+ </Suspense>
338
+
339
+ <Suspense fallback={null}>
340
+ <ThreeJsBackground />
341
+ </Suspense>
342
+ </div>
343
+ )
344
+ }
345
+ ```
346
+
347
+ ### Virtualization for Long Lists
348
+
349
+ ```typescript
350
+ import { useVirtualizer } from '@tanstack/react-virtual'
351
+
352
+ export function VirtualMarketList({ markets }: { markets: Market[] }) {
353
+ const parentRef = useRef<HTMLDivElement>(null)
354
+
355
+ const virtualizer = useVirtualizer({
356
+ count: markets.length,
357
+ getScrollElement: () => parentRef.current,
358
+ estimateSize: () => 100, // Estimated row height
359
+ overscan: 5 // Extra items to render
360
+ })
361
+
362
+ return (
363
+ <div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
364
+ <div
365
+ style={{
366
+ height: `${virtualizer.getTotalSize()}px`,
367
+ position: 'relative'
368
+ }}
369
+ >
370
+ {virtualizer.getVirtualItems().map(virtualRow => (
371
+ <div
372
+ key={virtualRow.index}
373
+ style={{
374
+ position: 'absolute',
375
+ top: 0,
376
+ left: 0,
377
+ width: '100%',
378
+ height: `${virtualRow.size}px`,
379
+ transform: `translateY(${virtualRow.start}px)`
380
+ }}
381
+ >
382
+ <MarketCard market={markets[virtualRow.index]} />
383
+ </div>
384
+ ))}
385
+ </div>
386
+ </div>
387
+ )
388
+ }
389
+ ```
390
+
391
+ ## Form Handling Patterns
392
+
393
+ ### Controlled Form with Validation
394
+
395
+ ```typescript
396
+ interface FormData {
397
+ name: string
398
+ description: string
399
+ endDate: string
400
+ }
401
+
402
+ interface FormErrors {
403
+ name?: string
404
+ description?: string
405
+ endDate?: string
406
+ }
407
+
408
+ export function CreateMarketForm() {
409
+ const [formData, setFormData] = useState<FormData>({
410
+ name: '',
411
+ description: '',
412
+ endDate: ''
413
+ })
414
+
415
+ const [errors, setErrors] = useState<FormErrors>({})
416
+
417
+ const validate = (): boolean => {
418
+ const newErrors: FormErrors = {}
419
+
420
+ if (!formData.name.trim()) {
421
+ newErrors.name = 'Name is required'
422
+ } else if (formData.name.length > 200) {
423
+ newErrors.name = 'Name must be under 200 characters'
424
+ }
425
+
426
+ if (!formData.description.trim()) {
427
+ newErrors.description = 'Description is required'
428
+ }
429
+
430
+ if (!formData.endDate) {
431
+ newErrors.endDate = 'End date is required'
432
+ }
433
+
434
+ setErrors(newErrors)
435
+ return Object.keys(newErrors).length === 0
436
+ }
437
+
438
+ const handleSubmit = async (e: React.FormEvent) => {
439
+ e.preventDefault()
440
+
441
+ if (!validate()) return
442
+
443
+ try {
444
+ await createMarket(formData)
445
+ // Success handling
446
+ } catch (error) {
447
+ // Error handling
448
+ }
449
+ }
450
+
451
+ return (
452
+ <form onSubmit={handleSubmit}>
453
+ <input
454
+ value={formData.name}
455
+ onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}
456
+ placeholder="Market name"
457
+ />
458
+ {errors.name && <span className="error">{errors.name}</span>}
459
+
460
+ {/* Other fields */}
461
+
462
+ <button type="submit">Create Market</button>
463
+ </form>
464
+ )
465
+ }
466
+ ```
467
+
468
+ ## Error Boundary Pattern
469
+
470
+ ```typescript
471
+ interface ErrorBoundaryState {
472
+ hasError: boolean
473
+ error: Error | null
474
+ }
475
+
476
+ export class ErrorBoundary extends React.Component<
477
+ { children: React.ReactNode },
478
+ ErrorBoundaryState
479
+ > {
480
+ state: ErrorBoundaryState = {
481
+ hasError: false,
482
+ error: null
483
+ }
484
+
485
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState {
486
+ return { hasError: true, error }
487
+ }
488
+
489
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
490
+ console.error('Error boundary caught:', error, errorInfo)
491
+ }
492
+
493
+ render() {
494
+ if (this.state.hasError) {
495
+ return (
496
+ <div className="error-fallback">
497
+ <h2>Something went wrong</h2>
498
+ <p>{this.state.error?.message}</p>
499
+ <button onClick={() => this.setState({ hasError: false })}>
500
+ Try again
501
+ </button>
502
+ </div>
503
+ )
504
+ }
505
+
506
+ return this.props.children
507
+ }
508
+ }
509
+
510
+ // Usage
511
+ <ErrorBoundary>
512
+ <App />
513
+ </ErrorBoundary>
514
+ ```
515
+
516
+ ## Animation Patterns
517
+
518
+ ### Framer Motion Animations
519
+
520
+ ```typescript
521
+ import { motion, AnimatePresence } from 'framer-motion'
522
+
523
+ // PASS: List animations
524
+ export function AnimatedMarketList({ markets }: { markets: Market[] }) {
525
+ return (
526
+ <AnimatePresence>
527
+ {markets.map(market => (
528
+ <motion.div
529
+ key={market.id}
530
+ initial={{ opacity: 0, y: 20 }}
531
+ animate={{ opacity: 1, y: 0 }}
532
+ exit={{ opacity: 0, y: -20 }}
533
+ transition={{ duration: 0.3 }}
534
+ >
535
+ <MarketCard market={market} />
536
+ </motion.div>
537
+ ))}
538
+ </AnimatePresence>
539
+ )
540
+ }
541
+
542
+ // PASS: Modal animations
543
+ export function Modal({ isOpen, onClose, children }: ModalProps) {
544
+ return (
545
+ <AnimatePresence>
546
+ {isOpen && (
547
+ <>
548
+ <motion.div
549
+ className="modal-overlay"
550
+ initial={{ opacity: 0 }}
551
+ animate={{ opacity: 1 }}
552
+ exit={{ opacity: 0 }}
553
+ onClick={onClose}
554
+ />
555
+ <motion.div
556
+ className="modal-content"
557
+ initial={{ opacity: 0, scale: 0.9, y: 20 }}
558
+ animate={{ opacity: 1, scale: 1, y: 0 }}
559
+ exit={{ opacity: 0, scale: 0.9, y: 20 }}
560
+ >
561
+ {children}
562
+ </motion.div>
563
+ </>
564
+ )}
565
+ </AnimatePresence>
566
+ )
567
+ }
568
+ ```
569
+
570
+ ## Accessibility Patterns
571
+
572
+ ### Keyboard Navigation
573
+
574
+ ```typescript
575
+ export function Dropdown({ options, onSelect }: DropdownProps) {
576
+ const [isOpen, setIsOpen] = useState(false)
577
+ const [activeIndex, setActiveIndex] = useState(0)
578
+
579
+ const handleKeyDown = (e: React.KeyboardEvent) => {
580
+ switch (e.key) {
581
+ case 'ArrowDown':
582
+ e.preventDefault()
583
+ setActiveIndex(i => Math.min(i + 1, options.length - 1))
584
+ break
585
+ case 'ArrowUp':
586
+ e.preventDefault()
587
+ setActiveIndex(i => Math.max(i - 1, 0))
588
+ break
589
+ case 'Enter':
590
+ e.preventDefault()
591
+ onSelect(options[activeIndex])
592
+ setIsOpen(false)
593
+ break
594
+ case 'Escape':
595
+ setIsOpen(false)
596
+ break
597
+ }
598
+ }
599
+
600
+ return (
601
+ <div
602
+ role="combobox"
603
+ aria-expanded={isOpen}
604
+ aria-haspopup="listbox"
605
+ onKeyDown={handleKeyDown}
606
+ >
607
+ {/* Dropdown implementation */}
608
+ </div>
609
+ )
610
+ }
611
+ ```
612
+
613
+ ### Focus Management
614
+
615
+ ```typescript
616
+ export function Modal({ isOpen, onClose, children }: ModalProps) {
617
+ const modalRef = useRef<HTMLDivElement>(null)
618
+ const previousFocusRef = useRef<HTMLElement | null>(null)
619
+
620
+ useEffect(() => {
621
+ if (isOpen) {
622
+ // Save currently focused element
623
+ previousFocusRef.current = document.activeElement as HTMLElement
624
+
625
+ // Focus modal
626
+ modalRef.current?.focus()
627
+ } else {
628
+ // Restore focus when closing
629
+ previousFocusRef.current?.focus()
630
+ }
631
+ }, [isOpen])
632
+
633
+ return isOpen ? (
634
+ <div
635
+ ref={modalRef}
636
+ role="dialog"
637
+ aria-modal="true"
638
+ tabIndex={-1}
639
+ onKeyDown={e => e.key === 'Escape' && onClose()}
640
+ >
641
+ {children}
642
+ </div>
643
+ ) : null
644
+ }
645
+ ```
646
+
647
+ **Remember**: Modern frontend patterns enable maintainable, performant user interfaces. Choose patterns that fit your project complexity.
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: "Frontend Patterns"
3
+ short_description: "React and Next.js frontend patterns"
4
+ brand_color: "#8B5CF6"
5
+ default_prompt: "Use $frontend-patterns to apply React and Next.js frontend patterns."
6
+ policy:
7
+ allow_implicit_invocation: true