@ggailabs/cli-context 0.5.6 → 1.0.1
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.
Potentially problematic release.
This version of @ggailabs/cli-context might be problematic. Click here for more details.
- package/README.md +25 -181
- package/dist/.context/docs/GENESIS_SYSTEM_PROMPT.md +62 -0
- package/dist/.context/eng/agents/architect.md +15 -0
- package/dist/.context/eng/agents/backend_typescript.md +1000 -0
- package/dist/.context/eng/agents/bug_hunter.md +49 -0
- package/dist/.context/eng/agents/code_reviewer.md +313 -0
- package/dist/.context/eng/agents/devops_specialist.md +718 -0
- package/dist/.context/eng/agents/frontend_specialist.md +1027 -0
- package/dist/.context/eng/agents/qa_specialist.md +1234 -0
- package/dist/.context/eng/agents/security_reviewer.md +382 -0
- package/dist/.context/eng/agents/ui_specialist.md +16 -0
- package/dist/.context/eng/docs/AGENT_HANDOFF_PROMPT.md +44 -0
- package/dist/.context/eng/docs/GENESIS_DESIGN_SYSTEM.md +15 -0
- package/dist/.context/eng/docs/GG_METHODOLOGY.md +48 -0
- package/dist/.context/eng/docs/OPERATIONS_LOG.md +30 -0
- package/dist/.context/eng/docs/PROJECT_MAP.md +35 -0
- package/dist/.context/eng/docs/standards/devops.md +0 -0
- package/dist/.context/eng/docs/standards/frontend.md +0 -0
- package/dist/.context/eng/docs/standards/typescript.md +12 -0
- package/dist/.context/eng/skills/agent_logging.md +18 -0
- package/dist/.context/eng/skills/brainstorming.md +227 -0
- package/dist/.context/eng/skills/exploring_codebase.md +1217 -0
- package/dist/.context/eng/skills/patterns/compliance_check.md +246 -0
- package/dist/.context/eng/skills/patterns/coverage_table.md +401 -0
- package/dist/.context/eng/skills/patterns/exit_criteria.md +31 -0
- package/dist/.context/eng/skills/patterns/failure_recovery.md +74 -0
- package/dist/.context/eng/skills/patterns/quality_gate.md +295 -0
- package/dist/.context/eng/skills/patterns/standards_workflow.md +391 -0
- package/dist/.context/eng/skills/patterns/state_tracking.md +30 -0
- package/dist/.context/eng/skills/patterns/task_tracking.md +38 -0
- package/dist/.context/eng/skills/previce.md +45 -0
- package/dist/.context/eng/skills/tdd.md +421 -0
- package/dist/.context/eng/skills/writing_plans.md +105 -0
- package/dist/.context/plans/.gitkeep +0 -0
- package/dist/.context/pt-br/agents/architect.md +69 -0
- package/dist/.context/pt-br/agents/backend_typescript.md +1000 -0
- package/dist/.context/pt-br/agents/bug_hunter.md +49 -0
- package/dist/.context/pt-br/agents/code_reviewer.md +313 -0
- package/dist/.context/pt-br/agents/devops_specialist.md +718 -0
- package/dist/.context/pt-br/agents/frontend_specialist.md +1027 -0
- package/dist/.context/pt-br/agents/qa_specialist.md +1234 -0
- package/dist/.context/pt-br/agents/security_reviewer.md +382 -0
- package/dist/.context/pt-br/agents/ui_specialist.md +55 -0
- package/dist/.context/pt-br/docs/AGENT_HANDOFF_PROMPT.md +44 -0
- package/dist/.context/pt-br/docs/GENESIS_DESIGN_SYSTEM.md +88 -0
- package/dist/.context/pt-br/docs/GG_METHODOLOGY.md +48 -0
- package/dist/.context/pt-br/docs/OPERATIONS_LOG.md +30 -0
- package/dist/.context/pt-br/docs/PROJECT_MAP.md +37 -0
- package/dist/.context/pt-br/docs/standards/devops.md +707 -0
- package/dist/.context/pt-br/docs/standards/frontend.md +748 -0
- package/dist/.context/pt-br/docs/standards/typescript.md +1150 -0
- package/dist/.context/pt-br/skills/agent_logging.md +36 -0
- package/dist/.context/pt-br/skills/brainstorming.md +227 -0
- package/dist/.context/pt-br/skills/exploring_codebase.md +1217 -0
- package/dist/.context/pt-br/skills/patterns/compliance_check.md +246 -0
- package/dist/.context/pt-br/skills/patterns/coverage_table.md +401 -0
- package/dist/.context/pt-br/skills/patterns/exit_criteria.md +31 -0
- package/dist/.context/pt-br/skills/patterns/failure_recovery.md +74 -0
- package/dist/.context/pt-br/skills/patterns/quality_gate.md +295 -0
- package/dist/.context/pt-br/skills/patterns/standards_workflow.md +391 -0
- package/dist/.context/pt-br/skills/patterns/state_tracking.md +30 -0
- package/dist/.context/pt-br/skills/patterns/task_tracking.md +38 -0
- package/dist/.context/pt-br/skills/previce.md +45 -0
- package/dist/.context/pt-br/skills/tdd.md +421 -0
- package/dist/.context/pt-br/skills/writing_plans.md +105 -0
- package/dist/.context/workflow/.gitkeep +0 -0
- package/dist/commands/init.js +140 -0
- package/dist/commands/monitor.js +34 -0
- package/dist/index.js +20 -568
- package/dist/services/monitor-service.js +340 -0
- package/dist/services/scaffolder.js +164 -0
- package/package.json +16 -58
- package/LICENSE +0 -21
- package/dist/generators/agents/agentConfig.d.ts +0 -4
- package/dist/generators/agents/agentConfig.d.ts.map +0 -1
- package/dist/generators/agents/agentConfig.js +0 -180
- package/dist/generators/agents/agentConfig.js.map +0 -1
- package/dist/generators/agents/agentGenerator.d.ts +0 -9
- package/dist/generators/agents/agentGenerator.d.ts.map +0 -1
- package/dist/generators/agents/agentGenerator.js +0 -97
- package/dist/generators/agents/agentGenerator.js.map +0 -1
- package/dist/generators/agents/agentTypes.d.ts +0 -4
- package/dist/generators/agents/agentTypes.d.ts.map +0 -1
- package/dist/generators/agents/agentTypes.js +0 -25
- package/dist/generators/agents/agentTypes.js.map +0 -1
- package/dist/generators/agents/index.d.ts +0 -4
- package/dist/generators/agents/index.d.ts.map +0 -1
- package/dist/generators/agents/index.js +0 -12
- package/dist/generators/agents/index.js.map +0 -1
- package/dist/generators/agents/templates/index.d.ts +0 -4
- package/dist/generators/agents/templates/index.d.ts.map +0 -1
- package/dist/generators/agents/templates/index.js +0 -8
- package/dist/generators/agents/templates/index.js.map +0 -1
- package/dist/generators/agents/templates/indexTemplate.d.ts +0 -3
- package/dist/generators/agents/templates/indexTemplate.d.ts.map +0 -1
- package/dist/generators/agents/templates/indexTemplate.js +0 -36
- package/dist/generators/agents/templates/indexTemplate.js.map +0 -1
- package/dist/generators/agents/templates/playbookTemplate.d.ts +0 -4
- package/dist/generators/agents/templates/playbookTemplate.d.ts.map +0 -1
- package/dist/generators/agents/templates/playbookTemplate.js +0 -99
- package/dist/generators/agents/templates/playbookTemplate.js.map +0 -1
- package/dist/generators/agents/templates/types.d.ts +0 -14
- package/dist/generators/agents/templates/types.d.ts.map +0 -1
- package/dist/generators/agents/templates/types.js +0 -3
- package/dist/generators/agents/templates/types.js.map +0 -1
- package/dist/generators/documentation/documentationGenerator.d.ts +0 -15
- package/dist/generators/documentation/documentationGenerator.d.ts.map +0 -1
- package/dist/generators/documentation/documentationGenerator.js +0 -188
- package/dist/generators/documentation/documentationGenerator.js.map +0 -1
- package/dist/generators/documentation/guideRegistry.d.ts +0 -6
- package/dist/generators/documentation/guideRegistry.d.ts.map +0 -1
- package/dist/generators/documentation/guideRegistry.js +0 -82
- package/dist/generators/documentation/guideRegistry.js.map +0 -1
- package/dist/generators/documentation/index.d.ts +0 -2
- package/dist/generators/documentation/index.d.ts.map +0 -1
- package/dist/generators/documentation/index.js +0 -6
- package/dist/generators/documentation/index.js.map +0 -1
- package/dist/generators/documentation/templates/apiReferenceTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/apiReferenceTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/apiReferenceTemplate.js +0 -490
- package/dist/generators/documentation/templates/apiReferenceTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/architectureTemplate.d.ts +0 -3
- package/dist/generators/documentation/templates/architectureTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/architectureTemplate.js +0 -66
- package/dist/generators/documentation/templates/architectureTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/common.d.ts +0 -7
- package/dist/generators/documentation/templates/common.d.ts.map +0 -1
- package/dist/generators/documentation/templates/common.js +0 -58
- package/dist/generators/documentation/templates/common.js.map +0 -1
- package/dist/generators/documentation/templates/dataFlowTemplate.d.ts +0 -3
- package/dist/generators/documentation/templates/dataFlowTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/dataFlowTemplate.js +0 -40
- package/dist/generators/documentation/templates/dataFlowTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/developmentWorkflowTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/developmentWorkflowTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/developmentWorkflowTemplate.js +0 -44
- package/dist/generators/documentation/templates/developmentWorkflowTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/glossaryTemplate.d.ts +0 -3
- package/dist/generators/documentation/templates/glossaryTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/glossaryTemplate.js +0 -41
- package/dist/generators/documentation/templates/glossaryTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/index.d.ts +0 -15
- package/dist/generators/documentation/templates/index.d.ts.map +0 -1
- package/dist/generators/documentation/templates/index.js +0 -30
- package/dist/generators/documentation/templates/index.js.map +0 -1
- package/dist/generators/documentation/templates/indexTemplate.d.ts +0 -3
- package/dist/generators/documentation/templates/indexTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/indexTemplate.js +0 -42
- package/dist/generators/documentation/templates/indexTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/migrationTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/migrationTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/migrationTemplate.js +0 -422
- package/dist/generators/documentation/templates/migrationTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/onboardingTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/onboardingTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/onboardingTemplate.js +0 -431
- package/dist/generators/documentation/templates/onboardingTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/projectOverviewTemplate.d.ts +0 -3
- package/dist/generators/documentation/templates/projectOverviewTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/projectOverviewTemplate.js +0 -65
- package/dist/generators/documentation/templates/projectOverviewTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/securityTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/securityTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/securityTemplate.js +0 -39
- package/dist/generators/documentation/templates/securityTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/testingTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/testingTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/testingTemplate.js +0 -45
- package/dist/generators/documentation/templates/testingTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/toolingTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/toolingTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/toolingTemplate.js +0 -42
- package/dist/generators/documentation/templates/toolingTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/troubleshootingTemplate.d.ts +0 -2
- package/dist/generators/documentation/templates/troubleshootingTemplate.d.ts.map +0 -1
- package/dist/generators/documentation/templates/troubleshootingTemplate.js +0 -292
- package/dist/generators/documentation/templates/troubleshootingTemplate.js.map +0 -1
- package/dist/generators/documentation/templates/types.d.ts +0 -23
- package/dist/generators/documentation/templates/types.d.ts.map +0 -1
- package/dist/generators/documentation/templates/types.js +0 -3
- package/dist/generators/documentation/templates/types.js.map +0 -1
- package/dist/generators/plans/index.d.ts +0 -2
- package/dist/generators/plans/index.d.ts.map +0 -1
- package/dist/generators/plans/index.js +0 -6
- package/dist/generators/plans/index.js.map +0 -1
- package/dist/generators/plans/planGenerator.d.ts +0 -22
- package/dist/generators/plans/planGenerator.d.ts.map +0 -1
- package/dist/generators/plans/planGenerator.js +0 -109
- package/dist/generators/plans/planGenerator.js.map +0 -1
- package/dist/generators/plans/templates/indexTemplate.d.ts +0 -3
- package/dist/generators/plans/templates/indexTemplate.d.ts.map +0 -1
- package/dist/generators/plans/templates/indexTemplate.js +0 -37
- package/dist/generators/plans/templates/indexTemplate.js.map +0 -1
- package/dist/generators/plans/templates/planTemplate.d.ts +0 -3
- package/dist/generators/plans/templates/planTemplate.d.ts.map +0 -1
- package/dist/generators/plans/templates/planTemplate.js +0 -166
- package/dist/generators/plans/templates/planTemplate.js.map +0 -1
- package/dist/generators/plans/templates/types.d.ts +0 -19
- package/dist/generators/plans/templates/types.d.ts.map +0 -1
- package/dist/generators/plans/templates/types.js +0 -3
- package/dist/generators/plans/templates/types.js.map +0 -1
- package/dist/generators/shared/contextGenerator.d.ts +0 -7
- package/dist/generators/shared/contextGenerator.d.ts.map +0 -1
- package/dist/generators/shared/contextGenerator.js +0 -13
- package/dist/generators/shared/contextGenerator.js.map +0 -1
- package/dist/generators/shared/directoryTemplateHelpers.d.ts +0 -2
- package/dist/generators/shared/directoryTemplateHelpers.d.ts.map +0 -1
- package/dist/generators/shared/directoryTemplateHelpers.js +0 -12
- package/dist/generators/shared/directoryTemplateHelpers.js.map +0 -1
- package/dist/generators/shared/generatorUtils.d.ts +0 -16
- package/dist/generators/shared/generatorUtils.d.ts.map +0 -1
- package/dist/generators/shared/generatorUtils.js +0 -119
- package/dist/generators/shared/generatorUtils.js.map +0 -1
- package/dist/generators/shared/index.d.ts +0 -4
- package/dist/generators/shared/index.d.ts.map +0 -1
- package/dist/generators/shared/index.js +0 -10
- package/dist/generators/shared/index.js.map +0 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/prompts/defaults.d.ts +0 -3
- package/dist/prompts/defaults.d.ts.map +0 -1
- package/dist/prompts/defaults.js +0 -95
- package/dist/prompts/defaults.js.map +0 -1
- package/dist/services/baseLLMClient.d.ts +0 -12
- package/dist/services/baseLLMClient.d.ts.map +0 -1
- package/dist/services/baseLLMClient.js +0 -80
- package/dist/services/baseLLMClient.js.map +0 -1
- package/dist/services/fill/fillService.d.ts +0 -46
- package/dist/services/fill/fillService.d.ts.map +0 -1
- package/dist/services/fill/fillService.js +0 -254
- package/dist/services/fill/fillService.js.map +0 -1
- package/dist/services/init/initService.d.ts +0 -37
- package/dist/services/init/initService.d.ts.map +0 -1
- package/dist/services/init/initService.js +0 -167
- package/dist/services/init/initService.js.map +0 -1
- package/dist/services/llmClientFactory.d.ts +0 -8
- package/dist/services/llmClientFactory.d.ts.map +0 -1
- package/dist/services/llmClientFactory.js +0 -23
- package/dist/services/llmClientFactory.js.map +0 -1
- package/dist/services/openRouterClient.d.ts +0 -9
- package/dist/services/openRouterClient.d.ts.map +0 -1
- package/dist/services/openRouterClient.js +0 -49
- package/dist/services/openRouterClient.js.map +0 -1
- package/dist/services/plan/planService.d.ts +0 -57
- package/dist/services/plan/planService.d.ts.map +0 -1
- package/dist/services/plan/planService.js +0 -334
- package/dist/services/plan/planService.js.map +0 -1
- package/dist/services/shared/llmConfig.d.ts +0 -22
- package/dist/services/shared/llmConfig.d.ts.map +0 -1
- package/dist/services/shared/llmConfig.js +0 -38
- package/dist/services/shared/llmConfig.js.map +0 -1
- package/dist/types.d.ts +0 -65
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/utils/cliUI.d.ts +0 -27
- package/dist/utils/cliUI.d.ts.map +0 -1
- package/dist/utils/cliUI.js +0 -252
- package/dist/utils/cliUI.js.map +0 -1
- package/dist/utils/fileMapper.d.ts +0 -11
- package/dist/utils/fileMapper.d.ts.map +0 -1
- package/dist/utils/fileMapper.js +0 -146
- package/dist/utils/fileMapper.js.map +0 -1
- package/dist/utils/gitService.d.ts +0 -50
- package/dist/utils/gitService.d.ts.map +0 -1
- package/dist/utils/gitService.js +0 -470
- package/dist/utils/gitService.js.map +0 -1
- package/dist/utils/i18n.d.ts +0 -171
- package/dist/utils/i18n.d.ts.map +0 -1
- package/dist/utils/i18n.js +0 -381
- package/dist/utils/i18n.js.map +0 -1
- package/dist/utils/promptLoader.d.ts +0 -12
- package/dist/utils/promptLoader.d.ts.map +0 -1
- package/dist/utils/promptLoader.js +0 -81
- package/dist/utils/promptLoader.js.map +0 -1
- package/dist/utils/versionChecker.d.ts +0 -15
- package/dist/utils/versionChecker.d.ts.map +0 -1
- package/dist/utils/versionChecker.js +0 -49
- package/dist/utils/versionChecker.js.map +0 -1
- package/prompts/update_plan_prompt.md +0 -41
- package/prompts/update_scaffold_prompt.md +0 -47
|
@@ -0,0 +1,748 @@
|
|
|
1
|
+
# Frontend Standards
|
|
2
|
+
|
|
3
|
+
> **⚠️ MAINTENANCE:** This file is indexed in `dev-team/skills/shared-patterns/standards-coverage-table.md`.
|
|
4
|
+
> When adding/removing `## ` sections, follow FOUR-FILE UPDATE RULE in CLAUDE.md: (1) edit standards file, (2) update TOC, (3) update standards-coverage-table.md, (4) update agent file.
|
|
5
|
+
|
|
6
|
+
This file defines the specific standards for frontend development.
|
|
7
|
+
|
|
8
|
+
> **Reference**: Always consult `docs/PROJECT_RULES.md` for common project standards.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
| # | Section | Description |
|
|
15
|
+
|---|---------|-------------|
|
|
16
|
+
| 1 | [Framework](#framework) | React 18+, Next.js 14+ |
|
|
17
|
+
| 2 | [Libraries & Tools](#libraries--tools) | Core, state, forms, UI, styling, testing |
|
|
18
|
+
| 3 | [State Management Patterns](#state-management-patterns) | TanStack Query, Zustand |
|
|
19
|
+
| 4 | [Form Patterns](#form-patterns) | React Hook Form + Zod |
|
|
20
|
+
| 5 | [Styling Standards](#styling-standards) | TailwindCSS, CSS variables |
|
|
21
|
+
| 6 | [Typography Standards](#typography-standards) | Font selection and pairing |
|
|
22
|
+
| 7 | [Animation Standards](#animation-standards) | CSS transitions, Framer Motion |
|
|
23
|
+
| 8 | [Component Patterns](#component-patterns) | Compound components, error boundaries |
|
|
24
|
+
| 9 | [Accessibility](#accessibility) | WCAG 2.1 AA compliance |
|
|
25
|
+
| 10 | [Performance](#performance) | Code splitting, image optimization |
|
|
26
|
+
| 11 | [Directory Structure](#directory-structure) | Next.js App Router layout |
|
|
27
|
+
| 12 | [Forbidden Patterns](#forbidden-patterns) | Anti-patterns to avoid |
|
|
28
|
+
| 13 | [Standards Compliance Categories](#standards-compliance-categories) | Categories for ring:dev-refactor |
|
|
29
|
+
|
|
30
|
+
**Meta-sections (not checked by agents):**
|
|
31
|
+
- [Checklist](#checklist) - Self-verification before submitting code
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Framework
|
|
36
|
+
|
|
37
|
+
- React 18+ / Next.js 14+
|
|
38
|
+
- TypeScript strict mode (see `typescript.md`)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Libraries & Tools
|
|
43
|
+
|
|
44
|
+
### Core
|
|
45
|
+
|
|
46
|
+
| Library | Use Case |
|
|
47
|
+
|---------|----------|
|
|
48
|
+
| React 18+ | UI framework |
|
|
49
|
+
| Next.js 14+ | Full-stack framework |
|
|
50
|
+
| TypeScript 5+ | Type safety |
|
|
51
|
+
|
|
52
|
+
### State Management
|
|
53
|
+
|
|
54
|
+
| Library | Use Case |
|
|
55
|
+
|---------|----------|
|
|
56
|
+
| TanStack Query | Server state (API data) |
|
|
57
|
+
| Zustand | Client state (UI state) |
|
|
58
|
+
| Context API | Simple shared state |
|
|
59
|
+
| Redux Toolkit | Complex global state |
|
|
60
|
+
|
|
61
|
+
### Forms
|
|
62
|
+
|
|
63
|
+
| Library | Use Case |
|
|
64
|
+
|---------|----------|
|
|
65
|
+
| React Hook Form | Form state management |
|
|
66
|
+
| Zod | Schema validation |
|
|
67
|
+
| @hookform/resolvers | RHF + Zod integration |
|
|
68
|
+
|
|
69
|
+
### UI Components
|
|
70
|
+
|
|
71
|
+
| Library | Use Case |
|
|
72
|
+
|---------|----------|
|
|
73
|
+
| Radix UI | Headless primitives |
|
|
74
|
+
| shadcn/ui | Pre-styled Radix components |
|
|
75
|
+
| Chakra UI | Full component library |
|
|
76
|
+
| Headless UI | Tailwind-native primitives |
|
|
77
|
+
|
|
78
|
+
### Styling
|
|
79
|
+
|
|
80
|
+
| Library | Use Case |
|
|
81
|
+
|---------|----------|
|
|
82
|
+
| TailwindCSS | Utility-first CSS |
|
|
83
|
+
| CSS Modules | Scoped CSS |
|
|
84
|
+
| Styled Components | CSS-in-JS |
|
|
85
|
+
| CSS Variables | Theming |
|
|
86
|
+
|
|
87
|
+
### Testing
|
|
88
|
+
|
|
89
|
+
| Library | Use Case |
|
|
90
|
+
|---------|----------|
|
|
91
|
+
| Vitest | Unit tests |
|
|
92
|
+
| Testing Library | Component tests |
|
|
93
|
+
| Playwright | E2E tests |
|
|
94
|
+
| MSW | API mocking |
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## State Management Patterns
|
|
99
|
+
|
|
100
|
+
### Server State with TanStack Query
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
104
|
+
|
|
105
|
+
// Query key factory
|
|
106
|
+
const userKeys = {
|
|
107
|
+
all: ['users'] as const,
|
|
108
|
+
lists: () => [...userKeys.all, 'list'] as const,
|
|
109
|
+
list: (filters: UserFilters) => [...userKeys.lists(), filters] as const,
|
|
110
|
+
details: () => [...userKeys.all, 'detail'] as const,
|
|
111
|
+
detail: (id: string) => [...userKeys.details(), id] as const,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Typed query hook
|
|
115
|
+
function useUser(userId: string) {
|
|
116
|
+
return useQuery({
|
|
117
|
+
queryKey: userKeys.detail(userId),
|
|
118
|
+
queryFn: () => fetchUser(userId),
|
|
119
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Mutation with cache update
|
|
124
|
+
function useCreateUser() {
|
|
125
|
+
const queryClient = useQueryClient();
|
|
126
|
+
|
|
127
|
+
return useMutation({
|
|
128
|
+
mutationFn: createUser,
|
|
129
|
+
onSuccess: (newUser) => {
|
|
130
|
+
// Update cache
|
|
131
|
+
queryClient.setQueryData(
|
|
132
|
+
userKeys.detail(newUser.id),
|
|
133
|
+
newUser
|
|
134
|
+
);
|
|
135
|
+
// Invalidate list
|
|
136
|
+
queryClient.invalidateQueries({
|
|
137
|
+
queryKey: userKeys.lists(),
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Client State with Zustand
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { create } from 'zustand';
|
|
148
|
+
import { persist } from 'zustand/middleware';
|
|
149
|
+
|
|
150
|
+
interface UIState {
|
|
151
|
+
theme: 'light' | 'dark';
|
|
152
|
+
sidebarOpen: boolean;
|
|
153
|
+
setTheme: (theme: 'light' | 'dark') => void;
|
|
154
|
+
toggleSidebar: () => void;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const useUIStore = create<UIState>()(
|
|
158
|
+
persist(
|
|
159
|
+
(set) => ({
|
|
160
|
+
theme: 'light',
|
|
161
|
+
sidebarOpen: true,
|
|
162
|
+
setTheme: (theme) => set({ theme }),
|
|
163
|
+
toggleSidebar: () => set((state) => ({
|
|
164
|
+
sidebarOpen: !state.sidebarOpen
|
|
165
|
+
})),
|
|
166
|
+
}),
|
|
167
|
+
{ name: 'ui-storage' }
|
|
168
|
+
)
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Usage in component
|
|
172
|
+
function Header() {
|
|
173
|
+
const { theme, setTheme } = useUIStore();
|
|
174
|
+
return <ThemeToggle theme={theme} onChange={setTheme} />;
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Form Patterns
|
|
181
|
+
|
|
182
|
+
### React Hook Form + Zod
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { useForm } from 'react-hook-form';
|
|
186
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
187
|
+
import { z } from 'zod';
|
|
188
|
+
|
|
189
|
+
// Schema
|
|
190
|
+
const createUserSchema = z.object({
|
|
191
|
+
name: z.string().min(1, 'Name is required').max(100),
|
|
192
|
+
email: z.string().email('Invalid email'),
|
|
193
|
+
role: z.enum(['admin', 'user', 'guest']),
|
|
194
|
+
notifications: z.boolean().default(true),
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
type CreateUserInput = z.infer<typeof createUserSchema>;
|
|
198
|
+
|
|
199
|
+
// Component
|
|
200
|
+
function CreateUserForm() {
|
|
201
|
+
const {
|
|
202
|
+
register,
|
|
203
|
+
handleSubmit,
|
|
204
|
+
formState: { errors, isSubmitting },
|
|
205
|
+
} = useForm<CreateUserInput>({
|
|
206
|
+
resolver: zodResolver(createUserSchema),
|
|
207
|
+
defaultValues: {
|
|
208
|
+
notifications: true,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const createUser = useCreateUser();
|
|
213
|
+
|
|
214
|
+
const onSubmit = async (data: CreateUserInput) => {
|
|
215
|
+
await createUser.mutateAsync(data);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
220
|
+
<Input
|
|
221
|
+
{...register('name')}
|
|
222
|
+
error={errors.name?.message}
|
|
223
|
+
/>
|
|
224
|
+
<Input
|
|
225
|
+
{...register('email')}
|
|
226
|
+
error={errors.email?.message}
|
|
227
|
+
/>
|
|
228
|
+
<Select {...register('role')}>
|
|
229
|
+
<option value="user">User</option>
|
|
230
|
+
<option value="admin">Admin</option>
|
|
231
|
+
</Select>
|
|
232
|
+
<Button type="submit" loading={isSubmitting}>
|
|
233
|
+
Create User
|
|
234
|
+
</Button>
|
|
235
|
+
</form>
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Styling Standards
|
|
243
|
+
|
|
244
|
+
### TailwindCSS Best Practices
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
// Use semantic class groupings
|
|
248
|
+
<div className="
|
|
249
|
+
flex items-center justify-between
|
|
250
|
+
p-4 gap-4
|
|
251
|
+
bg-white dark:bg-gray-900
|
|
252
|
+
border border-gray-200 rounded-lg
|
|
253
|
+
hover:shadow-md transition-shadow
|
|
254
|
+
">
|
|
255
|
+
|
|
256
|
+
// Extract repeated patterns to components
|
|
257
|
+
function Card({ children, className }: CardProps) {
|
|
258
|
+
return (
|
|
259
|
+
<div className={cn(
|
|
260
|
+
'bg-white dark:bg-gray-900',
|
|
261
|
+
'border border-gray-200 rounded-lg',
|
|
262
|
+
'p-4 shadow-sm',
|
|
263
|
+
className
|
|
264
|
+
)}>
|
|
265
|
+
{children}
|
|
266
|
+
</div>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### CSS Variables for Theming
|
|
272
|
+
|
|
273
|
+
```css
|
|
274
|
+
:root {
|
|
275
|
+
--color-primary: 220 90% 56%;
|
|
276
|
+
--color-secondary: 262 83% 58%;
|
|
277
|
+
--color-background: 0 0% 100%;
|
|
278
|
+
--color-foreground: 222 47% 11%;
|
|
279
|
+
--color-muted: 210 40% 96%;
|
|
280
|
+
--color-border: 214 32% 91%;
|
|
281
|
+
--radius: 0.5rem;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.dark {
|
|
285
|
+
--color-background: 222 47% 11%;
|
|
286
|
+
--color-foreground: 210 40% 98%;
|
|
287
|
+
--color-muted: 217 33% 17%;
|
|
288
|
+
--color-border: 217 33% 17%;
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Mobile-First Responsive Design
|
|
293
|
+
|
|
294
|
+
```tsx
|
|
295
|
+
// Always start mobile, scale up
|
|
296
|
+
<div className="
|
|
297
|
+
grid grid-cols-1
|
|
298
|
+
sm:grid-cols-2
|
|
299
|
+
lg:grid-cols-3
|
|
300
|
+
xl:grid-cols-4
|
|
301
|
+
gap-4
|
|
302
|
+
">
|
|
303
|
+
|
|
304
|
+
// Responsive text
|
|
305
|
+
<h1 className="text-2xl sm:text-3xl lg:text-4xl font-bold">
|
|
306
|
+
|
|
307
|
+
// Hide/show based on breakpoint
|
|
308
|
+
<div className="hidden md:block">Desktop only</div>
|
|
309
|
+
<div className="md:hidden">Mobile only</div>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Typography Standards
|
|
315
|
+
|
|
316
|
+
### Font Selection (AVOID GENERIC)
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
// FORBIDDEN - Generic AI fonts
|
|
320
|
+
font-family: 'Inter', sans-serif; // Too common
|
|
321
|
+
font-family: 'Roboto', sans-serif; // Too common
|
|
322
|
+
font-family: 'Arial', sans-serif; // System font
|
|
323
|
+
font-family: system-ui, sans-serif; // System stack
|
|
324
|
+
|
|
325
|
+
// RECOMMENDED - Distinctive fonts
|
|
326
|
+
font-family: 'Geist', sans-serif; // Modern, tech
|
|
327
|
+
font-family: 'Satoshi', sans-serif; // Contemporary
|
|
328
|
+
font-family: 'Cabinet Grotesk', sans-serif; // Bold, editorial
|
|
329
|
+
font-family: 'Clash Display', sans-serif; // Display headings
|
|
330
|
+
font-family: 'General Sans', sans-serif; // Clean, versatile
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Font Pairing
|
|
334
|
+
|
|
335
|
+
```css
|
|
336
|
+
/* Display + Body pairing */
|
|
337
|
+
--font-display: 'Clash Display', sans-serif;
|
|
338
|
+
--font-body: 'Satoshi', sans-serif;
|
|
339
|
+
|
|
340
|
+
/* Heading uses display */
|
|
341
|
+
h1, h2, h3 {
|
|
342
|
+
font-family: var(--font-display);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/* Body uses readable font */
|
|
346
|
+
body, p, span {
|
|
347
|
+
font-family: var(--font-body);
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Animation Standards
|
|
354
|
+
|
|
355
|
+
### CSS Transitions (Simple Effects)
|
|
356
|
+
|
|
357
|
+
```css
|
|
358
|
+
/* Standard transition */
|
|
359
|
+
.button {
|
|
360
|
+
transition: all 150ms ease;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* Specific properties for performance */
|
|
364
|
+
.card {
|
|
365
|
+
transition: transform 200ms ease, box-shadow 200ms ease;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/* Hover states */
|
|
369
|
+
.card:hover {
|
|
370
|
+
transform: translateY(-2px);
|
|
371
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### Framer Motion (Complex Animations)
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
379
|
+
|
|
380
|
+
// Page transitions
|
|
381
|
+
function PageWrapper({ children }: { children: React.ReactNode }) {
|
|
382
|
+
return (
|
|
383
|
+
<motion.div
|
|
384
|
+
initial={{ opacity: 0, y: 20 }}
|
|
385
|
+
animate={{ opacity: 1, y: 0 }}
|
|
386
|
+
exit={{ opacity: 0, y: -20 }}
|
|
387
|
+
transition={{ duration: 0.3 }}
|
|
388
|
+
>
|
|
389
|
+
{children}
|
|
390
|
+
</motion.div>
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Staggered list animation
|
|
395
|
+
function ItemList({ items }: { items: Item[] }) {
|
|
396
|
+
return (
|
|
397
|
+
<motion.ul>
|
|
398
|
+
{items.map((item, i) => (
|
|
399
|
+
<motion.li
|
|
400
|
+
key={item.id}
|
|
401
|
+
initial={{ opacity: 0, x: -20 }}
|
|
402
|
+
animate={{ opacity: 1, x: 0 }}
|
|
403
|
+
transition={{ delay: i * 0.1 }}
|
|
404
|
+
>
|
|
405
|
+
{item.name}
|
|
406
|
+
</motion.li>
|
|
407
|
+
))}
|
|
408
|
+
</motion.ul>
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### Animation Guidelines
|
|
414
|
+
|
|
415
|
+
1. **Focus on high-impact moments** - Page loads, modal opens, state changes
|
|
416
|
+
2. **One orchestrated animation > scattered micro-interactions**
|
|
417
|
+
3. **Keep durations short** - 150-300ms for UI, 300-500ms for page transitions
|
|
418
|
+
4. **Use easing** - `ease`, `ease-out` for exits, `ease-in-out` for continuous
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Component Patterns
|
|
423
|
+
|
|
424
|
+
### Compound Components
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
// Flexible API for complex components
|
|
428
|
+
function Tabs({ children, defaultValue }: TabsProps) {
|
|
429
|
+
const [value, setValue] = useState(defaultValue);
|
|
430
|
+
return (
|
|
431
|
+
<TabsContext.Provider value={{ value, setValue }}>
|
|
432
|
+
<div className="tabs">{children}</div>
|
|
433
|
+
</TabsContext.Provider>
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
Tabs.List = function TabsList({ children }: { children: React.ReactNode }) {
|
|
438
|
+
return <div className="tabs-list">{children}</div>;
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
Tabs.Trigger = function TabsTrigger({ value, children }: TabsTriggerProps) {
|
|
442
|
+
const { value: selected, setValue } = useTabsContext();
|
|
443
|
+
return (
|
|
444
|
+
<button
|
|
445
|
+
className={cn('tab', selected === value && 'active')}
|
|
446
|
+
onClick={() => setValue(value)}
|
|
447
|
+
>
|
|
448
|
+
{children}
|
|
449
|
+
</button>
|
|
450
|
+
);
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
Tabs.Content = function TabsContent({ value, children }: TabsContentProps) {
|
|
454
|
+
const { value: selected } = useTabsContext();
|
|
455
|
+
if (value !== selected) return null;
|
|
456
|
+
return <div className="tab-content">{children}</div>;
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
// Usage
|
|
460
|
+
<Tabs defaultValue="tab1">
|
|
461
|
+
<Tabs.List>
|
|
462
|
+
<Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>
|
|
463
|
+
<Tabs.Trigger value="tab2">Tab 2</Tabs.Trigger>
|
|
464
|
+
</Tabs.List>
|
|
465
|
+
<Tabs.Content value="tab1">Content 1</Tabs.Content>
|
|
466
|
+
<Tabs.Content value="tab2">Content 2</Tabs.Content>
|
|
467
|
+
</Tabs>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Error Boundaries
|
|
471
|
+
|
|
472
|
+
```tsx
|
|
473
|
+
import { Component, ErrorInfo, ReactNode } from 'react';
|
|
474
|
+
|
|
475
|
+
interface Props {
|
|
476
|
+
children: ReactNode;
|
|
477
|
+
fallback: ReactNode;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
interface State {
|
|
481
|
+
hasError: boolean;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
class ErrorBoundary extends Component<Props, State> {
|
|
485
|
+
state: State = { hasError: false };
|
|
486
|
+
|
|
487
|
+
static getDerivedStateFromError(): State {
|
|
488
|
+
return { hasError: true };
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
492
|
+
console.error('Error:', error, errorInfo);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
render() {
|
|
496
|
+
if (this.state.hasError) {
|
|
497
|
+
return this.props.fallback;
|
|
498
|
+
}
|
|
499
|
+
return this.props.children;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Usage
|
|
504
|
+
<ErrorBoundary fallback={<ErrorMessage />}>
|
|
505
|
+
<UserProfile userId={userId} />
|
|
506
|
+
</ErrorBoundary>
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## Accessibility
|
|
512
|
+
|
|
513
|
+
### Required Practices
|
|
514
|
+
|
|
515
|
+
```tsx
|
|
516
|
+
// Always use semantic HTML
|
|
517
|
+
<button>Click me</button> // not <div onClick={}>
|
|
518
|
+
|
|
519
|
+
// Images need alt text
|
|
520
|
+
<img src={user.avatar} alt={`${user.name}'s avatar`} />
|
|
521
|
+
|
|
522
|
+
// Form inputs need labels
|
|
523
|
+
<label htmlFor="email">Email</label>
|
|
524
|
+
<input id="email" type="email" />
|
|
525
|
+
|
|
526
|
+
// Use ARIA when needed
|
|
527
|
+
<button aria-label="Close dialog" aria-expanded={isOpen}>
|
|
528
|
+
<XIcon />
|
|
529
|
+
</button>
|
|
530
|
+
|
|
531
|
+
// Keyboard navigation
|
|
532
|
+
<div
|
|
533
|
+
role="button"
|
|
534
|
+
tabIndex={0}
|
|
535
|
+
onKeyDown={(e) => e.key === 'Enter' && onClick()}
|
|
536
|
+
onClick={onClick}
|
|
537
|
+
>
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
### Focus Management
|
|
541
|
+
|
|
542
|
+
```tsx
|
|
543
|
+
// Focus trap for modals
|
|
544
|
+
import { FocusTrap } from '@radix-ui/react-focus-scope';
|
|
545
|
+
|
|
546
|
+
<FocusTrap>
|
|
547
|
+
<Dialog>...</Dialog>
|
|
548
|
+
</FocusTrap>
|
|
549
|
+
|
|
550
|
+
// Auto-focus on mount
|
|
551
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
552
|
+
useEffect(() => {
|
|
553
|
+
inputRef.current?.focus();
|
|
554
|
+
}, []);
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
---
|
|
558
|
+
|
|
559
|
+
## Performance
|
|
560
|
+
|
|
561
|
+
### Code Splitting
|
|
562
|
+
|
|
563
|
+
```tsx
|
|
564
|
+
import { lazy, Suspense } from 'react';
|
|
565
|
+
|
|
566
|
+
// Lazy load heavy components
|
|
567
|
+
const Dashboard = lazy(() => import('./pages/Dashboard'));
|
|
568
|
+
const Analytics = lazy(() => import('./pages/Analytics'));
|
|
569
|
+
|
|
570
|
+
// Use Suspense
|
|
571
|
+
<Suspense fallback={<LoadingSpinner />}>
|
|
572
|
+
<Dashboard />
|
|
573
|
+
</Suspense>
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Image Optimization
|
|
577
|
+
|
|
578
|
+
```tsx
|
|
579
|
+
import Image from 'next/image';
|
|
580
|
+
|
|
581
|
+
// Always use next/image
|
|
582
|
+
<Image
|
|
583
|
+
src={user.avatar}
|
|
584
|
+
alt={user.name}
|
|
585
|
+
width={48}
|
|
586
|
+
height={48}
|
|
587
|
+
priority={isAboveFold}
|
|
588
|
+
/>
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
### Memoization
|
|
592
|
+
|
|
593
|
+
```tsx
|
|
594
|
+
// Memo expensive components
|
|
595
|
+
const ExpensiveList = memo(function ExpensiveList({ items }: Props) {
|
|
596
|
+
return items.map(item => <ExpensiveItem key={item.id} {...item} />);
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
// useMemo for expensive calculations
|
|
600
|
+
const sortedItems = useMemo(
|
|
601
|
+
() => items.sort((a, b) => b.score - a.score),
|
|
602
|
+
[items]
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
// useCallback for stable references
|
|
606
|
+
const handleClick = useCallback((id: string) => {
|
|
607
|
+
setSelectedId(id);
|
|
608
|
+
}, []);
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
## Directory Structure
|
|
614
|
+
|
|
615
|
+
```text
|
|
616
|
+
/src
|
|
617
|
+
/app # Next.js App Router
|
|
618
|
+
/api # API routes
|
|
619
|
+
/(auth) # Auth route group
|
|
620
|
+
/(dashboard) # Dashboard route group
|
|
621
|
+
layout.tsx
|
|
622
|
+
page.tsx
|
|
623
|
+
/components
|
|
624
|
+
/ui # Primitive UI components
|
|
625
|
+
button.tsx
|
|
626
|
+
input.tsx
|
|
627
|
+
card.tsx
|
|
628
|
+
/features # Feature-specific components
|
|
629
|
+
/user
|
|
630
|
+
UserProfile.tsx
|
|
631
|
+
UserList.tsx
|
|
632
|
+
/order
|
|
633
|
+
OrderForm.tsx
|
|
634
|
+
/hooks # Custom hooks
|
|
635
|
+
useUser.ts
|
|
636
|
+
useDebounce.ts
|
|
637
|
+
/lib # Utilities
|
|
638
|
+
api.ts
|
|
639
|
+
utils.ts
|
|
640
|
+
cn.ts
|
|
641
|
+
/stores # Zustand stores
|
|
642
|
+
userStore.ts
|
|
643
|
+
uiStore.ts
|
|
644
|
+
/types # TypeScript types
|
|
645
|
+
user.ts
|
|
646
|
+
api.ts
|
|
647
|
+
/public # Static assets
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
## Forbidden Patterns
|
|
653
|
+
|
|
654
|
+
**The following patterns are never allowed. Agents MUST refuse to implement these:**
|
|
655
|
+
|
|
656
|
+
### TypeScript Anti-Patterns
|
|
657
|
+
|
|
658
|
+
| Pattern | Why Forbidden | Correct Alternative |
|
|
659
|
+
|---------|---------------|---------------------|
|
|
660
|
+
| `any` type | Defeats TypeScript purpose | Use proper types, `unknown`, or generics |
|
|
661
|
+
| Type assertions without validation | Runtime errors | Use type guards or Zod parsing |
|
|
662
|
+
| `// @ts-ignore` or `// @ts-expect-error` | Hides real errors | Fix the type issue properly |
|
|
663
|
+
| Non-strict mode | Allows unsafe code | Enable `"strict": true` in tsconfig |
|
|
664
|
+
|
|
665
|
+
### Accessibility Anti-Patterns
|
|
666
|
+
|
|
667
|
+
| Pattern | Why Forbidden | Correct Alternative |
|
|
668
|
+
|---------|---------------|---------------------|
|
|
669
|
+
| `<div onClick={}>` for buttons | Not keyboard accessible | Use `<button>` element |
|
|
670
|
+
| `<span onClick={}>` for links | Not keyboard accessible | Use `<a href="">` element |
|
|
671
|
+
| Missing `alt` on images | Screen readers can't describe | Always provide descriptive alt text |
|
|
672
|
+
| Missing form labels | Inputs not associated | Use `<label htmlFor="">` |
|
|
673
|
+
| `tabIndex > 0` | Breaks natural tab order | Use `tabIndex={0}` or semantic HTML |
|
|
674
|
+
| `outline: none` without alternative | Removes focus visibility | Provide custom focus styles |
|
|
675
|
+
|
|
676
|
+
### State Management Anti-Patterns
|
|
677
|
+
|
|
678
|
+
| Pattern | Why Forbidden | Correct Alternative |
|
|
679
|
+
|---------|---------------|---------------------|
|
|
680
|
+
| `useEffect` for data fetching | Race conditions, no caching | Use TanStack Query |
|
|
681
|
+
| Props drilling > 3 levels | Unmaintainable | Use Context or Zustand |
|
|
682
|
+
| Storing server state in Redux/Zustand | Stale data, duplicate cache | Use TanStack Query for server state |
|
|
683
|
+
| `useState` for form state | No validation, verbose | Use React Hook Form |
|
|
684
|
+
|
|
685
|
+
### Security Anti-Patterns
|
|
686
|
+
|
|
687
|
+
| Pattern | Why Forbidden | Correct Alternative |
|
|
688
|
+
|---------|---------------|---------------------|
|
|
689
|
+
| `dangerouslySetInnerHTML` without sanitization | XSS vulnerability | Use DOMPurify or avoid entirely |
|
|
690
|
+
| Storing tokens in localStorage | XSS can steal tokens | Use httpOnly cookies |
|
|
691
|
+
| Hardcoded API keys in frontend | Exposed in bundle | Use environment variables, BFF |
|
|
692
|
+
| Unvalidated URL redirects | Open redirect vulnerability | Whitelist allowed domains |
|
|
693
|
+
|
|
694
|
+
### Font Anti-Patterns
|
|
695
|
+
|
|
696
|
+
| Pattern | Why Forbidden | Correct Alternative |
|
|
697
|
+
|---------|---------------|---------------------|
|
|
698
|
+
| `font-family: 'Inter'` | Generic AI aesthetic | Use Geist, Satoshi, Cabinet Grotesk |
|
|
699
|
+
| `font-family: 'Roboto'` | Generic, overused | Use General Sans, Clash Display |
|
|
700
|
+
| `font-family: 'Arial'` | System font, no character | Use distinctive web fonts |
|
|
701
|
+
| `font-family: system-ui` | No brand identity | Define specific font stack |
|
|
702
|
+
|
|
703
|
+
### Performance Anti-Patterns
|
|
704
|
+
|
|
705
|
+
| Pattern | Why Forbidden | Correct Alternative |
|
|
706
|
+
|---------|---------------|---------------------|
|
|
707
|
+
| `<img>` without next/image | No optimization | Use `next/image` component |
|
|
708
|
+
| Inline styles in loops | Creates new objects each render | Use className or CSS Modules |
|
|
709
|
+
| Missing `key` prop in lists | React can't optimize | Always provide stable keys |
|
|
710
|
+
| `useMemo`/`useCallback` everywhere | Premature optimization | Only when actually needed |
|
|
711
|
+
|
|
712
|
+
**If existing code uses FORBIDDEN patterns → Report as blocker, DO NOT extend.**
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
## Standards Compliance Categories
|
|
717
|
+
|
|
718
|
+
**When invoked from ring:dev-refactor, check all categories:**
|
|
719
|
+
|
|
720
|
+
| Category | Ring Standard | What to Verify |
|
|
721
|
+
|----------|--------------|----------------|
|
|
722
|
+
| **TypeScript** | Strict mode, no `any` | tsconfig.json, *.tsx files |
|
|
723
|
+
| **Accessibility** | WCAG 2.1 AA | Semantic HTML, ARIA, keyboard nav |
|
|
724
|
+
| **State Management** | TanStack Query + Zustand | No useEffect for fetching |
|
|
725
|
+
| **Forms** | React Hook Form + Zod | Validation schemas present |
|
|
726
|
+
| **Styling** | Tailwind, CSS variables | No inline styles in logic |
|
|
727
|
+
| **Fonts** | Distinctive fonts | No Inter, Roboto, Arial |
|
|
728
|
+
| **Performance** | next/image, code splitting | Lazy loading, memoization |
|
|
729
|
+
| **Security** | No XSS vectors | dangerouslySetInnerHTML usage |
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
## Checklist
|
|
734
|
+
|
|
735
|
+
Before submitting frontend code, verify:
|
|
736
|
+
|
|
737
|
+
- [ ] TypeScript strict mode (no `any`)
|
|
738
|
+
- [ ] Components use semantic HTML
|
|
739
|
+
- [ ] Forms validated with Zod
|
|
740
|
+
- [ ] TanStack Query for server state
|
|
741
|
+
- [ ] Zustand for client state (if needed)
|
|
742
|
+
- [ ] Mobile-first responsive design
|
|
743
|
+
- [ ] Keyboard accessible (tabIndex, onKeyDown)
|
|
744
|
+
- [ ] ARIA labels where needed
|
|
745
|
+
- [ ] Images use next/image with alt text
|
|
746
|
+
- [ ] No generic fonts (Inter, Roboto, Arial)
|
|
747
|
+
- [ ] Animations are purposeful, not decorative
|
|
748
|
+
- [ ] No FORBIDDEN patterns present
|