@robosoft/skillhub-cli 0.1.2 → 0.3.3
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/CHANGELOG.md +26 -25
- package/README.md +162 -182
- package/bin/skillhub.mjs +722 -365
- package/docs/skillhub-cli-logic.md +114 -83
- package/package.json +8 -5
- package/skillhub-registry/CHANGELOG.md +65 -0
- package/skillhub-registry/CLAUDE.md +108 -0
- package/skillhub-registry/README.md +196 -16
- package/skillhub-registry/docs/cheat-sheet.md +272 -0
- package/skillhub-registry/docs/contributing.md +166 -0
- package/skillhub-registry/docs/cost-hygiene.md +175 -0
- package/skillhub-registry/docs/customization.md +321 -0
- package/skillhub-registry/docs/exception-process.md +194 -0
- package/skillhub-registry/docs/installation.md +277 -0
- package/skillhub-registry/domain/api.md +303 -0
- package/skillhub-registry/domain/frontend/web-app.md +17 -0
- package/skillhub-registry/domain/frontend-app.md +46 -0
- package/skillhub-registry/domain/frontend-architecture.md +126 -0
- package/skillhub-registry/rules/anti-patterns.md +95 -0
- package/skillhub-registry/rules/code-standards.md +182 -0
- package/skillhub-registry/rules/frontend/antipattern.md +21 -0
- package/skillhub-registry/rules/frontend/component-standards.md +10 -0
- package/skillhub-registry/rules/frontend-app.md +24 -0
- package/skillhub-registry/rules/general.md +51 -0
- package/skillhub-registry/skills/api/SKILL.md +167 -0
- package/skillhub-registry/skills/build/SKILL.md +114 -0
- package/skillhub-registry/skills/fast/SKILL.md +56 -0
- package/skillhub-registry/skills/feature-dev/SKILL.md +166 -0
- package/skillhub-registry/skills/frontend/app/SKILL.md +28 -0
- package/skillhub-registry/skills/frontend/app/skill.json +10 -0
- package/skillhub-registry/skills/frontend/app/templates/feature/{{kebabName}}.tsx.hbs +11 -0
- package/skillhub-registry/skills/frontend-app/SKILL.md +48 -0
- package/skillhub-registry/skills/frontend-app/skill.json +11 -0
- package/skillhub-registry/skills/frontend-app/templates/feature/{{kebabName}}.tsx.hbs +11 -0
- package/skillhub-registry/skills/performance/SKILL.md +168 -0
- package/skillhub-registry/skills/react/SKILL.md +224 -0
- package/skillhub-registry/skills/refactor/SKILL.md +149 -0
- package/skillhub-registry/skills/review/SKILL.md +199 -0
- package/skillhub-registry/skills/strict/SKILL.md +74 -0
- package/skillhub-registry/skills/testing/SKILL.md +132 -0
- package/skillhub-registry/accessibility-review/1.0.0/SKILL.md +0 -22
- package/skillhub-registry/accessibility-review/1.0.0/checklist/ui-review.md +0 -8
- package/skillhub-registry/accessibility-review/1.0.0/skill.json +0 -9
- package/skillhub-registry/nextjs-clean-architecture/1.0.0/SKILL.md +0 -37
- package/skillhub-registry/nextjs-clean-architecture/1.0.0/checklist/definition-of-done.md +0 -9
- package/skillhub-registry/nextjs-clean-architecture/1.0.0/rules/folder-structure.md +0 -7
- package/skillhub-registry/nextjs-clean-architecture/1.0.0/skill.json +0 -9
- package/skillhub-registry/shadcn-crud-generator/1.0.0/SKILL.md +0 -25
- package/skillhub-registry/shadcn-crud-generator/1.0.0/skill.json +0 -9
- package/skillhub-registry/shadcn-crud-generator/1.0.0/templates/feature/actions.ts.hbs +0 -16
- package/skillhub-registry/shadcn-crud-generator/1.0.0/templates/feature/page.tsx.hbs +0 -13
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# Org API Conventions
|
|
2
|
+
|
|
3
|
+
**Status:** Org-specific decisions for our API surfaces. Layers on top of universal rules in `skills/api/SKILL.md`.
|
|
4
|
+
**Last updated:** 2026-05-06
|
|
5
|
+
**Owner:** [Your name / team]
|
|
6
|
+
|
|
7
|
+
This file documents *our* specific API conventions — the choices we've made, where the universal skill says "pick one, be consistent."
|
|
8
|
+
|
|
9
|
+
> **For developers:** When working on our APIs, both this file and `skills/api/SKILL.md` apply. Universal rules are the baseline; this file is the override.
|
|
10
|
+
|
|
11
|
+
> **For Claude:** This file is loaded only when working in our codebase or on our APIs. Treat its contents as authoritative for any conflict with the universal skill.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## How to Use This File
|
|
16
|
+
|
|
17
|
+
This is a **living document**. When the team decides on a new API convention, it gets added here. When a convention changes, it gets updated here. PRs should update this file when they introduce or modify a convention.
|
|
18
|
+
|
|
19
|
+
The sections below are templates — fill in your org's actual decisions, or write `[Not yet decided]` until you do.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## JSON Field Naming
|
|
24
|
+
|
|
25
|
+
**Our convention:** `[camelCase | snake_case | PascalCase]`
|
|
26
|
+
|
|
27
|
+
**Example:**
|
|
28
|
+
```json
|
|
29
|
+
|
|
30
|
+
{
|
|
31
|
+
"userId": "123",
|
|
32
|
+
"createdAt": "2026-05-06T12:00:00Z"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
**Rationale:** [Why we picked this — e.g., "matches our JS clients" or "consistency with database column names"]
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Error Response Envelope
|
|
40
|
+
|
|
41
|
+
**Our shape:**
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
|
|
45
|
+
{
|
|
46
|
+
"error": {
|
|
47
|
+
"code": "[example: INVALID_INPUT]",
|
|
48
|
+
"message": "[example: Human-readable description]",
|
|
49
|
+
"details": [
|
|
50
|
+
{ "field": "[example: email]", "issue": "[example: must be valid]" }
|
|
51
|
+
],
|
|
52
|
+
"request_id": "[example: req_abc123]"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
**Error code naming:** `SCREAMING_SNAKE_CASE`, prefixed by domain when ambiguous (e.g., `AUTH_INVALID_TOKEN`, `USER_NOT_FOUND`).
|
|
57
|
+
|
|
58
|
+
**Stable error codes maintained at:** `[link to error code registry, if any]`
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Authentication
|
|
63
|
+
|
|
64
|
+
**Method:** [Bearer JWT | API Key | Session Cookie | OAuth | etc.]
|
|
65
|
+
|
|
66
|
+
**Header:** `[example: Authorization: Bearer <token>]`
|
|
67
|
+
|
|
68
|
+
**Token lifetime:** [e.g., access token: 1h, refresh token: 30d]
|
|
69
|
+
|
|
70
|
+
**Where tokens come from:** [link to auth service docs]
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Versioning
|
|
75
|
+
|
|
76
|
+
**Strategy:** [URI path | Header | Accept header]
|
|
77
|
+
|
|
78
|
+
**Current version:** `[v1 | v2 | etc.]`
|
|
79
|
+
|
|
80
|
+
**Deprecated versions:** [List + sunset dates]
|
|
81
|
+
|
|
82
|
+
**Breaking change policy:** [e.g., "minimum 6-month deprecation window"]
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Pagination
|
|
87
|
+
|
|
88
|
+
**Style:** [cursor-based | offset-based | hybrid]
|
|
89
|
+
|
|
90
|
+
**Default page size:** [e.g., 20]
|
|
91
|
+
**Max page size:** [e.g., 100]
|
|
92
|
+
|
|
93
|
+
**Response shape:**
|
|
94
|
+
```json
|
|
95
|
+
|
|
96
|
+
{
|
|
97
|
+
"data": [ ... ],
|
|
98
|
+
"pagination": {
|
|
99
|
+
"next_cursor": "[example value]",
|
|
100
|
+
"has_more": true
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Org API Conventions
|
|
105
|
+
|
|
106
|
+
**Status:** Org-specific decisions for our API surfaces. Layers on top of universal rules in `skills/api/SKILL.md`.
|
|
107
|
+
**Last updated:** 2026-05-06
|
|
108
|
+
**Owner:** [Your name / team]
|
|
109
|
+
|
|
110
|
+
This file documents *our* specific API conventions — the choices we've made, where the universal skill says "pick one, be consistent."
|
|
111
|
+
|
|
112
|
+
> **For developers:** When working on our APIs, both this file and `skills/api/SKILL.md` apply. Universal rules are the baseline; this file is the override.
|
|
113
|
+
|
|
114
|
+
> **For Claude:** This file is loaded only when working in our codebase or on our APIs. Treat its contents as authoritative for any conflict with the universal skill.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## How to Use This File
|
|
119
|
+
|
|
120
|
+
This is a **living document**. When the team decides on a new API convention, it gets added here. When a convention changes, it gets updated here. PRs should update this file when they introduce or modify a convention.
|
|
121
|
+
|
|
122
|
+
The sections below are templates — fill in your org's actual decisions, or write `[Not yet decided]` until you do.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## JSON Field Naming
|
|
127
|
+
|
|
128
|
+
**Our convention:** `[camelCase | snake_case | PascalCase]`
|
|
129
|
+
|
|
130
|
+
**Example:**
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"userId": "123",
|
|
134
|
+
"createdAt": "2026-05-06T12:00:00Z"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Rationale:** [Why we picked this — e.g., "matches our JS clients" or "consistency with database column names"]
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Error Response Envelope
|
|
143
|
+
|
|
144
|
+
**Our shape:**
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"error": {
|
|
149
|
+
"code": "[example: INVALID_INPUT]",
|
|
150
|
+
"message": "[example: Human-readable description]",
|
|
151
|
+
"details": [
|
|
152
|
+
{ "field": "[example: email]", "issue": "[example: must be valid]" }
|
|
153
|
+
],
|
|
154
|
+
"request_id": "[example: req_abc123]"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Error code naming:** `SCREAMING_SNAKE_CASE`, prefixed by domain when ambiguous (e.g., `AUTH_INVALID_TOKEN`, `USER_NOT_FOUND`).
|
|
160
|
+
|
|
161
|
+
**Stable error codes maintained at:** `[link to error code registry, if any]`
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Authentication
|
|
166
|
+
|
|
167
|
+
**Method:** [Bearer JWT | API Key | Session Cookie | OAuth | etc.]
|
|
168
|
+
|
|
169
|
+
**Header:** `[example: Authorization: Bearer <token>]`
|
|
170
|
+
|
|
171
|
+
**Token lifetime:** [e.g., access token: 1h, refresh token: 30d]
|
|
172
|
+
|
|
173
|
+
**Where tokens come from:** [link to auth service docs]
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Versioning
|
|
178
|
+
|
|
179
|
+
**Strategy:** [URI path | Header | Accept header]
|
|
180
|
+
|
|
181
|
+
**Current version:** `[v1 | v2 | etc.]`
|
|
182
|
+
|
|
183
|
+
**Deprecated versions:** [List + sunset dates]
|
|
184
|
+
|
|
185
|
+
**Breaking change policy:** [e.g., "minimum 6-month deprecation window"]
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Pagination
|
|
190
|
+
|
|
191
|
+
**Style:** [cursor-based | offset-based | hybrid]
|
|
192
|
+
|
|
193
|
+
**Default page size:** [e.g., 20]
|
|
194
|
+
**Max page size:** [e.g., 100]
|
|
195
|
+
|
|
196
|
+
**Response shape:**
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"data": [ ... ],
|
|
200
|
+
"pagination": {
|
|
201
|
+
"next_cursor": "[example value]",
|
|
202
|
+
"has_more": true
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Rate Limiting
|
|
210
|
+
|
|
211
|
+
**Default limit:** [e.g., 100 requests / minute / user]
|
|
212
|
+
|
|
213
|
+
**Limit headers we return:**
|
|
214
|
+
- `X-RateLimit-Limit: 100`
|
|
215
|
+
- `X-RateLimit-Remaining: 87`
|
|
216
|
+
- `X-RateLimit-Reset: 1715000000`
|
|
217
|
+
|
|
218
|
+
**Endpoints with stricter limits:** [list, e.g., `/auth/login`: 5/min]
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Idempotency
|
|
223
|
+
|
|
224
|
+
**Idempotency-Key support:** [Which endpoints accept it — typically payment, order creation, anything destructive]
|
|
225
|
+
|
|
226
|
+
**Key format:** [e.g., UUID v4]
|
|
227
|
+
|
|
228
|
+
**Retention window:** [e.g., 24 hours]
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Standard Response Headers
|
|
233
|
+
|
|
234
|
+
Every response from our APIs includes:
|
|
235
|
+
|
|
236
|
+
- `X-Request-ID: <uuid>` — for tracing in logs
|
|
237
|
+
- `[Other org-standard headers]`
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Endpoints We Never Expose
|
|
242
|
+
|
|
243
|
+
Some endpoints exist for internal use only. These must:
|
|
244
|
+
|
|
245
|
+
- Be on a separate base URL or behind internal-only auth
|
|
246
|
+
- Never be linked from public docs
|
|
247
|
+
- [List specific endpoints / patterns here as they get added]
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Webhook Conventions
|
|
252
|
+
|
|
253
|
+
**Signing:** [HMAC-SHA256 with shared secret in `X-Org-Signature` header]
|
|
254
|
+
|
|
255
|
+
**Retry policy:** [e.g., "5 retries with exponential backoff over 24h"]
|
|
256
|
+
|
|
257
|
+
**Payload includes:**
|
|
258
|
+
- `event_id` (UUID)
|
|
259
|
+
- `event_type` (dot-namespaced, e.g., `order.created`)
|
|
260
|
+
- `timestamp` (ISO-8601)
|
|
261
|
+
- `data` (event-specific payload)
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Common Patterns Across Our APIs
|
|
266
|
+
|
|
267
|
+
[As your team converges on patterns, document them here. Examples:]
|
|
268
|
+
|
|
269
|
+
- **Soft deletes** — we use `deleted_at` timestamps, not hard deletes
|
|
270
|
+
- **Timestamps** — all timestamps are ISO-8601 strings in UTC
|
|
271
|
+
- **IDs** — prefixed by resource type (`user_abc123`, `order_xyz789`) — Stripe-style
|
|
272
|
+
- **Currency** — always integer cents, never floating-point dollars
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Anti-Patterns Specific to Our Codebase
|
|
277
|
+
|
|
278
|
+
[Things that have gone wrong before and we want to prevent. Examples:]
|
|
279
|
+
|
|
280
|
+
- ❌ Don't add `?debug=true` to expose internal details — even gated behind staff auth
|
|
281
|
+
- ❌ Don't return raw database errors in responses
|
|
282
|
+
- ❌ Don't include user emails in URL paths
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Open Questions / Pending Decisions
|
|
287
|
+
|
|
288
|
+
Document things the team hasn't decided yet, so devs know to ask:
|
|
289
|
+
|
|
290
|
+
- [ ] [Example: "GraphQL adoption — currently REST-only, evaluating"]
|
|
291
|
+
- [ ] [Example: "Federation pattern when we split services"]
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## How to Propose a Change to These Conventions
|
|
296
|
+
|
|
297
|
+
See `docs/exception-process.md` (or your org's standard).
|
|
298
|
+
|
|
299
|
+
Quick version:
|
|
300
|
+
1. Open a PR modifying this file
|
|
301
|
+
2. Tag the API working group
|
|
302
|
+
3. Discussion happens in PR review
|
|
303
|
+
4. Merge requires approval from [designated approvers]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Frontend Web App Domain Knowledge
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This domain file describes common frontend web-app expectations for SkillHub-generated work.
|
|
6
|
+
|
|
7
|
+
## Architecture Expectations
|
|
8
|
+
|
|
9
|
+
- Use a feature-first structure for business modules.
|
|
10
|
+
- Keep infrastructure concerns in `lib`, `services`, or adapter folders.
|
|
11
|
+
- Keep design-system components separate from feature components.
|
|
12
|
+
- Use typed API contracts and schema validation where possible.
|
|
13
|
+
- Align with the project router, state, styling, and testing conventions before adding new patterns.
|
|
14
|
+
|
|
15
|
+
## Product Expectations
|
|
16
|
+
|
|
17
|
+
Every production page should consider authentication state, permissions, loading state, empty state, error state, responsive layout, and accessibility.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Frontend App Domain Knowledge
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
This domain file captures reusable product and engineering knowledge for frontend application work.
|
|
6
|
+
|
|
7
|
+
## Standard Mental Model
|
|
8
|
+
|
|
9
|
+
A production frontend feature usually has these parts:
|
|
10
|
+
|
|
11
|
+
- Route or screen entry
|
|
12
|
+
- Data fetching and mutation layer
|
|
13
|
+
- UI components
|
|
14
|
+
- Validation and error handling
|
|
15
|
+
- Loading, empty, success, and failure states
|
|
16
|
+
- Accessibility and responsive behavior
|
|
17
|
+
- Analytics or event tracking when required
|
|
18
|
+
|
|
19
|
+
## Architecture Guidance
|
|
20
|
+
|
|
21
|
+
For Next.js or React apps, prefer:
|
|
22
|
+
|
|
23
|
+
```txt
|
|
24
|
+
src/
|
|
25
|
+
app/ or pages/
|
|
26
|
+
features/
|
|
27
|
+
feature-name/
|
|
28
|
+
components/
|
|
29
|
+
hooks/
|
|
30
|
+
services/
|
|
31
|
+
types.ts
|
|
32
|
+
index.ts
|
|
33
|
+
shared/
|
|
34
|
+
components/
|
|
35
|
+
hooks/
|
|
36
|
+
utils/
|
|
37
|
+
services/
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Common Risks
|
|
41
|
+
|
|
42
|
+
- Building a beautiful screen with fake data and no integration path
|
|
43
|
+
- Adding global state for local form state
|
|
44
|
+
- Ignoring mobile layout until QA finds it, the traditional frontend festival
|
|
45
|
+
- Hardcoding API contracts instead of using typed boundaries
|
|
46
|
+
- Skipping loading and error states because the happy path looked cute
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Frontend Architecture
|
|
2
|
+
|
|
3
|
+
**Status:** Standard for tech-enabled projects; recommended for others
|
|
4
|
+
**Last updated:** 2026-05-06
|
|
5
|
+
**Owner:** Raj Shah
|
|
6
|
+
|
|
7
|
+
> **TL;DR:** Organize by features, not layers. Each feature is a folder with components, hooks, services, and a public API via `index.ts`. Shared code lives in `shared/`.
|
|
8
|
+
|
|
9
|
+
This document describes the recommended folder structure and module boundaries for React projects. It is the standard on our tech-enabled projects and a recommended pattern others can adopt when refactoring or starting new projects. This is a target structure that we're working toward — not every project follows it today, and that's okay.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Why This Structure
|
|
14
|
+
|
|
15
|
+
Feature-based organization has proven to scale better than layer-based (all components in one folder, all services in another) as projects grow:
|
|
16
|
+
|
|
17
|
+
- **Ownership is localized.** When you own a feature, all its code lives in one place. Changes don't ripple across the codebase.
|
|
18
|
+
- **Module boundaries prevent spaghetti.** Public APIs via `index.ts` enforce what can and can't be imported, catching circular dependencies early.
|
|
19
|
+
- **Shared code is visible.** When logic is used by 2+ features, it gets promoted to `shared/` and stops being duplicated.
|
|
20
|
+
- **Easier to delete.** When a feature ships or gets retired, removing a feature folder is clean. Removing scattered services and components is error-prone.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## The Recommended Folder Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
src/
|
|
28
|
+
app/
|
|
29
|
+
Entry point, routing, top-level providers (auth, theme, query client).
|
|
30
|
+
The integration layer — not a place for business logic.
|
|
31
|
+
|
|
32
|
+
features/
|
|
33
|
+
<feature-name>/
|
|
34
|
+
components/ UI components specific to this feature.
|
|
35
|
+
hooks/ State, side effects, data fetching — feature-scoped.
|
|
36
|
+
services/ API calls and business logic for this feature.
|
|
37
|
+
types.ts Feature-level type definitions.
|
|
38
|
+
index.ts Public API — only exports intended for outside the feature.
|
|
39
|
+
|
|
40
|
+
shared/
|
|
41
|
+
components/ Reusable UI across features (Button, Modal, etc.).
|
|
42
|
+
hooks/ Reusable stateful logic (useFetch, useLocalStorage, etc.).
|
|
43
|
+
utils/ Pure utility functions (formatDate, parseJson, etc.).
|
|
44
|
+
constants/ Shared magic-value-free constants.
|
|
45
|
+
config/ Centralized environment config (see rules/code-standards.md).
|
|
46
|
+
services/ Shared infrastructure (HTTP client wrapper, analytics SDK setup).
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Each directory's purpose:**
|
|
50
|
+
|
|
51
|
+
- **`app/`** — Application shell. Routes, top-level component tree, global providers. No business logic lives here.
|
|
52
|
+
- **`features/<feature-name>/`** — A feature is an independently useful piece of the app (a user dashboard, a checkout flow, a settings page). Folder structure mirrors the feature's organization.
|
|
53
|
+
- **`shared/`** — Code used across multiple features. The first place to check before duplicating.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Module Boundaries (Strong Recommendations)
|
|
58
|
+
|
|
59
|
+
These boundaries make refactoring local and prevent the codebase from becoming a tangle:
|
|
60
|
+
|
|
61
|
+
- **Features should not import from other features directly.** If Feature A needs something from Feature B, either:
|
|
62
|
+
- The code goes to `shared/` if it's truly shared.
|
|
63
|
+
- Feature B exports it via its `index.ts` as a public API.
|
|
64
|
+
- Or it's a sign that the feature boundary is wrong and should be reconsidered.
|
|
65
|
+
|
|
66
|
+
- **Only `index.ts` is the public API.** Importing `features/checkout/utils/calculateTax.ts` from outside is a code smell — that's an implementation detail. The feature's `index.ts` should decide what's public.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// features/checkout/index.ts
|
|
70
|
+
export { CheckoutForm } from './components/CheckoutForm';
|
|
71
|
+
export { useCheckoutState } from './hooks/useCheckoutState';
|
|
72
|
+
export type { Order } from './types';
|
|
73
|
+
// calculateTax stays private — not exported
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- **Shared code in `shared/`.** If a utility, component, or hook is used by 2+ features, it doesn't live in either feature — it's promoted to `shared/`. This prevents duplication and makes updates centralized.
|
|
77
|
+
|
|
78
|
+
- **`app/` is the integration layer.** Routing, providers, the root component tree. Business logic (state, side effects, calculations) does not live in `app/`. It lives in features or shared, then integrated in `app/`.
|
|
79
|
+
|
|
80
|
+
> **Why:** These boundaries make refactoring local. When a feature's internal structure changes, only that feature's code needs to be updated. Without boundaries, refactoring becomes a codebase-wide hunt, and features start depending on each other's internals instead of their public APIs.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## When You Don't Need This Structure
|
|
85
|
+
|
|
86
|
+
Smaller projects and prototypes should use simpler structures:
|
|
87
|
+
|
|
88
|
+
- **Small projects** (~1-2 features, <~10 components) don't need feature folders. A flat `src/components/` and `src/services/` is clearer.
|
|
89
|
+
- **Throwaway prototypes** don't need architectural discipline — they earn their complexity at real scale.
|
|
90
|
+
- **The structure pays for itself around ~3+ features and ~50+ components.** Below that threshold, simpler is better. Premature structure is its own anti-pattern.
|
|
91
|
+
|
|
92
|
+
If you're building something small, keep it flat until the need arises.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Migration Guidance
|
|
97
|
+
|
|
98
|
+
For projects that don't currently follow this structure:
|
|
99
|
+
|
|
100
|
+
- **Don't refactor wholesale.** Converting an entire codebase to feature-based organization is a major project, not a cleanup task.
|
|
101
|
+
- **Adopt for new features.** As you build new features, use the folder structure. New code sets a pattern.
|
|
102
|
+
- **Refactor on touch.** When doing substantive work in an existing feature, consider promoting it to the structure as part of the change.
|
|
103
|
+
- **Convergence is gradual.** Over time, the codebase drifts toward the structure without a single "big migration" effort.
|
|
104
|
+
|
|
105
|
+
The goal is to make refactoring normal, not to land on a perfect structure immediately.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## What This Document Does NOT Cover
|
|
110
|
+
|
|
111
|
+
This file is one piece of the architecture picture. Related decisions are documented elsewhere:
|
|
112
|
+
|
|
113
|
+
- **React conventions** (component structure, hooks, state management patterns, accessibility) — see [`skills/react/SKILL.md`](../skills/react/SKILL.md)
|
|
114
|
+
- **API design and contract conventions** — see [`skills/api/SKILL.md`](../skills/api/SKILL.md) and [`domain/api.md`](api.md)
|
|
115
|
+
- **Styling system** (CSS-in-JS, Tailwind, BEM, etc.) — not yet standardized; project-specific for now
|
|
116
|
+
- **State management library** (Redux, Zustand, Jotai, Signals, etc.) — not yet standardized; project-specific for now
|
|
117
|
+
|
|
118
|
+
When styling and state-management decisions are standardized, they'll be added here and in the skills.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Where to Go from Here
|
|
123
|
+
|
|
124
|
+
- **React conventions and patterns** — [`skills/react/SKILL.md`](../skills/react/SKILL.md)
|
|
125
|
+
- **Proposing a change to this standard** — [`docs/contributing.md`](../docs/contributing.md)
|
|
126
|
+
- **Questions or feedback** — reach out to Raj Shah
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Anti-Patterns
|
|
2
|
+
|
|
3
|
+
Status: **Universal — applies to all coding tasks regardless of language**
|
|
4
|
+
Last updated: 2026-05-06
|
|
5
|
+
Owner: [Raj Shah]
|
|
6
|
+
|
|
7
|
+
Patterns that consistently cause problems. Each entry explains what it is, why it's harmful, and what to do instead. Language-specific anti-patterns belong in the relevant skill file (e.g., React-specific issues in `skills/react/SKILL.md`).
|
|
8
|
+
|
|
9
|
+
## God Objects / God Functions
|
|
10
|
+
|
|
11
|
+
**What it is:** A single function, class, or module that does many unrelated things — handling validation, transformation, persistence, and notification all in one place.
|
|
12
|
+
|
|
13
|
+
**Why it's harmful:** Touching one responsibility risks breaking the others. Tests become large and brittle. Reviewers can't tell what the change is actually about.
|
|
14
|
+
|
|
15
|
+
**Do instead:** Each unit of code owns *one* clear job. If you struggle to name a function in 3-5 words without `and`, it's doing too much.
|
|
16
|
+
|
|
17
|
+
## Premature Abstraction
|
|
18
|
+
|
|
19
|
+
**What it is:** Building generic, configurable, "flexible" code before there are concrete use cases that require it.
|
|
20
|
+
|
|
21
|
+
**Why it's harmful:** The flexibility usually doesn't match what's actually needed later. You end up with abstract layers that solve hypothetical problems while making real problems harder.
|
|
22
|
+
|
|
23
|
+
**Do instead:** Write the concrete version first. Generalize only when you have **3 real use cases** with genuinely shared intent — not just shared syntax.
|
|
24
|
+
|
|
25
|
+
## Speculative Flexibility
|
|
26
|
+
|
|
27
|
+
**What it is:** Adding configuration options, plugins, hooks, or extension points "in case we need them later."
|
|
28
|
+
|
|
29
|
+
**Why it's harmful:** Every option doubles the testing surface. Most options are never used. The ones that are used often need different shapes than originally guessed.
|
|
30
|
+
|
|
31
|
+
**Do instead:** Build for *current* needs. Adding configuration later is cheaper than removing it.
|
|
32
|
+
|
|
33
|
+
## Copy-Paste Duplication
|
|
34
|
+
|
|
35
|
+
**What it is:** Copying a block of code and tweaking small parts, instead of factoring out shared logic.
|
|
36
|
+
|
|
37
|
+
**Why it's harmful:** Bugs found in one copy don't get fixed in the others. Small tweaks accumulate into divergent versions of "the same" logic.
|
|
38
|
+
|
|
39
|
+
**Do instead:** On the *third* occurrence, extract a shared helper. Before that, leave it alone — premature DRY-ing creates the wrong abstraction.
|
|
40
|
+
|
|
41
|
+
## Magic Values
|
|
42
|
+
|
|
43
|
+
**What it is:** Numeric or string literals scattered through code with no explanation (`if (x > 17)`, `setTimeout(fn, 5000)`).
|
|
44
|
+
|
|
45
|
+
**Why it's harmful:** Readers must guess intent. Changing the value requires hunting through the codebase. Same value used in different places may mean different things.
|
|
46
|
+
|
|
47
|
+
**Do instead:** Extract to a named constant whose name explains the *meaning*, not the *value*.
|
|
48
|
+
|
|
49
|
+
## Inline Complex Logic
|
|
50
|
+
|
|
51
|
+
**What it is:** Cramming complex expressions, conditional chains, or transformations directly inside templates, JSX, return statements, or function arguments.
|
|
52
|
+
|
|
53
|
+
**Why it's harmful:** Hard to read, impossible to debug step-by-step, and breaks the visual structure of the surrounding code.
|
|
54
|
+
|
|
55
|
+
**Do instead:** Extract complex expressions into named variables or helper functions before the place they're used.
|
|
56
|
+
|
|
57
|
+
## Deeply Chained Conditionals
|
|
58
|
+
|
|
59
|
+
**What it is:** Nested ternaries, long `if/else if/else if` chains, or boolean expressions with 5+ operands.
|
|
60
|
+
|
|
61
|
+
**Why it's harmful:** Readers can't hold the logic in their head. Adding a new branch is risky. The "edge case" you missed is buried somewhere in the chain.
|
|
62
|
+
|
|
63
|
+
**Do instead:** Use early returns, lookup tables/maps, or split into well-named predicate functions.
|
|
64
|
+
|
|
65
|
+
## Silent Error Swallowing
|
|
66
|
+
|
|
67
|
+
**What it is:** Catching errors and doing nothing with them. Empty catch blocks, ignored promise rejections, unchecked return codes.
|
|
68
|
+
|
|
69
|
+
**Why it's harmful:** Failures become invisible. Bugs reach production and surface later as data corruption or mysterious behavior with no logs to trace.
|
|
70
|
+
|
|
71
|
+
**Do instead:** Always log, transform, retry, or propagate. If you genuinely want to ignore an error, leave a comment explaining why.
|
|
72
|
+
|
|
73
|
+
## Optimization Without Measurement
|
|
74
|
+
|
|
75
|
+
**What it is:** Adding caches, memoization, indices, or "performance" code without first measuring that there's a real bottleneck.
|
|
76
|
+
|
|
77
|
+
**Why it's harmful:** Adds complexity for imagined gains. Often the optimization makes things slower, breaks correctness, or hides a different bug. Real bottlenecks are rarely where you guess they are.
|
|
78
|
+
|
|
79
|
+
**Do instead:** Profile first. Optimize only proven hot paths. Document the measured before/after numbers.
|
|
80
|
+
|
|
81
|
+
## Comments That Restate the Code
|
|
82
|
+
|
|
83
|
+
**What it is:** Comments that translate code into English without adding information (`// increment counter` above `counter++`).
|
|
84
|
+
|
|
85
|
+
**Why it's harmful:** Adds noise. Goes stale when the code changes. Trains readers to ignore comments.
|
|
86
|
+
|
|
87
|
+
**Do instead:** Comments should explain *why* — context, constraints, decisions, non-obvious trade-offs. Delete comments that just describe *what*.
|
|
88
|
+
|
|
89
|
+
## Scope Creep in Edits
|
|
90
|
+
|
|
91
|
+
**What it is:** Refactoring unrelated code, renaming things, or "fixing" tangential issues while making a focused change.
|
|
92
|
+
|
|
93
|
+
**Why it's harmful:** Inflates diffs, makes review impossible, and mixes risky changes with safe ones. Reviewers can't approve the intended change without also approving everything else.
|
|
94
|
+
|
|
95
|
+
**Do instead:** Stay in scope. If you spot an unrelated issue, mention it at the end of your response — don't fix it unsolicited.
|