@nextsparkjs/ai-workflow 0.1.0-beta.86

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 (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/claude/_docs/workflows-optimizations.md +359 -0
  4. package/claude/agents/api-tester.md +636 -0
  5. package/claude/agents/architecture-supervisor.md +1381 -0
  6. package/claude/agents/backend-developer.md +1021 -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 +1460 -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 +1291 -0
  15. package/claude/agents/frontend-developer.md +1259 -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 +971 -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 +373 -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 +681 -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 +512 -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 +455 -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/close.md +146 -0
  77. package/claude/commands/session/commit.md +174 -0
  78. package/claude/commands/session/db-entity.md +206 -0
  79. package/claude/commands/session/db-fix.md +212 -0
  80. package/claude/commands/session/db-sample.md +206 -0
  81. package/claude/commands/session/demo.md +178 -0
  82. package/claude/commands/session/doc-bdd.md +207 -0
  83. package/claude/commands/session/doc-feature.md +218 -0
  84. package/claude/commands/session/doc-read.md +225 -0
  85. package/claude/commands/session/execute.md +204 -0
  86. package/claude/commands/session/explain.md +202 -0
  87. package/claude/commands/session/fix-bug.md +210 -0
  88. package/claude/commands/session/fix-build.md +182 -0
  89. package/claude/commands/session/fix-test.md +189 -0
  90. package/claude/commands/session/pending.md +232 -0
  91. package/claude/commands/session/refine.md +188 -0
  92. package/claude/commands/session/resume.md +192 -0
  93. package/claude/commands/session/review.md +192 -0
  94. package/claude/commands/session/scope-change.md +181 -0
  95. package/claude/commands/session/start-blocks.md +347 -0
  96. package/claude/commands/session/start.md +476 -0
  97. package/claude/commands/session/status.md +169 -0
  98. package/claude/commands/session/test-fix.md +221 -0
  99. package/claude/commands/session/test-run.md +203 -0
  100. package/claude/commands/session/test-write.md +242 -0
  101. package/claude/commands/session/validate.md +162 -0
  102. package/claude/config/context.json +54 -0
  103. package/claude/config/github.json +69 -0
  104. package/claude/config/github.schema.json +106 -0
  105. package/claude/config/team.json +46 -0
  106. package/claude/config/team.schema.json +106 -0
  107. package/claude/config/workspace.json +49 -0
  108. package/claude/config/workspace.schema.json +64 -0
  109. package/claude/scripts/.gitkeep +0 -0
  110. package/claude/sessions/.gitkeep +0 -0
  111. package/claude/skills/README.md +228 -0
  112. package/claude/skills/accessibility/SKILL.md +573 -0
  113. package/claude/skills/api-bypass-layers/SKILL.md +550 -0
  114. package/claude/skills/asana-integration/SKILL.md +499 -0
  115. package/claude/skills/better-auth/SKILL.md +666 -0
  116. package/claude/skills/billing-subscriptions/SKILL.md +660 -0
  117. package/claude/skills/block-decision-matrix/SKILL.md +359 -0
  118. package/claude/skills/clickup-integration/SKILL.md +434 -0
  119. package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
  120. package/claude/skills/create-plugin/SKILL.md +425 -0
  121. package/claude/skills/create-theme/SKILL.md +331 -0
  122. package/claude/skills/cypress-api/SKILL.md +511 -0
  123. package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
  124. package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
  125. package/claude/skills/cypress-e2e/SKILL.md +526 -0
  126. package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
  127. package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
  128. package/claude/skills/cypress-selectors/SKILL.md +309 -0
  129. package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
  130. package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
  131. package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
  132. package/claude/skills/database-migrations/SKILL.md +335 -0
  133. package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
  134. package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
  135. package/claude/skills/design-system/SKILL.md +682 -0
  136. package/claude/skills/documentation/SKILL.md +540 -0
  137. package/claude/skills/entity-api/SKILL.md +482 -0
  138. package/claude/skills/entity-system/SKILL.md +635 -0
  139. package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
  140. package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
  141. package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
  142. package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
  143. package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
  144. package/claude/skills/github/SKILL.md +467 -0
  145. package/claude/skills/i18n-nextintl/SKILL.md +302 -0
  146. package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
  147. package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
  148. package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
  149. package/claude/skills/impact-analysis/SKILL.md +203 -0
  150. package/claude/skills/jest-unit/SKILL.md +306 -0
  151. package/claude/skills/jest-unit/references/component-testing.md +371 -0
  152. package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
  153. package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
  154. package/claude/skills/jira-integration/SKILL.md +539 -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 +483 -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 +677 -0
  228. package/claude/skills/registry-system/SKILL.md +331 -0
  229. package/claude/skills/scheduled-actions/SKILL.md +431 -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 +479 -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 +34 -0
  270. package/scripts/setup.mjs +282 -0
  271. package/scripts/sync.mjs +209 -0
@@ -0,0 +1,677 @@
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 useEffect for data fetching
607
+ useEffect(() => {
608
+ fetch('/api/data').then(setData)
609
+ }, [])
610
+
611
+ // ✅ CORRECT: Use TanStack Query
612
+ const { data } = useQuery({ queryKey: ['data'], queryFn: fetchData })
613
+
614
+ // ❌ NEVER: Create objects/functions in render without memoization
615
+ <Button onClick={() => handleClick(id)} /> // New function each render
616
+
617
+ // ✅ CORRECT: Use useCallback for stable references
618
+ const handleButtonClick = useCallback(() => handleClick(id), [id])
619
+ <Button onClick={handleButtonClick} />
620
+
621
+ // ❌ NEVER: Access hooks conditionally
622
+ if (condition) {
623
+ const value = useContext(MyContext) // Breaks Rules of Hooks
624
+ }
625
+
626
+ // ✅ CORRECT: Always call hooks at top level
627
+ const value = useContext(MyContext)
628
+ if (condition) {
629
+ // use value
630
+ }
631
+
632
+ // ❌ NEVER: Forget 'use client' directive for client components
633
+ export function InteractiveComponent() {
634
+ const [state, setState] = useState() // Error: useState is not defined
635
+ }
636
+
637
+ // ✅ CORRECT: Add directive at top of file
638
+ 'use client'
639
+ export function InteractiveComponent() {
640
+ const [state, setState] = useState()
641
+ }
642
+
643
+ // ❌ NEVER: Use client-side hooks in Server Components
644
+ // app/page.tsx (Server Component)
645
+ export default function Page() {
646
+ const [count, setCount] = useState(0) // Error!
647
+ }
648
+
649
+ // ✅ CORRECT: Extract to Client Component
650
+ // app/page.tsx
651
+ import { Counter } from './Counter'
652
+ export default function Page() {
653
+ return <Counter /> // Client Component handles state
654
+ }
655
+ ```
656
+
657
+ ## Checklist
658
+
659
+ Before finalizing React component implementation:
660
+
661
+ - [ ] Correct component type (Server vs Client)
662
+ - [ ] 'use client' directive if using hooks
663
+ - [ ] TanStack Query for data fetching (not useEffect)
664
+ - [ ] Context with custom hook for state sharing
665
+ - [ ] Suspense boundaries for async operations
666
+ - [ ] Error boundaries for error handling
667
+ - [ ] useCallback for event handlers passed as props
668
+ - [ ] data-cy attributes on interactive elements
669
+ - [ ] Proper TypeScript types for props
670
+ - [ ] Loading states handled
671
+
672
+ ## Related Skills
673
+
674
+ - `tanstack-query` - Data fetching patterns
675
+ - `shadcn-components` - UI component patterns
676
+ - `accessibility` - ARIA and keyboard patterns
677
+ - `cypress-selectors` - Testing selectors