@nextsparkjs/ai-workflow 0.1.0-beta.100

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 (272) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/claude/_docs/workflows-optimizations.md +359 -0
  4. package/claude/agents/api-tester.md +634 -0
  5. package/claude/agents/architecture-supervisor.md +1351 -0
  6. package/claude/agents/backend-developer.md +997 -0
  7. package/claude/agents/backend-validator.md +417 -0
  8. package/claude/agents/bdd-docs-writer.md +737 -0
  9. package/claude/agents/block-developer.md +677 -0
  10. package/claude/agents/code-reviewer.md +1432 -0
  11. package/claude/agents/db-developer.md +721 -0
  12. package/claude/agents/db-validator.md +407 -0
  13. package/claude/agents/demo-video-generator.md +493 -0
  14. package/claude/agents/documentation-writer.md +1268 -0
  15. package/claude/agents/frontend-developer.md +1234 -0
  16. package/claude/agents/frontend-validator.md +777 -0
  17. package/claude/agents/functional-validator.md +630 -0
  18. package/claude/agents/mock-analyst.md +387 -0
  19. package/claude/agents/product-manager.md +963 -0
  20. package/claude/agents/qa-automation.md +1762 -0
  21. package/claude/agents/release-manager.md +634 -0
  22. package/claude/agents/selectors-translator.md +262 -0
  23. package/claude/agents/unit-test-writer.md +785 -0
  24. package/claude/agents/visual-comparator.md +329 -0
  25. package/claude/agents/workflow-maintainer.md +352 -0
  26. package/claude/commands/do/README.md +88 -0
  27. package/claude/commands/do/create-api.md +64 -0
  28. package/claude/commands/do/create-entity.md +66 -0
  29. package/claude/commands/do/create-migration.md +64 -0
  30. package/claude/commands/do/create-plugin.md +56 -0
  31. package/claude/commands/do/create-theme.md +70 -0
  32. package/claude/commands/do/mock-data.md +67 -0
  33. package/claude/commands/do/reset-db.md +71 -0
  34. package/claude/commands/do/setup-scheduled-action.md +75 -0
  35. package/claude/commands/do/sync-code-review.md +117 -0
  36. package/claude/commands/do/update-selectors.md +112 -0
  37. package/claude/commands/do/use-skills.md +90 -0
  38. package/claude/commands/do/validate-blocks.md +69 -0
  39. package/claude/commands/how-to/README.md +261 -0
  40. package/claude/commands/how-to/add-metadata.md +692 -0
  41. package/claude/commands/how-to/add-taxonomies.md +806 -0
  42. package/claude/commands/how-to/add-translations.md +571 -0
  43. package/claude/commands/how-to/create-api.md +577 -0
  44. package/claude/commands/how-to/create-block.md +575 -0
  45. package/claude/commands/how-to/create-child-entities.md +771 -0
  46. package/claude/commands/how-to/create-entity.md +597 -0
  47. package/claude/commands/how-to/create-migrations.md +605 -0
  48. package/claude/commands/how-to/create-plugin.md +654 -0
  49. package/claude/commands/how-to/customize-app.md +481 -0
  50. package/claude/commands/how-to/customize-dashboard.md +553 -0
  51. package/claude/commands/how-to/customize-theme.md +438 -0
  52. package/claude/commands/how-to/define-features-flows.md +632 -0
  53. package/claude/commands/how-to/deploy.md +507 -0
  54. package/claude/commands/how-to/handle-file-uploads.md +746 -0
  55. package/claude/commands/how-to/implement-search.md +1001 -0
  56. package/claude/commands/how-to/install-plugins.md +352 -0
  57. package/claude/commands/how-to/manage-test-coverage.md +984 -0
  58. package/claude/commands/how-to/run-tests.md +400 -0
  59. package/claude/commands/how-to/set-app-languages.md +601 -0
  60. package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
  61. package/claude/commands/how-to/set-scheduled-actions.md +527 -0
  62. package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
  63. package/claude/commands/how-to/setup-authentication.md +388 -0
  64. package/claude/commands/how-to/setup-claude-code.md +440 -0
  65. package/claude/commands/how-to/setup-database.md +274 -0
  66. package/claude/commands/how-to/setup-email-providers.md +598 -0
  67. package/claude/commands/how-to/setup-mobile-dev.md +627 -0
  68. package/claude/commands/how-to/start.md +500 -0
  69. package/claude/commands/how-to/use-devtools.md +639 -0
  70. package/claude/commands/how-to/use-superadmin.md +622 -0
  71. package/claude/commands/session/README.md +193 -0
  72. package/claude/commands/session/block-create.md +190 -0
  73. package/claude/commands/session/block-list.md +203 -0
  74. package/claude/commands/session/block-update.md +192 -0
  75. package/claude/commands/session/block-validate.md +218 -0
  76. package/claude/commands/session/changelog.md +115 -0
  77. package/claude/commands/session/close.md +225 -0
  78. package/claude/commands/session/commit.md +174 -0
  79. package/claude/commands/session/db-entity.md +206 -0
  80. package/claude/commands/session/db-fix.md +212 -0
  81. package/claude/commands/session/db-sample.md +206 -0
  82. package/claude/commands/session/demo.md +178 -0
  83. package/claude/commands/session/doc-bdd.md +207 -0
  84. package/claude/commands/session/doc-feature.md +218 -0
  85. package/claude/commands/session/doc-read.md +225 -0
  86. package/claude/commands/session/execute.md +204 -0
  87. package/claude/commands/session/explain.md +202 -0
  88. package/claude/commands/session/fix-bug.md +210 -0
  89. package/claude/commands/session/fix-build.md +182 -0
  90. package/claude/commands/session/fix-test.md +189 -0
  91. package/claude/commands/session/pending.md +232 -0
  92. package/claude/commands/session/refine.md +188 -0
  93. package/claude/commands/session/resume.md +192 -0
  94. package/claude/commands/session/review.md +192 -0
  95. package/claude/commands/session/scope-change.md +181 -0
  96. package/claude/commands/session/start-blocks.md +347 -0
  97. package/claude/commands/session/start.md +604 -0
  98. package/claude/commands/session/status.md +169 -0
  99. package/claude/commands/session/test-fix.md +221 -0
  100. package/claude/commands/session/test-run.md +203 -0
  101. package/claude/commands/session/test-write.md +242 -0
  102. package/claude/commands/session/validate.md +162 -0
  103. package/claude/config/context.json +40 -0
  104. package/claude/config/github.json +69 -0
  105. package/claude/config/github.schema.json +106 -0
  106. package/claude/config/team.json +46 -0
  107. package/claude/config/team.schema.json +106 -0
  108. package/claude/config/workspace.json +43 -0
  109. package/claude/config/workspace.schema.json +75 -0
  110. package/claude/skills/README.md +228 -0
  111. package/claude/skills/accessibility/SKILL.md +573 -0
  112. package/claude/skills/api-bypass-layers/SKILL.md +550 -0
  113. package/claude/skills/asana-integration/SKILL.md +499 -0
  114. package/claude/skills/better-auth/SKILL.md +666 -0
  115. package/claude/skills/billing-subscriptions/SKILL.md +660 -0
  116. package/claude/skills/block-decision-matrix/SKILL.md +359 -0
  117. package/claude/skills/clickup-integration/SKILL.md +434 -0
  118. package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
  119. package/claude/skills/create-plugin/SKILL.md +425 -0
  120. package/claude/skills/create-theme/SKILL.md +331 -0
  121. package/claude/skills/cypress-api/SKILL.md +511 -0
  122. package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
  123. package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
  124. package/claude/skills/cypress-e2e/SKILL.md +526 -0
  125. package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
  126. package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
  127. package/claude/skills/cypress-selectors/SKILL.md +309 -0
  128. package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
  129. package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
  130. package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
  131. package/claude/skills/database-migrations/SKILL.md +335 -0
  132. package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
  133. package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
  134. package/claude/skills/design-system/SKILL.md +682 -0
  135. package/claude/skills/documentation/SKILL.md +540 -0
  136. package/claude/skills/entity-api/SKILL.md +482 -0
  137. package/claude/skills/entity-system/SKILL.md +635 -0
  138. package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
  139. package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
  140. package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
  141. package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
  142. package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
  143. package/claude/skills/github/SKILL.md +467 -0
  144. package/claude/skills/i18n-nextintl/SKILL.md +302 -0
  145. package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
  146. package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
  147. package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
  148. package/claude/skills/impact-analysis/SKILL.md +203 -0
  149. package/claude/skills/jest-unit/SKILL.md +306 -0
  150. package/claude/skills/jest-unit/references/component-testing.md +371 -0
  151. package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
  152. package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
  153. package/claude/skills/jira-integration/SKILL.md +539 -0
  154. package/claude/skills/media-library/SKILL.md +743 -0
  155. package/claude/skills/mock-analysis/SKILL.md +276 -0
  156. package/claude/skills/monorepo-architecture/SKILL.md +162 -0
  157. package/claude/skills/nextjs-api-development/SKILL.md +364 -0
  158. package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
  159. package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
  160. package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
  161. package/claude/skills/notion-integration/SKILL.md +641 -0
  162. package/claude/skills/npm-development-workflow/SKILL.md +480 -0
  163. package/claude/skills/page-builder-blocks/SKILL.md +530 -0
  164. package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
  165. package/claude/skills/permissions-system/SKILL.md +619 -0
  166. package/claude/skills/plugins/SKILL.md +340 -0
  167. package/claude/skills/plugins/references/plugin-templates.md +414 -0
  168. package/claude/skills/plugins/references/plugin-testing.md +353 -0
  169. package/claude/skills/plugins/references/plugin-types.md +198 -0
  170. package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
  171. package/claude/skills/pom-patterns/SKILL.md +452 -0
  172. package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
  173. package/claude/skills/rate-limiting/SKILL.md +342 -0
  174. package/claude/skills/react-best-practices/AGENTS.md +2410 -0
  175. package/claude/skills/react-best-practices/README.md +123 -0
  176. package/claude/skills/react-best-practices/SKILL.md +125 -0
  177. package/claude/skills/react-best-practices/metadata.json +15 -0
  178. package/claude/skills/react-best-practices/rules/_sections.md +46 -0
  179. package/claude/skills/react-best-practices/rules/_template.md +28 -0
  180. package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  181. package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  182. package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  183. package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  184. package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  185. package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  186. package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  187. package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  188. package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  189. package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  190. package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  191. package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  192. package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  193. package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
  194. package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  195. package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  196. package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  197. package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  198. package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  199. package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  200. package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  201. package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  202. package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  203. package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  204. package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  205. package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  206. package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  207. package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  208. package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  209. package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  210. package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  211. package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  212. package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  213. package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  214. package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  215. package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  216. package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  217. package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  218. package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  219. package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  220. package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  221. package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  222. package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  223. package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  224. package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
  225. package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
  226. package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  227. package/claude/skills/react-patterns/SKILL.md +688 -0
  228. package/claude/skills/registry-system/SKILL.md +331 -0
  229. package/claude/skills/scheduled-actions/SKILL.md +671 -0
  230. package/claude/skills/scope-enforcement/SKILL.md +542 -0
  231. package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
  232. package/claude/skills/server-actions/SKILL.md +493 -0
  233. package/claude/skills/service-layer/SKILL.md +587 -0
  234. package/claude/skills/session-management/SKILL.md +266 -0
  235. package/claude/skills/session-management/scripts/create-session.py +166 -0
  236. package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
  237. package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
  238. package/claude/skills/session-management/scripts/session-archive.sh +87 -0
  239. package/claude/skills/session-management/scripts/session-close.sh +133 -0
  240. package/claude/skills/session-management/scripts/session-init.sh +225 -0
  241. package/claude/skills/session-management/scripts/session-list.sh +163 -0
  242. package/claude/skills/session-management/scripts/split-plan.sh +116 -0
  243. package/claude/skills/shadcn-components/SKILL.md +586 -0
  244. package/claude/skills/shadcn-theming/SKILL.md +446 -0
  245. package/claude/skills/suspense-loading/SKILL.md +280 -0
  246. package/claude/skills/tailwind-theming/SKILL.md +507 -0
  247. package/claude/skills/tanstack-query/SKILL.md +608 -0
  248. package/claude/skills/test-coverage/SKILL.md +239 -0
  249. package/claude/skills/web-design-guidelines/SKILL.md +39 -0
  250. package/claude/skills/zod-validation/SKILL.md +537 -0
  251. package/claude/templates/blocks/progress.md +86 -0
  252. package/claude/templates/iteration/changes.md +61 -0
  253. package/claude/templates/iteration/progress.md +55 -0
  254. package/claude/templates/log.md +31 -0
  255. package/claude/templates/story/context.md +77 -0
  256. package/claude/templates/story/pendings.md +37 -0
  257. package/claude/templates/story/plan.md +299 -0
  258. package/claude/templates/story/requirements.md +109 -0
  259. package/claude/templates/story/scope.json +10 -0
  260. package/claude/templates/story/tests.md +91 -0
  261. package/claude/templates/task/progress.md +58 -0
  262. package/claude/templates/task/requirements.md +54 -0
  263. package/claude/workflows/README.md +154 -0
  264. package/claude/workflows/blocks.md +614 -0
  265. package/claude/workflows/story.md +1207 -0
  266. package/claude/workflows/task.md +927 -0
  267. package/claude/workflows/tweak.md +527 -0
  268. package/cursor/.gitkeep +0 -0
  269. package/package.json +35 -0
  270. package/scripts/postinstall.mjs +198 -0
  271. package/scripts/setup.mjs +282 -0
  272. package/scripts/sync.mjs +209 -0
