@baldurpan/create-ai-workflow 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/dist/agents-block.js +70 -0
- package/dist/bin.js +14 -0
- package/dist/check/markdown.js +47 -0
- package/dist/check/parse.js +113 -0
- package/dist/check/rules.js +245 -0
- package/dist/cli.js +109 -0
- package/dist/commands/check.js +41 -0
- package/dist/commands/install.js +76 -0
- package/dist/commands/standards-add.js +145 -0
- package/dist/commands/update.js +214 -0
- package/dist/layout.js +115 -0
- package/dist/log.js +20 -0
- package/dist/manifest.js +53 -0
- package/dist/paths.js +41 -0
- package/package.json +37 -0
- package/templates/blocks/agents-block.md +30 -0
- package/templates/claude/agents/planner.agent.md +60 -0
- package/templates/claude/agents/reviewer.agent.md +77 -0
- package/templates/context/README.md +81 -0
- package/templates/context/plan-template.md +69 -0
- package/templates/context/plan-template.notes.md +55 -0
- package/templates/context/roles/coder.md +76 -0
- package/templates/context/workflow.md +143 -0
- package/templates/skills/feature-close/SKILL.md +102 -0
- package/templates/skills/feature-implement/SKILL.md +142 -0
- package/templates/skills/feature-plan/SKILL.md +138 -0
- package/templates/skills/feature-status/SKILL.md +86 -0
- package/templates/skills/onboard/SKILL.md +122 -0
- package/templates/skills/orchestrate/SKILL.md +92 -0
- package/templates/skills/roadmap/SKILL.md +97 -0
- package/templates/standards/.source +8 -0
- package/templates/standards/README.md +104 -0
- package/templates/standards/architecture/api-design.md +212 -0
- package/templates/standards/architecture/dependency-boundaries.md +104 -0
- package/templates/standards/architecture/feature-driven.md +102 -0
- package/templates/standards/architecture/folder-structure.md +108 -0
- package/templates/standards/architecture/monorepos.md +107 -0
- package/templates/standards/architecture/refactoring.md +97 -0
- package/templates/standards/architecture/shared-code.md +81 -0
- package/templates/standards/docs/PHP-SPEC.md +1195 -0
- package/templates/standards/docs/SPEC.md +540 -0
- package/templates/standards/examples/bad/data-fetching.tsx +52 -0
- package/templates/standards/examples/bad/derived-state.tsx +60 -0
- package/templates/standards/examples/bad/feature-component.tsx +80 -0
- package/templates/standards/examples/bad/prop-drilling.tsx +70 -0
- package/templates/standards/examples/good/data-fetching.tsx +53 -0
- package/templates/standards/examples/good/derived-state.tsx +52 -0
- package/templates/standards/examples/good/feature-component.tsx +141 -0
- package/templates/standards/examples/good/invoice.schema.ts +20 -0
- package/templates/standards/examples/good/prop-drilling.tsx +83 -0
- package/templates/standards/philosophy/ai-agent-behavior.md +93 -0
- package/templates/standards/philosophy/core-principles.md +49 -0
- package/templates/standards/philosophy/incremental-abstraction.md +56 -0
- package/templates/standards/philosophy/maintainability.md +66 -0
- package/templates/standards/philosophy/readability.md +87 -0
- package/templates/standards/php/README.md +62 -0
- package/templates/standards/php/anti-patterns.md +259 -0
- package/templates/standards/php/architecture.md +241 -0
- package/templates/standards/php/frameworks.md +197 -0
- package/templates/standards/php/rules.md +205 -0
- package/templates/standards/php/security.md +190 -0
- package/templates/standards/php/testing.md +139 -0
- package/templates/standards/php/tooling.md +245 -0
- package/templates/standards/react/accessibility.md +130 -0
- package/templates/standards/react/anti-patterns.md +187 -0
- package/templates/standards/react/component-design.md +139 -0
- package/templates/standards/react/error-boundaries.md +195 -0
- package/templates/standards/react/forms.md +147 -0
- package/templates/standards/react/hooks.md +88 -0
- package/templates/standards/react/memoization.md +87 -0
- package/templates/standards/react/state-management.md +123 -0
- package/templates/standards/react/testing.md +118 -0
- package/templates/standards/react/use-effect.md +110 -0
- package/templates/standards/security/api-security.md +136 -0
- package/templates/standards/security/auth.md +112 -0
- package/templates/standards/security/secrets.md +105 -0
- package/templates/standards/security/validation.md +89 -0
- package/templates/standards/templates/.editorconfig +16 -0
- package/templates/standards/templates/.nvmrc +1 -0
- package/templates/standards/templates/AGENTS.md +46 -0
- package/templates/standards/templates/CLAUDE.md +3 -0
- package/templates/standards/templates/_dot_gitignore +50 -0
- package/templates/standards/templates/biome.json +53 -0
- package/templates/standards/templates/eslint.config.js +61 -0
- package/templates/standards/templates/project-readme.md +76 -0
- package/templates/standards/templates/pull-request-template.md +46 -0
- package/templates/standards/templates/tsconfig.json +35 -0
- package/templates/standards/tooling/biome.md +92 -0
- package/templates/standards/tooling/ci.md +128 -0
- package/templates/standards/tooling/dates.md +194 -0
- package/templates/standards/tooling/dependencies.md +90 -0
- package/templates/standards/tooling/nx.md +113 -0
- package/templates/standards/tooling/observability.md +183 -0
- package/templates/standards/tooling/prisma.md +152 -0
- package/templates/standards/tooling/shadcn.md +115 -0
- package/templates/standards/tooling/tailwind.md +135 -0
- package/templates/standards/tooling/tanstack-query.md +214 -0
- package/templates/standards/tooling/tanstack-router.md +365 -0
- package/templates/standards/tooling/tanstack.md +31 -0
- package/templates/standards/tooling/vite.md +135 -0
- package/templates/standards/typescript/anti-patterns.md +107 -0
- package/templates/standards/typescript/error-handling.md +216 -0
- package/templates/standards/typescript/naming.md +78 -0
- package/templates/standards/typescript/rules.md +159 -0
- package/templates/standards/typescript/tsconfig/base.json +32 -0
- package/templates/standards/typescript/tsconfig/nextjs.json +12 -0
- package/templates/standards/typescript/tsconfig/react.json +9 -0
- package/templates/standards/typescript/validation.md +104 -0
- package/templates/stubs/executors.md +49 -0
- package/templates/stubs/findings.md +40 -0
- package/templates/stubs/history.md +13 -0
- package/templates/stubs/roadmap.md +29 -0
- package/templates/stubs/stack.md +35 -0
- package/templates/stubs/verify.md +48 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
# AI Engineering Standards Repository
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Build a personal AI-native engineering standards repository intended primarily for AI agent consumption (Claude Code, AGENTS.md, Cursor, Continue, etc.), while still remaining readable for humans.
|
|
6
|
+
|
|
7
|
+
This repository should serve as:
|
|
8
|
+
|
|
9
|
+
- A reusable engineering standards system
|
|
10
|
+
- A source of truth for TypeScript and React best practices
|
|
11
|
+
- A reusable starter/reference kit for new projects
|
|
12
|
+
- A refactoring guide for older codebases
|
|
13
|
+
- A retrieval-friendly knowledge base for AI coding agents
|
|
14
|
+
|
|
15
|
+
The repository should optimize for:
|
|
16
|
+
|
|
17
|
+
- deterministic AI guidance
|
|
18
|
+
- maintainability
|
|
19
|
+
- composability
|
|
20
|
+
- readability
|
|
21
|
+
- scalability
|
|
22
|
+
- accessibility
|
|
23
|
+
- incremental architecture
|
|
24
|
+
|
|
25
|
+
The repository should NOT optimize for:
|
|
26
|
+
|
|
27
|
+
- excessive prose
|
|
28
|
+
- philosophical essays
|
|
29
|
+
- premature abstraction
|
|
30
|
+
- enterprise boilerplate
|
|
31
|
+
- giant generalized frameworks
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
# Core Engineering Philosophy
|
|
36
|
+
|
|
37
|
+
## Core Principle
|
|
38
|
+
|
|
39
|
+
Prefer explicit, composable, feature-oriented architecture over generalized abstractions and centralized complexity.
|
|
40
|
+
|
|
41
|
+
## Architectural Values
|
|
42
|
+
|
|
43
|
+
- Composition over inheritance
|
|
44
|
+
- Readability over cleverness
|
|
45
|
+
- Explicitness over magic
|
|
46
|
+
- Feature ownership over centralized organization
|
|
47
|
+
- Incremental abstraction over premature DRY
|
|
48
|
+
- Maintainability over premature optimization
|
|
49
|
+
- Colocation over fragmentation
|
|
50
|
+
- Accessibility-first development
|
|
51
|
+
- Strong type safety
|
|
52
|
+
- Predictable data flow
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
# AI Agent Behavior Rules
|
|
57
|
+
|
|
58
|
+
AI agents working with these standards should:
|
|
59
|
+
|
|
60
|
+
## Prioritize
|
|
61
|
+
|
|
62
|
+
- readability
|
|
63
|
+
- accessibility
|
|
64
|
+
- composability
|
|
65
|
+
- maintainability
|
|
66
|
+
- type safety
|
|
67
|
+
- feature isolation
|
|
68
|
+
- incremental refactoring
|
|
69
|
+
- explicit APIs
|
|
70
|
+
- predictable architecture
|
|
71
|
+
|
|
72
|
+
## Avoid
|
|
73
|
+
|
|
74
|
+
- giant files
|
|
75
|
+
- useEffect abuse
|
|
76
|
+
- premature abstractions
|
|
77
|
+
- hook mini-frameworks
|
|
78
|
+
- defensive memoization
|
|
79
|
+
- over-generalized utilities
|
|
80
|
+
- excessive inheritance
|
|
81
|
+
- Redux
|
|
82
|
+
- hidden side effects
|
|
83
|
+
- implementation testing
|
|
84
|
+
- state synchronization effects
|
|
85
|
+
- aggressive rewrites without approval
|
|
86
|
+
|
|
87
|
+
## Refactoring Rules
|
|
88
|
+
|
|
89
|
+
- Preserve behavior
|
|
90
|
+
- Prefer additive refactors
|
|
91
|
+
- Preserve architecture boundaries
|
|
92
|
+
- Ask before major architectural divergence
|
|
93
|
+
- Gently migrate legacy systems
|
|
94
|
+
- If possible, write tests before refactoring untested code
|
|
95
|
+
- Avoid massive rewrites unless explicitly requested
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
# Repository Structure
|
|
100
|
+
|
|
101
|
+
Create the repository roughly with this structure:
|
|
102
|
+
|
|
103
|
+
ai-engineering-standards/
|
|
104
|
+
├── README.md
|
|
105
|
+
│
|
|
106
|
+
├── philosophy/
|
|
107
|
+
│ ├── core-principles.md
|
|
108
|
+
│ ├── ai-agent-behavior.md
|
|
109
|
+
│ ├── incremental-abstraction.md
|
|
110
|
+
│ ├── maintainability.md
|
|
111
|
+
│ └── readability.md
|
|
112
|
+
│
|
|
113
|
+
├── typescript/
|
|
114
|
+
│ ├── rules.md
|
|
115
|
+
│ ├── anti-patterns.md
|
|
116
|
+
│ ├── validation.md
|
|
117
|
+
│ ├── naming.md
|
|
118
|
+
│ ├── error-handling.md
|
|
119
|
+
│ └── tsconfig/
|
|
120
|
+
│ ├── base.json
|
|
121
|
+
│ ├── react.json
|
|
122
|
+
│ └── nextjs.json
|
|
123
|
+
│
|
|
124
|
+
├── react/
|
|
125
|
+
│ ├── component-design.md
|
|
126
|
+
│ ├── hooks.md
|
|
127
|
+
│ ├── use-effect.md
|
|
128
|
+
│ ├── memoization.md
|
|
129
|
+
│ ├── state-management.md
|
|
130
|
+
│ ├── forms.md
|
|
131
|
+
│ ├── accessibility.md
|
|
132
|
+
│ ├── testing.md
|
|
133
|
+
│ └── anti-patterns.md
|
|
134
|
+
│
|
|
135
|
+
├── architecture/
|
|
136
|
+
│ ├── feature-driven.md
|
|
137
|
+
│ ├── shared-code.md
|
|
138
|
+
│ ├── monorepos.md
|
|
139
|
+
│ ├── folder-structure.md
|
|
140
|
+
│ ├── refactoring.md
|
|
141
|
+
│ └── dependency-boundaries.md
|
|
142
|
+
│
|
|
143
|
+
├── tooling/
|
|
144
|
+
│ ├── tanstack.md
|
|
145
|
+
│ ├── nx.md
|
|
146
|
+
│ ├── vite.md
|
|
147
|
+
│ ├── biome.md
|
|
148
|
+
│ ├── tailwind.md
|
|
149
|
+
│ ├── shadcn.md
|
|
150
|
+
│ └── prisma.md
|
|
151
|
+
│
|
|
152
|
+
├── security/
|
|
153
|
+
│ ├── validation.md
|
|
154
|
+
│ ├── secrets.md
|
|
155
|
+
│ ├── auth.md
|
|
156
|
+
│ └── api-security.md
|
|
157
|
+
│
|
|
158
|
+
├── examples/
|
|
159
|
+
│ ├── good/
|
|
160
|
+
│ └── bad/
|
|
161
|
+
│
|
|
162
|
+
├── templates/
|
|
163
|
+
│ ├── CLAUDE.md
|
|
164
|
+
│ ├── AGENTS.md
|
|
165
|
+
│ ├── project-readme.md
|
|
166
|
+
│ └── pull-request-template.md
|
|
167
|
+
│
|
|
168
|
+
└── packages/
|
|
169
|
+
├── tsconfig/
|
|
170
|
+
├── eslint-config/
|
|
171
|
+
└── biome-config/
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
# Documentation Style Requirements
|
|
176
|
+
|
|
177
|
+
Optimize all documentation for AI retrieval quality.
|
|
178
|
+
|
|
179
|
+
Documentation should be:
|
|
180
|
+
|
|
181
|
+
- directive
|
|
182
|
+
- concise
|
|
183
|
+
- hierarchical
|
|
184
|
+
- example-heavy
|
|
185
|
+
- low ambiguity
|
|
186
|
+
- deterministic
|
|
187
|
+
- composable
|
|
188
|
+
|
|
189
|
+
Avoid:
|
|
190
|
+
|
|
191
|
+
- giant essays
|
|
192
|
+
- vague wording
|
|
193
|
+
- contradictory guidance
|
|
194
|
+
- excessive prose
|
|
195
|
+
|
|
196
|
+
Preferred style:
|
|
197
|
+
|
|
198
|
+
md # Rules ## DO - ... ## DO NOT - ... ## PRIORITY Readability > micro-optimization
|
|
199
|
+
|
|
200
|
+
Separate:
|
|
201
|
+
|
|
202
|
+
- rules
|
|
203
|
+
- rationale
|
|
204
|
+
- examples
|
|
205
|
+
|
|
206
|
+
where appropriate.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
# TypeScript Standards
|
|
211
|
+
|
|
212
|
+
## General
|
|
213
|
+
|
|
214
|
+
- "strict": true
|
|
215
|
+
- Avoid any
|
|
216
|
+
- Prefer unions over enums
|
|
217
|
+
- Avoid type assertions when possible
|
|
218
|
+
- Prefer generated API types
|
|
219
|
+
- Prefer schema-driven validation
|
|
220
|
+
- Prefer explicit naming
|
|
221
|
+
- Avoid type gymnastics
|
|
222
|
+
- Avoid unnecessary DTO duplication
|
|
223
|
+
|
|
224
|
+
## tsconfig Preferences
|
|
225
|
+
|
|
226
|
+
Include strong strictness rules such as:
|
|
227
|
+
|
|
228
|
+
- noUnusedLocals
|
|
229
|
+
- noUnusedParameters
|
|
230
|
+
- noUncheckedIndexedAccess
|
|
231
|
+
- noPropertyAccessFromIndexSignature
|
|
232
|
+
- noFallthroughCasesInSwitch
|
|
233
|
+
- allowUnreachableCode: false
|
|
234
|
+
- allowUnusedLabels: false
|
|
235
|
+
- noUncheckedSideEffectImports
|
|
236
|
+
- erasableSyntaxOnly
|
|
237
|
+
|
|
238
|
+
Use:
|
|
239
|
+
|
|
240
|
+
- ~/\* absolute imports
|
|
241
|
+
|
|
242
|
+
## Validation
|
|
243
|
+
|
|
244
|
+
- Prefer Zod
|
|
245
|
+
- Investigate Valibot
|
|
246
|
+
- Schema-first validation is encouraged
|
|
247
|
+
- Shared FE/BE schemas are preferred
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
# React Standards
|
|
252
|
+
|
|
253
|
+
## Architecture
|
|
254
|
+
|
|
255
|
+
- Prefer feature-driven architecture
|
|
256
|
+
- Colocate feature-specific logic
|
|
257
|
+
- Avoid organization-by-type for large apps
|
|
258
|
+
- Prefer composition over deeply nested prop drilling
|
|
259
|
+
- Compound components are encouraged
|
|
260
|
+
|
|
261
|
+
## Components
|
|
262
|
+
|
|
263
|
+
- Keep components reasonably scoped
|
|
264
|
+
- Avoid gigantic files
|
|
265
|
+
- Large files should trigger decomposition review
|
|
266
|
+
- One file should generally have one primary responsibility
|
|
267
|
+
|
|
268
|
+
## Hooks
|
|
269
|
+
|
|
270
|
+
## DO
|
|
271
|
+
|
|
272
|
+
- Encapsulate reusable behavior
|
|
273
|
+
- Keep hooks composable
|
|
274
|
+
- Keep effects explicit
|
|
275
|
+
|
|
276
|
+
## DO NOT
|
|
277
|
+
|
|
278
|
+
- Create hook mini-frameworks
|
|
279
|
+
- Wrap useState purely for renaming
|
|
280
|
+
- Hide side effects unexpectedly
|
|
281
|
+
|
|
282
|
+
Before creating custom hooks:
|
|
283
|
+
|
|
284
|
+
- Check whether an existing solution already exists
|
|
285
|
+
- Investigate @uidotdev/usehooks
|
|
286
|
+
|
|
287
|
+
## useEffect Doctrine
|
|
288
|
+
|
|
289
|
+
useEffect should primarily be used for:
|
|
290
|
+
|
|
291
|
+
- external system synchronization
|
|
292
|
+
- subscriptions
|
|
293
|
+
- DOM APIs
|
|
294
|
+
- timers
|
|
295
|
+
- imperative bridges
|
|
296
|
+
|
|
297
|
+
Avoid useEffect for:
|
|
298
|
+
|
|
299
|
+
- state synchronization
|
|
300
|
+
- derived state
|
|
301
|
+
- unnecessary data flow orchestration
|
|
302
|
+
|
|
303
|
+
## Memoization
|
|
304
|
+
|
|
305
|
+
## DO
|
|
306
|
+
|
|
307
|
+
- Optimize proven bottlenecks
|
|
308
|
+
- Use useCallback for stable drilled callbacks when needed
|
|
309
|
+
|
|
310
|
+
## DO NOT
|
|
311
|
+
|
|
312
|
+
- Defensively memoize
|
|
313
|
+
- Abuse useMemo
|
|
314
|
+
- Use memoization to silence dependency warnings
|
|
315
|
+
- Overuse React.memo
|
|
316
|
+
|
|
317
|
+
Priority:
|
|
318
|
+
|
|
319
|
+
- Readability > micro-optimization
|
|
320
|
+
|
|
321
|
+
## State Management Hierarchy
|
|
322
|
+
|
|
323
|
+
Preferred order:
|
|
324
|
+
|
|
325
|
+
1. URL state
|
|
326
|
+
2. Server state (TanStack Query)
|
|
327
|
+
3. Local component state
|
|
328
|
+
4. Context
|
|
329
|
+
5. Zustand only when truly necessary
|
|
330
|
+
6. Never Redux
|
|
331
|
+
|
|
332
|
+
## Forms
|
|
333
|
+
|
|
334
|
+
- Prefer TanStack ecosystem where possible
|
|
335
|
+
- React Hook Form is acceptable
|
|
336
|
+
- Prefer controlled inputs
|
|
337
|
+
- Prefer shared schema validation
|
|
338
|
+
- Optimistic updates are encouraged
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
# Styling Standards
|
|
343
|
+
|
|
344
|
+
Preferred stack:
|
|
345
|
+
|
|
346
|
+
- Tailwind CSS
|
|
347
|
+
- Shadcn UI
|
|
348
|
+
- CSS variables for theming
|
|
349
|
+
- Design tokens
|
|
350
|
+
- Minimal arbitrary values
|
|
351
|
+
|
|
352
|
+
Avoid:
|
|
353
|
+
|
|
354
|
+
- CSS Modules unless necessary
|
|
355
|
+
- Excessive arbitrary Tailwind values
|
|
356
|
+
|
|
357
|
+
Preferred theming approach:
|
|
358
|
+
|
|
359
|
+
- CSS variable-based themes
|
|
360
|
+
- Tailwind integration
|
|
361
|
+
- Runtime-friendly tokens
|
|
362
|
+
- Dark/light mode support
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
# Testing Standards
|
|
367
|
+
|
|
368
|
+
## Philosophy
|
|
369
|
+
|
|
370
|
+
- Integration tests over implementation tests
|
|
371
|
+
- Test behavior, not implementation details
|
|
372
|
+
- Avoid snapshot tests
|
|
373
|
+
- Unit test pure utilities and logic
|
|
374
|
+
- Use Playwright only for critical E2E flows
|
|
375
|
+
|
|
376
|
+
## Preferred Tooling
|
|
377
|
+
|
|
378
|
+
- Vitest
|
|
379
|
+
- Testing Library
|
|
380
|
+
- Playwright
|
|
381
|
+
|
|
382
|
+
Follow the philosophy from:
|
|
383
|
+
https://kentcdodds.com/blog/common-mistakes-with-react-testing-library
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
# Accessibility Standards
|
|
388
|
+
|
|
389
|
+
Accessibility standards should be strict.
|
|
390
|
+
|
|
391
|
+
## Requirements
|
|
392
|
+
|
|
393
|
+
- Semantic HTML first
|
|
394
|
+
- Keyboard navigation mandatory
|
|
395
|
+
- Screenreader friendliness mandatory
|
|
396
|
+
- Form labeling mandatory
|
|
397
|
+
- ARIA only when necessary
|
|
398
|
+
- Avoid clickable divs
|
|
399
|
+
- Ensure color contrast compliance
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
# Error Handling Standards
|
|
404
|
+
|
|
405
|
+
## Rules
|
|
406
|
+
|
|
407
|
+
- Never swallow errors
|
|
408
|
+
- Never hide original error context
|
|
409
|
+
- Avoid generic "Something went wrong" messages
|
|
410
|
+
- Preserve HTTP status codes and payloads
|
|
411
|
+
- Use contextual logging
|
|
412
|
+
- Avoid large ambiguous try/catch blocks
|
|
413
|
+
- Use custom error classes where appropriate
|
|
414
|
+
- Validate inputs before transitions
|
|
415
|
+
|
|
416
|
+
## Async Rules
|
|
417
|
+
|
|
418
|
+
- Avoid unhandled promise rejections
|
|
419
|
+
- Await async operations properly
|
|
420
|
+
- Use .catch() where appropriate
|
|
421
|
+
|
|
422
|
+
## User-Facing Errors
|
|
423
|
+
|
|
424
|
+
Every user-facing error should:
|
|
425
|
+
|
|
426
|
+
- explain the failure
|
|
427
|
+
- explain the next step
|
|
428
|
+
- remain actionable
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
# Dependency Philosophy
|
|
433
|
+
|
|
434
|
+
## DO
|
|
435
|
+
|
|
436
|
+
- Prefer browser-native APIs
|
|
437
|
+
- Prefer mature maintained libraries
|
|
438
|
+
- Check bundle impact
|
|
439
|
+
|
|
440
|
+
## DO NOT
|
|
441
|
+
|
|
442
|
+
- Add tiny unnecessary dependencies
|
|
443
|
+
- Add bloated libraries
|
|
444
|
+
- Use abandoned packages
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
# Monorepo Philosophy
|
|
449
|
+
|
|
450
|
+
Preferred tooling:
|
|
451
|
+
|
|
452
|
+
- Nx
|
|
453
|
+
- pnpm
|
|
454
|
+
|
|
455
|
+
Guidelines:
|
|
456
|
+
|
|
457
|
+
- Preserve feature isolation
|
|
458
|
+
- Avoid circular dependencies
|
|
459
|
+
- Avoid publishable packages unless explicitly required
|
|
460
|
+
- Group packages by domain when scaling
|
|
461
|
+
|
|
462
|
+
Example:
|
|
463
|
+
|
|
464
|
+
txt packages/ frontend/ backend/
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
# CI / PR Standards
|
|
469
|
+
|
|
470
|
+
Required:
|
|
471
|
+
|
|
472
|
+
- lint gating
|
|
473
|
+
- typecheck gating
|
|
474
|
+
- test gating
|
|
475
|
+
- formatting gating
|
|
476
|
+
|
|
477
|
+
Guidance:
|
|
478
|
+
|
|
479
|
+
- Smaller PRs are preferred for reviewability
|
|
480
|
+
- Large PRs are acceptable when necessary
|
|
481
|
+
- Prefer squash merges
|
|
482
|
+
- Prioritize high-quality PR titles/descriptions
|
|
483
|
+
|
|
484
|
+
When using PR workflows:
|
|
485
|
+
|
|
486
|
+
- Investigate @burglekitt/worktree
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
# Initial Implementation Plan
|
|
491
|
+
|
|
492
|
+
Start implementation in phases.
|
|
493
|
+
|
|
494
|
+
## Phase 1
|
|
495
|
+
|
|
496
|
+
- Repository structure
|
|
497
|
+
- README
|
|
498
|
+
- Core philosophy documents
|
|
499
|
+
- AI behavior document
|
|
500
|
+
- tsconfig package
|
|
501
|
+
- biome/eslint configs
|
|
502
|
+
|
|
503
|
+
## Phase 2
|
|
504
|
+
|
|
505
|
+
- React/TypeScript standards docs
|
|
506
|
+
- Examples
|
|
507
|
+
- AGENTS.md templates
|
|
508
|
+
- CLAUDE.md templates
|
|
509
|
+
|
|
510
|
+
## Phase 3
|
|
511
|
+
|
|
512
|
+
- Advanced architecture docs
|
|
513
|
+
- Security docs
|
|
514
|
+
- Monorepo docs
|
|
515
|
+
- Starter templates
|
|
516
|
+
- Scaffolding utilities
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
# Important Final Guidance
|
|
521
|
+
|
|
522
|
+
This repository is primarily intended for:
|
|
523
|
+
|
|
524
|
+
- AI retrieval
|
|
525
|
+
- deterministic engineering guidance
|
|
526
|
+
- reusable architectural consistency
|
|
527
|
+
|
|
528
|
+
Optimize for:
|
|
529
|
+
|
|
530
|
+
- clarity
|
|
531
|
+
- consistency
|
|
532
|
+
- composability
|
|
533
|
+
- maintainability
|
|
534
|
+
- AI adherence
|
|
535
|
+
|
|
536
|
+
Not for:
|
|
537
|
+
|
|
538
|
+
- excessive prose
|
|
539
|
+
- academic writing
|
|
540
|
+
- generalized enterprise abstraction
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BAD: Manual data fetching with useEffect
|
|
3
|
+
*
|
|
4
|
+
* Problems:
|
|
5
|
+
* - Race condition: if `userId` changes mid-fetch, the older response can overwrite the newer one
|
|
6
|
+
* - No caching: every mount triggers a fetch
|
|
7
|
+
* - No deduplication: two components mounting in parallel each fetch
|
|
8
|
+
* - Error state has no handling
|
|
9
|
+
* - No request cancellation on unmount
|
|
10
|
+
* - State sprawl: 3 useState calls to track what TanStack Query gives for free
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { useEffect, useState } from "react";
|
|
14
|
+
|
|
15
|
+
interface User {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
email: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface UserProfileProps {
|
|
22
|
+
userId: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function UserProfile({ userId }: UserProfileProps) {
|
|
26
|
+
const [user, setUser] = useState<User | null>(null);
|
|
27
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
28
|
+
// ✗ no error state — failures are silently swallowed below
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setIsLoading(true);
|
|
32
|
+
fetch(`/api/users/${userId}`)
|
|
33
|
+
.then((r) => r.json())
|
|
34
|
+
.then((data) => {
|
|
35
|
+
// ✗ if userId changed during this fetch, this overwrites the newer result
|
|
36
|
+
setUser(data);
|
|
37
|
+
setIsLoading(false);
|
|
38
|
+
});
|
|
39
|
+
// ✗ no .catch — network errors silently leave isLoading=true forever
|
|
40
|
+
// ✗ no AbortController — cancelled fetches still fire setState on unmount
|
|
41
|
+
}, [userId]);
|
|
42
|
+
|
|
43
|
+
if (isLoading) return <div>Loading…</div>;
|
|
44
|
+
if (!user) return null;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<article>
|
|
48
|
+
<h1>{user.name}</h1>
|
|
49
|
+
<p>{user.email}</p>
|
|
50
|
+
</article>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BAD: Syncing derived values into state with useEffect
|
|
3
|
+
*
|
|
4
|
+
* Problems:
|
|
5
|
+
* - `filtered` and `total` are duplicate state — they can drift from `items`/`search`
|
|
6
|
+
* - Extra render on every input change (state update → effect → state update → render)
|
|
7
|
+
* - More code, more bugs, no benefit over computing during render
|
|
8
|
+
* - Initial render shows stale values until the effect runs
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { useEffect, useState } from "react";
|
|
12
|
+
|
|
13
|
+
interface Item {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
price: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ItemListProps {
|
|
20
|
+
items: Item[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function ItemList({ items }: ItemListProps) {
|
|
24
|
+
const [search, setSearch] = useState("");
|
|
25
|
+
// ✗ derived values stored as state
|
|
26
|
+
const [filtered, setFiltered] = useState<Item[]>([]);
|
|
27
|
+
const [total, setTotal] = useState(0);
|
|
28
|
+
|
|
29
|
+
// ✗ effect syncs derived state — entirely unnecessary
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const result = items.filter((item) =>
|
|
32
|
+
item.name.toLowerCase().includes(search.toLowerCase()),
|
|
33
|
+
);
|
|
34
|
+
setFiltered(result);
|
|
35
|
+
setTotal(result.reduce((sum, item) => sum + item.price, 0));
|
|
36
|
+
}, [items, search]);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<section>
|
|
40
|
+
<label>
|
|
41
|
+
Search
|
|
42
|
+
<input
|
|
43
|
+
type="search"
|
|
44
|
+
value={search}
|
|
45
|
+
onChange={(event) => setSearch(event.target.value)}
|
|
46
|
+
/>
|
|
47
|
+
</label>
|
|
48
|
+
<p>
|
|
49
|
+
{filtered.length} items — total ${total.toFixed(2)}
|
|
50
|
+
</p>
|
|
51
|
+
<ul>
|
|
52
|
+
{filtered.map((item) => (
|
|
53
|
+
<li key={item.id}>
|
|
54
|
+
{item.name} — ${item.price.toFixed(2)}
|
|
55
|
+
</li>
|
|
56
|
+
))}
|
|
57
|
+
</ul>
|
|
58
|
+
</section>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BAD EXAMPLE: God component with multiple anti-patterns
|
|
3
|
+
*
|
|
4
|
+
* Anti-patterns demonstrated:
|
|
5
|
+
* - useEffect for data fetching (use TanStack Query instead)
|
|
6
|
+
* - useEffect for derived state (compute during render instead)
|
|
7
|
+
* - Giant single component (decompose instead)
|
|
8
|
+
* - No types / implicit any
|
|
9
|
+
* - No error handling
|
|
10
|
+
* - No loading state
|
|
11
|
+
* - No accessibility (clickable div, no labels, no semantic markup)
|
|
12
|
+
* - Index as key
|
|
13
|
+
* - Unhandled promise (missing await / .catch)
|
|
14
|
+
* - Defensive unnecessary memoization
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { useEffect, useMemo, useState } from "react";
|
|
18
|
+
|
|
19
|
+
// ✗ No types defined — all data is implicitly any
|
|
20
|
+
|
|
21
|
+
export default function Invoices() {
|
|
22
|
+
// ✗ Manual fetch state instead of TanStack Query
|
|
23
|
+
const [data, setData] = useState(null);
|
|
24
|
+
const [loading, setLoading] = useState(false);
|
|
25
|
+
|
|
26
|
+
// ✗ useEffect for data fetching — race conditions, no caching, no deduplication
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
setLoading(true);
|
|
29
|
+
fetch("/api/invoices")
|
|
30
|
+
.then((r) => r.json())
|
|
31
|
+
.then((d) => {
|
|
32
|
+
setData(d);
|
|
33
|
+
setLoading(false);
|
|
34
|
+
// ✗ No error handling — silently fails on network errors
|
|
35
|
+
});
|
|
36
|
+
}, []);
|
|
37
|
+
|
|
38
|
+
// ✗ useEffect for derived state — should be computed during render
|
|
39
|
+
const [total, setTotal] = useState(0);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
if (data) {
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
setTotal(data.reduce((sum, inv) => sum + inv.amount, 0));
|
|
44
|
+
}
|
|
45
|
+
}, [data]);
|
|
46
|
+
|
|
47
|
+
// ✗ Defensive memoization of a trivial computation
|
|
48
|
+
const label = useMemo(() => `Total: $${total}`, [total]);
|
|
49
|
+
|
|
50
|
+
// ✗ No loading state rendered to user
|
|
51
|
+
if (loading) return null;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
// ✗ No semantic markup — div soup
|
|
55
|
+
<div>
|
|
56
|
+
<div>{label}</div>
|
|
57
|
+
<div>
|
|
58
|
+
{/* ✗ Index as key — unstable, causes rendering bugs */}
|
|
59
|
+
{/* ✗ any type throughout */}
|
|
60
|
+
{(data as any)?.map((invoice: any, i: number) => (
|
|
61
|
+
<div
|
|
62
|
+
key={i}
|
|
63
|
+
// ✗ Clickable div — not keyboard accessible, not a button
|
|
64
|
+
onClick={() => window.location.href = `/invoices/${invoice.id}`}
|
|
65
|
+
style={{ cursor: "pointer" }}
|
|
66
|
+
>
|
|
67
|
+
{/* ✗ No accessible label, no semantic structure */}
|
|
68
|
+
<span>{invoice.title}</span>
|
|
69
|
+
<span>{invoice.status}</span>
|
|
70
|
+
<span>{invoice.amount}</span>
|
|
71
|
+
{/* ✗ Unhandled promise — fire and forget without .catch */}
|
|
72
|
+
<span onClick={() => fetch(`/api/invoices/${invoice.id}/archive`, { method: "POST" })}>
|
|
73
|
+
Archive
|
|
74
|
+
</span>
|
|
75
|
+
</div>
|
|
76
|
+
))}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|