@@ -0,0 +1,688 @@
1
+ ---
2
+ name: react-patterns
3
+ description: |
4
+ Modern React patterns for this Next.js 15 application.
5
+ Covers Server/Client Components, Context API, TanStack Query, Suspense, Error Boundaries, and performance patterns.
6
+ Use this skill when implementing React components or understanding component architecture.
7
+ allowed-tools: Read, Glob, Grep
8
+ version: 1.0.0
9
+ ---
10
+
11
+ # React Patterns Skill
12
+
13
+ Patterns for working with React 19 and Next.js 15 App Router in this application.
14
+
15
+ ## Architecture Overview
16
+
17
+ ```
18
+ REACT COMPONENT ARCHITECTURE:
19
+
20
+ Server Components (Default):
21
+ ├── app/layout.tsx # Root layout with providers
22
+ ├── app/page.tsx # Pages (default server)
23
+ └── app/dashboard/layout.tsx # Nested layouts
24
+
25
+ Client Components ('use client'):
26
+ ├── core/components/ # Interactive UI components
27
+ ├── core/contexts/ # React Context providers
28
+ ├── core/hooks/ # Custom hooks
29
+ └── core/providers/ # Provider wrappers
30
+
31
+ Data Fetching Strategy:
32
+ ├── TanStack Query # Client-side data fetching
33
+ ├── Server Actions # Server mutations
34
+ └── Route Handlers # API endpoints
35
+ ```
36
+
37
+ ## When to Use This Skill
38
+
39
+ - Deciding between Server and Client Components
40
+ - Implementing Context API patterns
41
+ - Using TanStack Query for data fetching
42
+ - Adding Suspense boundaries
43
+ - Implementing error handling
44
+ - Performance optimization with useCallback/useMemo
45
+
46
+ ## Server Components vs Client Components
47
+
48
+ ### Server Components (Default)
49
+
50
+ All components in the `app/` directory are Server Components by default.
51
+
52
+ ```typescript
53
+ // app/layout.tsx - Server Component
54
+ export default async function RootLayout({
55
+ children,
56
+ }: {
57
+ children: React.ReactNode
58
+ }) {
59
+ // Can use async/await directly
60
+ const locale = await getUserLocale()
61
+ const messages = await getMessages({ locale })
62
+ const defaultTheme = await getDefaultThemeMode()
63
+
64
+ return (
65
+ <html lang={locale} suppressHydrationWarning>
66
+ <body>
67
+ {/* Wrap client components in providers */}
68
+ <NextIntlClientProvider messages={messages}>
69
+ <NextThemeProvider defaultTheme={defaultTheme}>
70
+ <QueryProvider>
71
+ <TeamProvider>
72
+ {children}
73
+ </TeamProvider>
74
+ </QueryProvider>
75
+ </NextThemeProvider>
76
+ </NextIntlClientProvider>
77
+ </body>
78
+ </html>
79
+ )
80
+ }
81
+ ```
82
+
83
+ **When to use Server Components:**
84
+ - Fetching data from database
85
+ - Accessing backend resources
86
+ - Keeping sensitive data on server
87
+ - Reducing client JavaScript bundle
88
+ - Pages that don't need interactivity
89
+
90
+ ### Client Components
91
+
92
+ Mark with `'use client'` directive at the top of the file.
93
+
94
+ ```typescript
95
+ 'use client'
96
+
97
+ import { useState, useCallback } from 'react'
98
+ import { useRouter } from 'next/navigation'
99
+ import { useAuth } from '@/core/hooks/useAuth'
100
+
101
+ export function LoginForm() {
102
+ const [error, setError] = useState<string | null>(null)
103
+ const { signIn } = useAuth()
104
+ const router = useRouter()
105
+
106
+ const handleSubmit = useCallback(async (data: LoginData) => {
107
+ try {
108
+ await signIn(data)
109
+ router.push('/dashboard')
110
+ } catch (err) {
111
+ setError(err instanceof Error ? err.message : 'Sign in failed')
112
+ }
113
+ }, [signIn, router])
114
+
115
+ return (
116
+ <form onSubmit={handleSubmit}>
117
+ {/* Form content */}
118
+ </form>
119
+ )
120
+ }
121
+ ```
122
+
123
+ **When to use Client Components:**
124
+ - Using React hooks (useState, useEffect, etc.)
125
+ - Adding event listeners (onClick, onChange, etc.)
126
+ - Using browser APIs
127
+ - Using third-party libraries that use hooks
128
+ - Components that need interactivity
129
+
130
+ ## Context API Pattern
131
+
132
+ ### Creating Context with Custom Hook
133
+
134
+ ```typescript
135
+ // core/contexts/TeamContext.tsx
136
+ 'use client'
137
+
138
+ import { createContext, useContext, useState, useCallback, ReactNode } from 'react'
139
+
140
+ interface TeamContextValue {
141
+ currentTeam: Team | null
142
+ userTeams: UserTeamMembership[]
143
+ isLoading: boolean
144
+ switchTeam: (teamId: string) => Promise<void>
145
+ refreshTeams: () => Promise<void>
146
+ }
147
+
148
+ const TeamContext = createContext<TeamContextValue | undefined>(undefined)
149
+
150
+ export function TeamProvider({ children }: { children: ReactNode }) {
151
+ const [currentTeam, setCurrentTeam] = useState<Team | null>(null)
152
+ const [userTeams, setUserTeams] = useState<UserTeamMembership[]>([])
153
+ const [isLoading, setIsLoading] = useState(true)
154
+
155
+ const switchTeam = useCallback(async (teamId: string) => {
156
+ // Implementation
157
+ }, [])
158
+
159
+ const refreshTeams = useCallback(async () => {
160
+ // Implementation
161
+ }, [])
162
+
163
+ return (
164
+ <TeamContext.Provider value={{
165
+ currentTeam,
166
+ userTeams,
167
+ isLoading,
168
+ switchTeam,
169
+ refreshTeams,
170
+ }}>
171
+ {children}
172
+ </TeamContext.Provider>
173
+ )
174
+ }
175
+
176
+ // Custom hook with error boundary
177
+ export function useTeamContext() {
178
+ const context = useContext(TeamContext)
179
+ if (context === undefined) {
180
+ throw new Error('useTeamContext must be used within TeamProvider')
181
+ }
182
+ return context
183
+ }
184
+ ```
185
+
186
+ ### Provider Nesting Pattern
187
+
188
+ ```typescript
189
+ // app/layout.tsx
190
+ <NextIntlClientProvider messages={messages}>
191
+ <NextThemeProvider>
192
+ <QueryProvider>
193
+ <TeamProvider>
194
+ <SubscriptionProvider>
195
+ {children}
196
+ </SubscriptionProvider>
197
+ </TeamProvider>
198
+ </QueryProvider>
199
+ </NextThemeProvider>
200
+ </NextIntlClientProvider>
201
+ ```
202
+
203
+ **Order matters:** Providers that depend on others must be nested inside them.
204
+
205
+ ## TanStack Query for Data Fetching
206
+
207
+ ### Provider Setup
208
+
209
+ ```typescript
210
+ // core/providers/query-provider.tsx
211
+ 'use client'
212
+
213
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
214
+ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
215
+ import { useState } from 'react'
216
+
217
+ export function QueryProvider({ children }: { children: React.ReactNode }) {
218
+ const [queryClient] = useState(
219
+ () => new QueryClient({
220
+ defaultOptions: {
221
+ queries: {
222
+ staleTime: 60 * 1000, // 1 minute
223
+ refetchOnWindowFocus: false,
224
+ },
225
+ },
226
+ })
227
+ )
228
+
229
+ return (
230
+ <QueryClientProvider client={queryClient}>
231
+ {children}
232
+ {process.env.NEXT_PUBLIC_RQ_DEVTOOLS === 'true' && (
233
+ <ReactQueryDevtools initialIsOpen={false} />
234
+ )}
235
+ </QueryClientProvider>
236
+ )
237
+ }
238
+ ```
239
+
240
+ ### Query Pattern
241
+
242
+ ```typescript
243
+ // ✅ CORRECT - Use TanStack Query for data fetching
244
+ import { useQuery } from '@tanstack/react-query'
245
+
246
+ function CustomerList() {
247
+ const { data, isLoading, error } = useQuery({
248
+ queryKey: ['customers'],
249
+ queryFn: () => fetch('/api/v1/customers').then(res => res.json()),
250
+ })
251
+
252
+ if (isLoading) return <Skeleton />
253
+ if (error) return <ErrorMessage error={error} />
254
+
255
+ return <DataTable data={data} />
256
+ }
257
+
258
+ // ❌ WRONG - Don't use useEffect for data fetching
259
+ function CustomerList() {
260
+ const [data, setData] = useState(null)
261
+ const [loading, setLoading] = useState(true)
262
+
263
+ useEffect(() => {
264
+ fetch('/api/v1/customers')
265
+ .then(res => res.json())
266
+ .then(setData)
267
+ .finally(() => setLoading(false))
268
+ }, [])
269
+ }
270
+ ```
271
+
272
+ ### Mutation Pattern
273
+
274
+ ```typescript
275
+ import { useMutation, useQueryClient } from '@tanstack/react-query'
276
+
277
+ function CreateCustomerForm() {
278
+ const queryClient = useQueryClient()
279
+
280
+ const mutation = useMutation({
281
+ mutationFn: (data: CreateCustomer) =>
282
+ fetch('/api/v1/customers', {
283
+ method: 'POST',
284
+ headers: { 'Content-Type': 'application/json' },
285
+ body: JSON.stringify(data),
286
+ }).then(res => res.json()),
287
+ onSuccess: () => {
288
+ // Invalidate queries to refetch
289
+ queryClient.invalidateQueries({ queryKey: ['customers'] })
290
+ },
291
+ })
292
+
293
+ return (
294
+ <form onSubmit={(e) => {
295
+ e.preventDefault()
296
+ mutation.mutate(formData)
297
+ }}>
298
+ {/* Form fields */}
299
+ </form>
300
+ )
301
+ }
302
+ ```
303
+
304
+ ## Suspense Boundaries
305
+
306
+ ### Basic Usage
307
+
308
+ ```typescript
309
+ import { Suspense } from 'react'
310
+
311
+ function DashboardLayout({ children }: { children: React.ReactNode }) {
312
+ return (
313
+ <div>
314
+ <Suspense fallback={<NavSkeleton />}>
315
+ <Navigation />
316
+ </Suspense>
317
+
318
+ <main>
319
+ <Suspense fallback={<ContentSkeleton />}>
320
+ {children}
321
+ </Suspense>
322
+ </main>
323
+ </div>
324
+ )
325
+ }
326
+ ```
327
+
328
+ ### With Async Components
329
+
330
+ ```typescript
331
+ // app/dashboard/layout.tsx
332
+ 'use client'
333
+
334
+ import { Suspense } from 'react'
335
+
336
+ function AuthMethodDetectorWrapper() {
337
+ useAuthMethodDetector() // Hook that reads URL params
338
+ return null
339
+ }
340
+
341
+ export default function DashboardLayout({ children }: { children: React.ReactNode }) {
342
+ return (
343
+ <>
344
+ {/* Wrap async detection in Suspense */}
345
+ <Suspense fallback={null}>
346
+ <AuthMethodDetectorWrapper />
347
+ </Suspense>
348
+
349
+ <div data-cy="dashboard-container">
350
+ {children}
351
+ </div>
352
+ </>
353
+ )
354
+ }
355
+ ```
356
+
357
+ ### Block Renderer with Suspense
358
+
359
+ ```typescript
360
+ // app/components/page-renderer.tsx
361
+ import { Suspense } from 'react'
362
+
363
+ function BlockSkeleton() {
364
+ return (
365
+ <div className="w-full py-12 px-4 animate-pulse">
366
+ <div className="h-8 bg-muted rounded w-1/3 mb-4" />
367
+ <div className="h-4 bg-muted rounded w-2/3" />
368
+ </div>
369
+ )
370
+ }
371
+
372
+ function BlockRenderer({ block }: { block: BlockInstance }) {
373
+ const BlockComponent = getBlockComponent(block.blockSlug)
374
+
375
+ return (
376
+ <Suspense fallback={<BlockSkeleton />}>
377
+ <BlockComponent {...block.props} />
378
+ </Suspense>
379
+ )
380
+ }
381
+ ```
382
+
383
+ ## Error Boundaries
384
+
385
+ ### Next.js Error Boundary
386
+
387
+ ```typescript
388
+ // app/dashboard/(main)/[entity]/error.tsx
389
+ 'use client'
390
+
391
+ import { useEffect } from 'react'
392
+ import { Button } from '@/core/components/ui/button'
393
+ import { AlertCircle } from 'lucide-react'
394
+
395
+ export default function EntityError({
396
+ error,
397
+ reset,
398
+ }: {
399
+ error: Error & { digest?: string }
400
+ reset: () => void
401
+ }) {
402
+ useEffect(() => {
403
+ console.error('Entity page error:', error)
404
+ }, [error])
405
+
406
+ return (
407
+ <div className="flex flex-col items-center justify-center min-h-[400px] gap-4 p-6">
408
+ <AlertCircle className="h-12 w-12 text-destructive" />
409
+ <h2 className="text-xl font-semibold">Something went wrong!</h2>
410
+ <p className="text-sm text-muted-foreground max-w-md text-center">
411
+ {error.message || 'An error occurred while loading this page.'}
412
+ </p>
413
+
414
+ <div className="flex items-center gap-2">
415
+ <Button variant="outline" onClick={() => window.history.back()}>
416
+ Go Back
417
+ </Button>
418
+ <Button onClick={() => reset()}>
419
+ Try Again
420
+ </Button>
421
+ </div>
422
+
423
+ {/* Development error details */}
424
+ {process.env.NODE_ENV === 'development' && error.stack && (
425
+ <details className="mt-4 p-4 bg-muted rounded-lg text-xs max-w-2xl w-full">
426
+ <summary className="cursor-pointer font-medium">Error Details</summary>
427
+ <pre className="mt-2 overflow-auto">{error.stack}</pre>
428
+ </details>
429
+ )}
430
+ </div>
431
+ )
432
+ }
433
+ ```
434
+
435
+ ### Custom Error Component
436
+
437
+ ```typescript
438
+ // Block error fallback
439
+ function BlockError({ blockSlug }: { blockSlug: string }) {
440
+ return (
441
+ <div className="w-full py-12 px-4 bg-destructive/10 border border-destructive/20 rounded">
442
+ <div className="max-w-7xl mx-auto text-center">
443
+ <p className="text-destructive">
444
+ Failed to load block: <code className="font-mono">{blockSlug}</code>
445
+ </p>
446
+ <p className="text-sm text-muted-foreground mt-2">
447
+ This block may not be available or there was an error rendering it.
448
+ </p>
449
+ </div>
450
+ </div>
451
+ )
452
+ }
453
+ ```
454
+
455
+ ## Performance Patterns
456
+
457
+ ### useCallback for Event Handlers
458
+
459
+ ```typescript
460
+ 'use client'
461
+
462
+ import { useCallback, useState } from 'react'
463
+
464
+ function ThemeToggle() {
465
+ const { setTheme, theme } = useTheme()
466
+ const { user } = useAuth()
467
+
468
+ // Memoize callback to prevent unnecessary re-renders
469
+ const handleThemeChange = useCallback(async (newTheme: string) => {
470
+ setTheme(newTheme)
471
+
472
+ // Persist preference if logged in
473
+ if (user?.id) {
474
+ try {
475
+ await fetch('/api/user/profile', {
476
+ method: 'PATCH',
477
+ headers: { 'Content-Type': 'application/json' },
478
+ body: JSON.stringify({
479
+ meta: { uiPreferences: { theme: newTheme } }
480
+ }),
481
+ })
482
+ } catch (error) {
483
+ console.error('Failed to save theme preference:', error)
484
+ }
485
+ }
486
+ }, [setTheme, user])
487
+
488
+ return (
489
+ <DropdownMenu>
490
+ <DropdownMenuItem onClick={() => handleThemeChange('light')}>
491
+ Light
492
+ </DropdownMenuItem>
493
+ <DropdownMenuItem onClick={() => handleThemeChange('dark')}>
494
+ Dark
495
+ </DropdownMenuItem>
496
+ </DropdownMenu>
497
+ )
498
+ }
499
+ ```
500
+
501
+ ### Avoiding Unnecessary Re-renders
502
+
503
+ ```typescript
504
+ // ✅ CORRECT - useState with initializer function
505
+ const [queryClient] = useState(() => new QueryClient())
506
+
507
+ // ❌ WRONG - Creates new instance on every render
508
+ const queryClient = new QueryClient()
509
+ ```
510
+
511
+ ## Custom Hooks Pattern
512
+
513
+ ### useAuth Hook
514
+
515
+ ```typescript
516
+ // core/hooks/useAuth.ts
517
+ 'use client'
518
+
519
+ import { useRouter } from 'next/navigation'
520
+ import { authClient } from '@/core/lib/auth-client'
521
+
522
+ export function useAuth() {
523
+ const router = useRouter()
524
+ const session = authClient.useSession()
525
+
526
+ const handleSignIn = async ({ email, password, redirectTo }: SignInParams) => {
527
+ const { data, error } = await authClient.signIn.email({ email, password })
528
+
529
+ if (error) {
530
+ throw new Error(error.message || 'Error signing in')
531
+ }
532
+
533
+ if (data) {
534
+ router.push(redirectTo || '/dashboard')
535
+ }
536
+
537
+ return data
538
+ }
539
+
540
+ const handleSignOut = async () => {
541
+ if (typeof window !== 'undefined') {
542
+ localStorage.removeItem('activeTeamId')
543
+ }
544
+ await authClient.signOut()
545
+ router.push('/login')
546
+ }
547
+
548
+ return {
549
+ user: session.data?.user,
550
+ session: session.data,
551
+ isLoading: session.isPending,
552
+ signIn: handleSignIn,
553
+ signOut: handleSignOut,
554
+ // ... other auth methods
555
+ }
556
+ }
557
+ ```
558
+
559
+ ## React 19 Patterns (Available but Not Used)
560
+
561
+ These patterns are documented in `.rules/components.md` but not currently used in the codebase:
562
+
563
+ ### use() Hook
564
+
565
+ ```typescript
566
+ // Pattern available in React 19
567
+ import { use } from 'react'
568
+
569
+ function TodoList({ todosPromise }: { todosPromise: Promise<Todo[]> }) {
570
+ const todos = use(todosPromise) // Suspends until resolved
571
+ return (
572
+ <ul>
573
+ {todos.map(todo => <li key={todo.id}>{todo.title}</li>)}
574
+ </ul>
575
+ )
576
+ }
577
+ ```
578
+
579
+ **Current approach:** Use TanStack Query instead.
580
+
581
+ ### useActionState
582
+
583
+ ```typescript
584
+ // Pattern available in React 19
585
+ import { useActionState } from 'react'
586
+
587
+ function LoginForm() {
588
+ const [state, formAction, isPending] = useActionState(loginAction, null)
589
+
590
+ return (
591
+ <form action={formAction}>
592
+ {state?.error && <p className="text-destructive">{state.error}</p>}
593
+ <input name="email" type="email" />
594
+ <input name="password" type="password" />
595
+ <button disabled={isPending}>Sign In</button>
596
+ </form>
597
+ )
598
+ }
599
+ ```
600
+
601
+ **Current approach:** Use React Hook Form with Zod validation.
602
+
603
+ ## Anti-Patterns
604
+
605
+ ```typescript
606
+ // ❌ NEVER: Use namespace import for React
607
+ import * as React from 'react'
608
+ React.useState()
609
+ React.useCallback()
610
+ React.memo()
611
+
612
+ // ✅ CORRECT: Use named imports (project convention)
613
+ import { useState, useCallback, memo } from 'react'
614
+ // For types: import { type MouseEvent, type DragEvent } from 'react'
615
+
616
+ // ❌ NEVER: Use useEffect for data fetching
617
+ useEffect(() => {
618
+ fetch('/api/data').then(setData)
619
+ }, [])
620
+
621
+ // ✅ CORRECT: Use TanStack Query
622
+ const { data } = useQuery({ queryKey: ['data'], queryFn: fetchData })
623
+
624
+ // ❌ NEVER: Create objects/functions in render without memoization
625
+ <Button onClick={() => handleClick(id)} /> // New function each render
626
+
627
+ // ✅ CORRECT: Use useCallback for stable references
628
+ const handleButtonClick = useCallback(() => handleClick(id), [id])
629
+ <Button onClick={handleButtonClick} />
630
+
631
+ // ❌ NEVER: Access hooks conditionally
632
+ if (condition) {
633
+ const value = useContext(MyContext) // Breaks Rules of Hooks
634
+ }
635
+
636
+ // ✅ CORRECT: Always call hooks at top level
637
+ const value = useContext(MyContext)
638
+ if (condition) {
639
+ // use value
640
+ }
641
+
642
+ // ❌ NEVER: Forget 'use client' directive for client components
643
+ export function InteractiveComponent() {
644
+ const [state, setState] = useState() // Error: useState is not defined
645
+ }
646
+
647
+ // ✅ CORRECT: Add directive at top of file
648
+ 'use client'
649
+ export function InteractiveComponent() {
650
+ const [state, setState] = useState()
651
+ }
652
+
653
+ // ❌ NEVER: Use client-side hooks in Server Components
654
+ // app/page.tsx (Server Component)
655
+ export default function Page() {
656
+ const [count, setCount] = useState(0) // Error!
657
+ }
658
+
659
+ // ✅ CORRECT: Extract to Client Component
660
+ // app/page.tsx
661
+ import { Counter } from './Counter'
662
+ export default function Page() {
663
+ return <Counter /> // Client Component handles state
664
+ }
665
+ ```
666
+
667
+ ## Checklist
668
+
669
+ Before finalizing React component implementation:
670
+
671
+ - [ ] Correct component type (Server vs Client)
672
+ - [ ] Named imports from 'react' (never `import * as React`)
673
+ - [ ] 'use client' directive if using hooks
674
+ - [ ] TanStack Query for data fetching (not useEffect)
675
+ - [ ] Context with custom hook for state sharing
676
+ - [ ] Suspense boundaries for async operations
677
+ - [ ] Error boundaries for error handling
678
+ - [ ] useCallback for event handlers passed as props
679
+ - [ ] data-cy attributes on interactive elements
680
+ - [ ] Proper TypeScript types for props
681
+ - [ ] Loading states handled
682
+
683
+ ## Related Skills
684
+
685
+ - `tanstack-query` - Data fetching patterns
686
+ - `shadcn-components` - UI component patterns
687
+ - `accessibility` - ARIA and keyboard patterns
688
+ - `cypress-selectors` - Testing selectors