triples-agentic 2.4.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 +326 -0
- package/docs/workflow.md +163 -0
- package/install.sh +98 -0
- package/package.json +54 -0
- package/src/agents/README.md +85 -0
- package/src/agents/jiwoo-prd.md +84 -0
- package/src/agents/kaede-backend.md +95 -0
- package/src/agents/kotone-flutter.md +100 -0
- package/src/agents/lynn-testcase.md +92 -0
- package/src/agents/nakyoung-tasks.md +89 -0
- package/src/agents/seoyeon.md +76 -0
- package/src/agents/shion-qa.md +89 -0
- package/src/agents/sohyun-ios.md +97 -0
- package/src/agents/yeonji-android.md +98 -0
- package/src/agents/yooyeon-rfc.md +82 -0
- package/src/agents/yubin-frontend.md +88 -0
- package/src/bin/setup.js +640 -0
- package/src/hooks/README.md +102 -0
- package/src/hooks/dangerous-commands.json +33 -0
- package/src/hooks/dangerous-commands.md +18 -0
- package/src/knowledge/README.md +129 -0
- package/src/knowledge/general/boy-scout-rule.md +13 -0
- package/src/knowledge/general/composition-over-inheritance.md +14 -0
- package/src/knowledge/general/dry.md +14 -0
- package/src/knowledge/general/fail-fast.md +13 -0
- package/src/knowledge/general/kiss.md +15 -0
- package/src/knowledge/general/least-surprise.md +13 -0
- package/src/knowledge/general/slap.md +29 -0
- package/src/knowledge/general/solid.md +44 -0
- package/src/knowledge/general/tdd.md +76 -0
- package/src/knowledge/general/yagni.md +12 -0
- package/src/knowledge/mobile/android/android-architecture.md +83 -0
- package/src/knowledge/mobile/android/android-platform.md +60 -0
- package/src/knowledge/mobile/android/kotlin-concurrency.md +75 -0
- package/src/knowledge/mobile/android/kotlin-core.md +88 -0
- package/src/knowledge/mobile/flutter/dart-async.md +93 -0
- package/src/knowledge/mobile/flutter/dart-core.md +97 -0
- package/src/knowledge/mobile/flutter/flutter-architecture.md +88 -0
- package/src/knowledge/mobile/flutter/flutter-platform.md +79 -0
- package/src/knowledge/mobile/ios/ios-architecture.md +88 -0
- package/src/knowledge/mobile/ios/ios-platform.md +66 -0
- package/src/knowledge/mobile/ios/swift-concurrency.md +99 -0
- package/src/knowledge/mobile/ios/swift-core.md +79 -0
- package/src/knowledge/planning/architecture-database.md +47 -0
- package/src/knowledge/planning/architecture-patterns.md +64 -0
- package/src/knowledge/planning/architecture-security.md +61 -0
- package/src/knowledge/planning/estimation.md +82 -0
- package/src/knowledge/planning/orchestration.md +70 -0
- package/src/knowledge/planning/prd-quality-gates.md +38 -0
- package/src/knowledge/planning/prd-writing.md +59 -0
- package/src/knowledge/planning/product-principles.md +48 -0
- package/src/knowledge/planning/product-prioritization.md +45 -0
- package/src/knowledge/planning/rfc-quality-gates.md +38 -0
- package/src/knowledge/planning/rfc-writing.md +81 -0
- package/src/knowledge/planning/task-decomposition.md +61 -0
- package/src/knowledge/planning/task-readiness.md +64 -0
- package/src/knowledge/quality/qa-execution.md +55 -0
- package/src/knowledge/quality/qa-reporting.md +71 -0
- package/src/knowledge/quality/test-case-quality.md +61 -0
- package/src/knowledge/quality/test-case-writing.md +76 -0
- package/src/knowledge/quality/testing-strategy.md +70 -0
- package/src/knowledge/quality/testing-types.md +84 -0
- package/src/knowledge/web/backend/api-design.md +74 -0
- package/src/knowledge/web/backend/api-security.md +54 -0
- package/src/knowledge/web/backend/backend-security.md +84 -0
- package/src/knowledge/web/backend/backend-structure.md +78 -0
- package/src/knowledge/web/frontend/frontend-components.md +49 -0
- package/src/knowledge/web/frontend/frontend-performance.md +41 -0
- package/src/knowledge/web/frontend/frontend-state.md +59 -0
- package/src/knowledge/web/frontend/web-accessibility.md +51 -0
- package/src/knowledge/web/frontend/web-performance.md +51 -0
- package/src/knowledge/web/frontend/web-security.md +59 -0
- package/src/templates/prd.md +109 -0
- package/src/templates/rfc.md +156 -0
- package/src/templates/task-breakdown.md +172 -0
- package/src/templates/test-case.md +157 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-types
|
|
3
|
+
description: Unit, integration, and E2E test types — what to test, recommended tools, and platform-specific frameworks
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Testing Types & Tools
|
|
7
|
+
|
|
8
|
+
## Unit Tests
|
|
9
|
+
|
|
10
|
+
Test a single function/class in complete isolation. Use mocks/stubs for dependencies.
|
|
11
|
+
|
|
12
|
+
**What to unit test**:
|
|
13
|
+
- Business logic functions
|
|
14
|
+
- Data transformation / mapping functions
|
|
15
|
+
- Input validation rules
|
|
16
|
+
- State machine transitions
|
|
17
|
+
- Error handling paths
|
|
18
|
+
- Edge cases (empty, null, boundary values)
|
|
19
|
+
|
|
20
|
+
**What NOT to unit test**:
|
|
21
|
+
- Framework internals
|
|
22
|
+
- Simple getters/setters with no logic
|
|
23
|
+
- Third-party library behaviour
|
|
24
|
+
|
|
25
|
+
### Tools by Platform
|
|
26
|
+
|
|
27
|
+
| Platform | Framework | Assertion / Mocking |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| Web (JS/TS) | Vitest / Jest | Testing Library, Mockito |
|
|
30
|
+
| Node.js | Vitest / Jest | Supertest (HTTP) |
|
|
31
|
+
| Android | JUnit 5 | Mockk, Turbine (Flow) |
|
|
32
|
+
| iOS | XCTest / Swift Testing | Protocols + fakes |
|
|
33
|
+
| Flutter | flutter_test | mockito / mocktail |
|
|
34
|
+
|
|
35
|
+
## Integration Tests
|
|
36
|
+
|
|
37
|
+
Test that two or more components work correctly together.
|
|
38
|
+
|
|
39
|
+
**What to integration test**:
|
|
40
|
+
- API endpoint handler + service + database (real DB in test mode)
|
|
41
|
+
- Authentication middleware + protected route
|
|
42
|
+
- Webhook receiver + event handler
|
|
43
|
+
|
|
44
|
+
**Common patterns**:
|
|
45
|
+
- **Test DB**: real DB with test fixtures; rollback after each test
|
|
46
|
+
- **Mock external APIs**: WireMock, MSW, MockWebServer, http.Client mock
|
|
47
|
+
|
|
48
|
+
## E2E Tests
|
|
49
|
+
|
|
50
|
+
Test a complete user flow from UI to database.
|
|
51
|
+
|
|
52
|
+
**What to E2E test** (keep the list short):
|
|
53
|
+
- Login / registration flow
|
|
54
|
+
- Core purchase / conversion flow
|
|
55
|
+
- Critical admin operations
|
|
56
|
+
- Signup → first meaningful action
|
|
57
|
+
|
|
58
|
+
**Tools by Platform**
|
|
59
|
+
|
|
60
|
+
| Platform | Tool |
|
|
61
|
+
|---|---|
|
|
62
|
+
| Web | Playwright (preferred), Cypress |
|
|
63
|
+
| Android | Espresso, UIAutomator2 |
|
|
64
|
+
| iOS | XCUITest |
|
|
65
|
+
| Flutter | integration_test + flutter_driver |
|
|
66
|
+
| API / Contract | Postman / Newman, REST-assured |
|
|
67
|
+
|
|
68
|
+
## Test Data Factories
|
|
69
|
+
|
|
70
|
+
Generate realistic test data:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// TypeScript example
|
|
74
|
+
function createUser(overrides: Partial<User> = {}): User {
|
|
75
|
+
return {
|
|
76
|
+
id: crypto.randomUUID(),
|
|
77
|
+
email: 'test@example.com',
|
|
78
|
+
name: 'Test User',
|
|
79
|
+
...overrides,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Never reuse test data between tests — each test should set up its own state.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-design
|
|
3
|
+
description: REST and GraphQL API design conventions — URL structure, versioning, pagination, filtering, and documentation
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API Design
|
|
7
|
+
|
|
8
|
+
## REST URL Conventions
|
|
9
|
+
|
|
10
|
+
- Use plural nouns for resources: `/users`, `/orders`, `/products`
|
|
11
|
+
- Lowercase, hyphen-separated: `/user-profiles`, not `/UserProfiles`
|
|
12
|
+
- Nested resources for clear ownership: `/users/:id/orders`
|
|
13
|
+
- Query params for filtering/sorting: `/products?category=electronics&sort=price_asc`
|
|
14
|
+
- Avoid verbs in URLs (the HTTP method IS the verb): `POST /orders` not `POST /createOrder`
|
|
15
|
+
|
|
16
|
+
## Versioning
|
|
17
|
+
|
|
18
|
+
- URL versioning: `/api/v1/users` — simple, explicit, cacheable
|
|
19
|
+
- Header versioning: `Accept: application/vnd.myapp.v1+json` — cleaner URLs, harder to test
|
|
20
|
+
- **Default**: URL versioning for public APIs
|
|
21
|
+
|
|
22
|
+
## Pagination
|
|
23
|
+
|
|
24
|
+
**Cursor-based** (preferred for large/live datasets):
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"data": [...],
|
|
28
|
+
"pagination": { "nextCursor": "eyJpZCI6MTAwfQ==", "hasMore": true }
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Offset-based** (simpler for small, stable datasets):
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"data": [...],
|
|
36
|
+
"pagination": { "page": 1, "pageSize": 20, "total": 450 }
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Filtering & Sorting
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
GET /products?category=electronics&minPrice=100&maxPrice=500
|
|
44
|
+
GET /users?sort=created_at:desc,name:asc
|
|
45
|
+
GET /orders?status=pending,processing
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## GraphQL Conventions
|
|
49
|
+
|
|
50
|
+
```graphql
|
|
51
|
+
type User {
|
|
52
|
+
id: ID!
|
|
53
|
+
email: String!
|
|
54
|
+
orders(first: Int, after: String): OrderConnection!
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
type Mutation {
|
|
58
|
+
createUser(input: CreateUserInput!): CreateUserPayload!
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- Use Relay connection pattern for paginated lists
|
|
63
|
+
- Mutations take `input` objects, return `payload` objects
|
|
64
|
+
- Use `!` for non-nullable fields; nullable is the default
|
|
65
|
+
|
|
66
|
+
## API Documentation
|
|
67
|
+
|
|
68
|
+
Every endpoint needs:
|
|
69
|
+
- Description, method, URL, headers, path/query params
|
|
70
|
+
- Request body (with types and examples)
|
|
71
|
+
- All response status codes with body shapes
|
|
72
|
+
- A real request/response pair as example
|
|
73
|
+
|
|
74
|
+
Tools: **OpenAPI 3.x (Swagger)** for REST, **GraphQL Playground** for GraphQL.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-security
|
|
3
|
+
description: API security — authentication headers, CORS policy, rate limiting, deprecation policy, and client error handling
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API Security & Lifecycle
|
|
7
|
+
|
|
8
|
+
## Authentication
|
|
9
|
+
|
|
10
|
+
- **Bearer token** (JWT): `Authorization: Bearer <token>` — stateless, works for mobile and web
|
|
11
|
+
- **API Key**: `Authorization: ApiKey <key>` or `X-Api-Key: <key>` — for service-to-service
|
|
12
|
+
- Always HTTPS — never send credentials over plain HTTP
|
|
13
|
+
- Return `401 Unauthorized` for missing/invalid token, `403 Forbidden` for insufficient permissions
|
|
14
|
+
|
|
15
|
+
## CORS
|
|
16
|
+
|
|
17
|
+
```http
|
|
18
|
+
Access-Control-Allow-Origin: https://app.example.com
|
|
19
|
+
Access-Control-Allow-Methods: GET, POST, PATCH, DELETE
|
|
20
|
+
Access-Control-Allow-Headers: Authorization, Content-Type
|
|
21
|
+
Access-Control-Max-Age: 86400
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **Never** `Access-Control-Allow-Origin: *` for authenticated APIs
|
|
25
|
+
- Whitelist specific origins per environment
|
|
26
|
+
- Preflight requests (`OPTIONS`) must respond with `204 No Content`
|
|
27
|
+
|
|
28
|
+
## Rate Limiting Headers
|
|
29
|
+
|
|
30
|
+
```http
|
|
31
|
+
X-RateLimit-Limit: 100
|
|
32
|
+
X-RateLimit-Remaining: 42
|
|
33
|
+
X-RateLimit-Reset: 1735689600
|
|
34
|
+
Retry-After: 60
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Always tell the client when they can retry.
|
|
38
|
+
|
|
39
|
+
## Versioning & Deprecation Policy
|
|
40
|
+
|
|
41
|
+
1. Introduce new field/endpoint alongside old one
|
|
42
|
+
2. Mark old field as `deprecated` in schema / docs
|
|
43
|
+
3. Announce deprecation with a removal date (minimum 6 months notice)
|
|
44
|
+
4. Monitor usage before removal; don't remove when still used
|
|
45
|
+
5. Remove only when usage is zero or all clients have migrated
|
|
46
|
+
|
|
47
|
+
## Client Error Handling Rules
|
|
48
|
+
|
|
49
|
+
- Always handle `401` by clearing auth state and redirecting to login
|
|
50
|
+
- Implement exponential backoff for `429` and `503` responses
|
|
51
|
+
- Cache responses where appropriate (`Cache-Control` header from server)
|
|
52
|
+
- Use request cancellation to avoid race conditions in search/autocomplete
|
|
53
|
+
- Never retry `400`/`422` (client errors) — fix the request instead
|
|
54
|
+
- Log all 5xx responses on the client side for debugging
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-security
|
|
3
|
+
description: Backend security — JWT auth patterns, RBAC, input validation, parameterized queries, and structured logging
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Backend — Security & Observability
|
|
7
|
+
|
|
8
|
+
## Authentication Pattern (JWT)
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
1. Client sends credentials → POST /auth/login
|
|
12
|
+
2. Server validates → returns { access_token, refresh_token }
|
|
13
|
+
3. Client sends: Authorization: Bearer <access_token>
|
|
14
|
+
4. Server validates JWT signature + expiry on every request
|
|
15
|
+
5. Refresh via POST /auth/refresh with refresh_token
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
- **Access tokens**: short-lived (15–60 min)
|
|
19
|
+
- **Refresh tokens**: long-lived (7–30 days), stored httpOnly cookie
|
|
20
|
+
- Never store JWTs in localStorage (XSS risk)
|
|
21
|
+
- Validate signature AND expiry on every protected route
|
|
22
|
+
|
|
23
|
+
## RBAC Authorization
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
User → has Role(s) → Role has Permissions → Permission gates resources/actions
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- Check authorization in the **service layer**, not the route handler
|
|
30
|
+
- Never pass user-controlled values as part of the authorization check
|
|
31
|
+
- Use allowlists, not denylists
|
|
32
|
+
|
|
33
|
+
## Input Validation
|
|
34
|
+
|
|
35
|
+
- Validate ALL inputs at the API boundary before processing
|
|
36
|
+
- Use parameterized queries or ORM — never string concatenation in SQL
|
|
37
|
+
- Validate content type, file size, and MIME type for uploads
|
|
38
|
+
- Schema validation library: Zod (TypeScript), Pydantic (Python), Joi (Node.js)
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// Validate at the boundary
|
|
42
|
+
const schema = z.object({
|
|
43
|
+
email: z.string().email(),
|
|
44
|
+
name: z.string().min(1).max(100),
|
|
45
|
+
});
|
|
46
|
+
const body = schema.parse(req.body); // throws if invalid
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Structured Logging
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
logger.info({
|
|
53
|
+
event: 'user.login',
|
|
54
|
+
userId: user.id,
|
|
55
|
+
correlationId: req.id,
|
|
56
|
+
ip: req.ip,
|
|
57
|
+
durationMs: Date.now() - startTime,
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Log levels:
|
|
62
|
+
- `debug` — dev only, verbose internal state
|
|
63
|
+
- `info` — normal operations (requests, business events)
|
|
64
|
+
- `warn` — unexpected but handled (retry succeeded, fallback used)
|
|
65
|
+
- `error` — needs investigation (unhandled exception, external failure)
|
|
66
|
+
|
|
67
|
+
**Never log**: passwords, tokens, full credit card numbers, PII in plain text.
|
|
68
|
+
|
|
69
|
+
## Rate Limiting
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
// Express rate-limit example
|
|
73
|
+
const limiter = rateLimit({
|
|
74
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
75
|
+
max: 100,
|
|
76
|
+
standardHeaders: true,
|
|
77
|
+
legacyHeaders: false,
|
|
78
|
+
});
|
|
79
|
+
app.use('/api/', limiter);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- Apply stricter limits to auth endpoints (`POST /auth/login`)
|
|
83
|
+
- Return `429 Too Many Requests` with `Retry-After` header
|
|
84
|
+
- Consider IP-based and user-based limits separately
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-structure
|
|
3
|
+
description: Backend project structure, API response conventions, database best practices, and error handling patterns
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Backend — Structure & Conventions
|
|
7
|
+
|
|
8
|
+
## Core Principles
|
|
9
|
+
|
|
10
|
+
1. **Reliability over cleverness.** Boring code that works beats clever code that surprises you at 3am.
|
|
11
|
+
2. **Fail explicitly.** Return specific error codes and messages. Never silently swallow errors.
|
|
12
|
+
3. **Idempotency.** Design operations that can be safely retried.
|
|
13
|
+
4. **Defense in depth.** Validate at the API layer AND at the database layer.
|
|
14
|
+
|
|
15
|
+
## Project Structure (Layered)
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
src/
|
|
19
|
+
├── api/ # Route handlers (HTTP layer only — no business logic)
|
|
20
|
+
│ └── routes/
|
|
21
|
+
├── services/ # Business logic (pure functions where possible)
|
|
22
|
+
├── repositories/ # Database access (single source of truth for queries)
|
|
23
|
+
├── models/ # Data models / schemas / types
|
|
24
|
+
├── middleware/ # Auth, logging, rate limiting, error handling
|
|
25
|
+
├── utils/ # Pure utility functions
|
|
26
|
+
└── config/ # Environment configuration
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API Response Conventions
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
// Success
|
|
33
|
+
{ "data": { ... }, "meta": { "page": 1, "total": 100 } }
|
|
34
|
+
|
|
35
|
+
// Error
|
|
36
|
+
{ "error": { "code": "VALIDATION_ERROR", "message": "Email is required", "field": "email" } }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Status Codes
|
|
40
|
+
- `200 OK` — successful GET/PATCH
|
|
41
|
+
- `201 Created` — successful POST (include `Location` header)
|
|
42
|
+
- `204 No Content` — successful DELETE
|
|
43
|
+
- `400 Bad Request` — invalid data (include field-level errors)
|
|
44
|
+
- `401 Unauthorized` — missing or invalid authentication
|
|
45
|
+
- `403 Forbidden` — authenticated but not authorized
|
|
46
|
+
- `404 Not Found` — resource doesn't exist
|
|
47
|
+
- `409 Conflict` — duplicate resource or state conflict
|
|
48
|
+
- `422 Unprocessable Entity` — failed business rule validation
|
|
49
|
+
- `429 Too Many Requests` — rate limit hit (include `Retry-After` header)
|
|
50
|
+
- `500 Internal Server Error` — never expose stack traces in production
|
|
51
|
+
|
|
52
|
+
## Database Best Practices
|
|
53
|
+
|
|
54
|
+
- **Migrations**: every schema change is a migration file (never edit production schema manually)
|
|
55
|
+
- **Transactions**: wrap multi-step operations that must succeed or fail together
|
|
56
|
+
- **Indexes**: index foreign keys, columns used in WHERE/ORDER BY, and unique constraints
|
|
57
|
+
- **N+1 prevention**: use joins or batch loading — never query in a loop
|
|
58
|
+
- **Soft deletes**: `deleted_at TIMESTAMP` instead of hard DELETE for auditable data
|
|
59
|
+
- **Timestamps**: every table has `created_at` and `updated_at` (auto-managed)
|
|
60
|
+
|
|
61
|
+
## Error Handling
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// Centralized error handler (Express)
|
|
65
|
+
app.use((err, req, res, next) => {
|
|
66
|
+
logger.error({ err, correlationId: req.id, method: req.method, url: req.url });
|
|
67
|
+
|
|
68
|
+
if (err instanceof ValidationError) {
|
|
69
|
+
return res.status(400).json({ error: { code: 'VALIDATION_ERROR', ...err.details } });
|
|
70
|
+
}
|
|
71
|
+
if (err instanceof NotFoundError) {
|
|
72
|
+
return res.status(404).json({ error: { code: 'NOT_FOUND', message: err.message } });
|
|
73
|
+
}
|
|
74
|
+
return res.status(500).json({ error: { code: 'INTERNAL_ERROR', message: 'An unexpected error occurred' } });
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Never expose stack traces or internal error messages to clients in production.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-components
|
|
3
|
+
description: Component-driven UI development — React/Vue/Angular patterns, component design rules, and CSS architecture
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend — Components & Frameworks
|
|
7
|
+
|
|
8
|
+
## Core Principles
|
|
9
|
+
|
|
10
|
+
1. **Component-driven development.** Build UIs as a tree of composable, reusable components.
|
|
11
|
+
2. **State is the enemy.** Minimize local state. Lift state when shared, externalize when global.
|
|
12
|
+
3. **Performance is a feature.** Users feel latency. Design for the P95 experience, not localhost.
|
|
13
|
+
4. **Accessible by default.** Screen reader support and keyboard navigation are not optional extras.
|
|
14
|
+
|
|
15
|
+
## Framework Conventions
|
|
16
|
+
|
|
17
|
+
### React
|
|
18
|
+
- Prefer functional components + hooks over class components
|
|
19
|
+
- `useState` for local UI state; `useReducer` for complex local state
|
|
20
|
+
- Avoid prop drilling beyond 2 levels — lift to context or state manager
|
|
21
|
+
- Server Components (Next.js 13+): use for data-fetching; Client Components only for interactivity
|
|
22
|
+
- `useEffect` dependency arrays must be exhaustive — lint rule: `react-hooks/exhaustive-deps`
|
|
23
|
+
|
|
24
|
+
### Vue 3
|
|
25
|
+
- Composition API preferred over Options API for new code
|
|
26
|
+
- `ref()` for primitives, `reactive()` for objects
|
|
27
|
+
- Pinia for global state (not Vuex)
|
|
28
|
+
- `<script setup>` shorthand for all SFCs
|
|
29
|
+
|
|
30
|
+
### Angular
|
|
31
|
+
- Standalone components (Angular 14+) — no NgModule unless maintaining legacy
|
|
32
|
+
- Signals for reactive state (Angular 17+)
|
|
33
|
+
- OnPush change detection by default for performance
|
|
34
|
+
|
|
35
|
+
## Component Design Rules
|
|
36
|
+
|
|
37
|
+
- One component = one responsibility
|
|
38
|
+
- Props down, events up (unidirectional data flow)
|
|
39
|
+
- Keep components small: if it needs a scroll to read, split it
|
|
40
|
+
- Naming: `UserProfileCard`, not `Card3` or `ProfileThing`
|
|
41
|
+
- Extract presentational components from smart/container components
|
|
42
|
+
|
|
43
|
+
## CSS Architecture
|
|
44
|
+
|
|
45
|
+
- **Utility-first (Tailwind)**: fast iteration, no CSS naming decisions, co-located styles
|
|
46
|
+
- **CSS Modules**: scoped styles without a framework; pairs well with React/Vue
|
|
47
|
+
- **BEM**: use only in large teams where Tailwind is not adopted
|
|
48
|
+
|
|
49
|
+
Avoid global CSS except for: CSS resets, font imports, CSS custom properties (tokens).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-performance
|
|
3
|
+
description: Frontend performance budgets, Core Web Vitals targets, bundle optimization, and frontend testing strategies
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend — Performance & Testing
|
|
7
|
+
|
|
8
|
+
## Performance Budgets
|
|
9
|
+
|
|
10
|
+
| Metric | Target | Tool |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| Largest Contentful Paint (LCP) | < 2.5s | Lighthouse |
|
|
13
|
+
| First Input Delay (FID) | < 100ms | Web Vitals |
|
|
14
|
+
| Cumulative Layout Shift (CLS) | < 0.1 | Lighthouse |
|
|
15
|
+
| Bundle size (initial JS) | < 200KB gzipped | webpack-bundle-analyzer |
|
|
16
|
+
| Image size (hero) | < 200KB WebP | Squoosh / ImageOptim |
|
|
17
|
+
|
|
18
|
+
## Bundle Optimization
|
|
19
|
+
|
|
20
|
+
- Code-split at the route level — each route loads only its own JS
|
|
21
|
+
- Tree-shake unused exports (ensure your bundler config enables it)
|
|
22
|
+
- Audit bundle size before merging large dependency additions
|
|
23
|
+
- Prefer lighter alternatives: `date-fns` over `moment`, `zod` over `yup`
|
|
24
|
+
|
|
25
|
+
## Render Performance
|
|
26
|
+
|
|
27
|
+
- Avoid unnecessary re-renders: use `memo`, `useMemo`, `useCallback` only when measured, not preemptively
|
|
28
|
+
- Use `React.lazy` / dynamic imports for below-fold components
|
|
29
|
+
- Use `ListView.builder` pattern (virtual list) for large dynamic lists
|
|
30
|
+
- Avoid inline object/function creation in JSX that defeats memoization
|
|
31
|
+
|
|
32
|
+
## Testing Frontend Code
|
|
33
|
+
|
|
34
|
+
- **Unit test**: pure functions, custom hooks, utility functions
|
|
35
|
+
- **Component test**: render component → simulate user action → assert output (Testing Library)
|
|
36
|
+
- **E2E test**: critical user flows only (login, checkout, core CRUD) — Playwright or Cypress
|
|
37
|
+
|
|
38
|
+
### Testing Library Principles
|
|
39
|
+
- Query by role, label, or text — not by CSS class or test ID
|
|
40
|
+
- Test what the user sees, not implementation details
|
|
41
|
+
- `getByRole('button', { name: /submit/i })` not `getByTestId('submit-btn')`
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-state
|
|
3
|
+
description: Frontend state management decision guide, routing conventions, and form handling patterns
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Frontend — State, Routing & Forms
|
|
7
|
+
|
|
8
|
+
## State Management Decision
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
Is the state:
|
|
12
|
+
├── Used by one component only? → useState / ref()
|
|
13
|
+
├── Used by a subtree of components? → Context / provide-inject
|
|
14
|
+
├── Used app-wide, changes frequently? → Zustand / Pinia / NgRx
|
|
15
|
+
└── Server data (API responses)? → React Query / SWR / TanStack Query
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Never use global state for server data — that's what data-fetching libraries are for.
|
|
19
|
+
|
|
20
|
+
## Recommended Libraries
|
|
21
|
+
|
|
22
|
+
| Need | React | Vue 3 | Angular |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| Server state | TanStack Query / SWR | VueQuery | NgRx/data or custom |
|
|
25
|
+
| Global client state | Zustand / Jotai | Pinia | NgRx |
|
|
26
|
+
| Forms | React Hook Form + Zod | VeeValidate + Zod | Reactive Forms |
|
|
27
|
+
| Routing | React Router / Next.js | Vue Router / Nuxt | Angular Router |
|
|
28
|
+
|
|
29
|
+
## Routing Conventions
|
|
30
|
+
|
|
31
|
+
- File-based routing where supported (Next.js, Nuxt, SvelteKit)
|
|
32
|
+
- Route names map to user intent: `/dashboard`, `/settings/profile`, not `/page3`
|
|
33
|
+
- Lazy-load route components to reduce initial bundle
|
|
34
|
+
- Guard authenticated routes at the router level, not inside components
|
|
35
|
+
|
|
36
|
+
## Form Handling
|
|
37
|
+
|
|
38
|
+
- **React**: React Hook Form (minimal re-renders) + Zod for schema validation
|
|
39
|
+
- **Vue**: VeeValidate + Zod
|
|
40
|
+
- **Angular**: Reactive Forms + Zod or built-in validators
|
|
41
|
+
- Never submit a form without client-side validation
|
|
42
|
+
- Never trust client-side validation on the server — validate both sides
|
|
43
|
+
|
|
44
|
+
## Data Fetching Patterns
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// React Query example
|
|
48
|
+
const { data, isLoading, error } = useQuery({
|
|
49
|
+
queryKey: ['users', userId],
|
|
50
|
+
queryFn: () => fetchUser(userId),
|
|
51
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Mutation
|
|
55
|
+
const mutation = useMutation({
|
|
56
|
+
mutationFn: updateUser,
|
|
57
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['users'] }),
|
|
58
|
+
});
|
|
59
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-accessibility
|
|
3
|
+
description: WCAG 2.1 AA compliance — semantic HTML, ARIA patterns, keyboard navigation, and color contrast
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web Accessibility (a11y)
|
|
7
|
+
|
|
8
|
+
Target: **WCAG 2.1 AA**
|
|
9
|
+
|
|
10
|
+
## Semantic HTML
|
|
11
|
+
|
|
12
|
+
Use the correct element for the job:
|
|
13
|
+
- `<button>` for actions, `<a>` for navigation — never `<div>` with onClick
|
|
14
|
+
- `<nav>`, `<main>`, `<aside>`, `<footer>` for landmark regions
|
|
15
|
+
- Heading hierarchy: one `<h1>` per page, `<h2>` for sections (no skipping)
|
|
16
|
+
- `<table>` with `<thead>`, `<th scope="col">`, `<caption>` for data tables
|
|
17
|
+
- `<form>` with `<label>` associated to every input (via `for` attribute or wrapping)
|
|
18
|
+
|
|
19
|
+
## ARIA
|
|
20
|
+
|
|
21
|
+
Use ARIA only when semantic HTML is insufficient:
|
|
22
|
+
- `aria-label` — when text content doesn't describe the element (icon-only buttons)
|
|
23
|
+
- `aria-expanded` — for accordion/disclosure patterns
|
|
24
|
+
- `aria-live="polite"` — for dynamic content updates (loading states, notifications)
|
|
25
|
+
- `aria-describedby` — to link error messages to their input fields
|
|
26
|
+
- Never add `role="button"` to a `<div>` — use `<button>` instead
|
|
27
|
+
|
|
28
|
+
## Keyboard Navigation
|
|
29
|
+
|
|
30
|
+
- All interactive elements must be reachable via `Tab`
|
|
31
|
+
- All actions must be triggerable via `Enter` / `Space`
|
|
32
|
+
- Focus must be visible (`:focus-visible` CSS, never `outline: none` without a replacement)
|
|
33
|
+
- Modal dialogs must trap focus while open; restore focus on close
|
|
34
|
+
- Skip nav link: `<a href="#main-content" class="skip-link">Skip to main content</a>`
|
|
35
|
+
|
|
36
|
+
## Color & Contrast
|
|
37
|
+
|
|
38
|
+
- Text contrast ratio ≥ 4.5:1 (normal text), ≥ 3:1 (large text: 18px+ or bold 14px+)
|
|
39
|
+
- Never use color alone to convey information — add icons, patterns, or text
|
|
40
|
+
- Check with: WebAIM Contrast Checker, axe DevTools browser extension
|
|
41
|
+
|
|
42
|
+
## Common Mistakes to Avoid
|
|
43
|
+
|
|
44
|
+
| Mistake | Fix |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `<div onClick>` | Use `<button>` or `<a>` |
|
|
47
|
+
| Missing alt text | Add `alt=""` for decorative, meaningful alt for content |
|
|
48
|
+
| Form inputs without labels | Add `<label for="id">` or `aria-label` |
|
|
49
|
+
| Low contrast text | Minimum 4.5:1 ratio |
|
|
50
|
+
| Focus indicator hidden | Never `outline: none` without a visible replacement |
|
|
51
|
+
| Only color indicates errors | Add icon + text alongside color |
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-performance
|
|
3
|
+
description: Web performance optimization — critical rendering path, loading strategies, caching, image optimization, and PWA
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web Performance
|
|
7
|
+
|
|
8
|
+
## Critical Rendering Path
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
HTML parsed → DOM built → CSS parsed → CSSOM built → Render Tree → Layout → Paint → Composite
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Minimize blocking resources in `<head>`. Defer non-critical JS. Inline critical CSS.
|
|
15
|
+
|
|
16
|
+
## Loading Strategies
|
|
17
|
+
|
|
18
|
+
- **Images**: `loading="lazy"` for below-fold; `loading="eager"` + preload for hero
|
|
19
|
+
- **Fonts**: `font-display: swap` to prevent FOIT; preload primary font file
|
|
20
|
+
- **Scripts**: `defer` or `async` for non-critical; module scripts are deferred by default
|
|
21
|
+
- **CSS**: inline critical CSS; load rest with `rel="preload"` as stylesheet
|
|
22
|
+
|
|
23
|
+
## Caching
|
|
24
|
+
|
|
25
|
+
- **Static assets**: `Cache-Control: max-age=31536000, immutable` (with content hash in filename)
|
|
26
|
+
- **API responses**: `Cache-Control: private, max-age=60` or `no-cache` based on freshness needs
|
|
27
|
+
- **Service Worker**: cache-first for shell, network-first for API data
|
|
28
|
+
|
|
29
|
+
## Image Optimization
|
|
30
|
+
|
|
31
|
+
- Use `<picture>` with `srcset` for responsive images
|
|
32
|
+
- WebP for photographs, SVG for icons and illustrations
|
|
33
|
+
- Always set explicit `width` and `height` attributes to prevent CLS
|
|
34
|
+
- Use a CDN with on-the-fly image resizing for user-generated content
|
|
35
|
+
- Target hero images < 200KB, other content images < 100KB
|
|
36
|
+
|
|
37
|
+
## PWA Checklist
|
|
38
|
+
|
|
39
|
+
- [ ] HTTPS
|
|
40
|
+
- [ ] Web App Manifest with icons, name, theme color
|
|
41
|
+
- [ ] Service Worker with offline fallback
|
|
42
|
+
- [ ] Responsive design (passes mobile-friendly test)
|
|
43
|
+
- [ ] Fast initial load (LCP < 2.5s)
|
|
44
|
+
- [ ] Installable (meets browser criteria)
|
|
45
|
+
|
|
46
|
+
## Browser Compatibility
|
|
47
|
+
|
|
48
|
+
Target: last 2 stable versions of Chrome, Firefox, Safari, Edge.
|
|
49
|
+
- Check support at: caniuse.com
|
|
50
|
+
- Use feature detection, not user-agent sniffing
|
|
51
|
+
- **Test in Safari** — it's the new IE for many modern web features
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-security
|
|
3
|
+
description: Web security — CSP, HTTPS/HSTS, XSS prevention, CSRF protection, and Subresource Integrity
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Web Security
|
|
7
|
+
|
|
8
|
+
## Content Security Policy (CSP)
|
|
9
|
+
|
|
10
|
+
Block inline scripts and unauthorized origins:
|
|
11
|
+
|
|
12
|
+
```http
|
|
13
|
+
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- Never use `'unsafe-inline'` for scripts in production
|
|
17
|
+
- Use nonces for inline scripts that cannot be moved to external files
|
|
18
|
+
- Report violations with `Content-Security-Policy-Report-Only` before enforcing
|
|
19
|
+
|
|
20
|
+
## HTTPS & Transport Security
|
|
21
|
+
|
|
22
|
+
```http
|
|
23
|
+
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
|
|
24
|
+
X-Frame-Options: DENY
|
|
25
|
+
X-Content-Type-Options: nosniff
|
|
26
|
+
Referrer-Policy: strict-origin-when-cross-origin
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- Enforce HTTPS at the load balancer; never serve on HTTP
|
|
30
|
+
- Register for HSTS preload at hstspreload.org for maximum protection
|
|
31
|
+
|
|
32
|
+
## XSS Prevention
|
|
33
|
+
|
|
34
|
+
- Never use `innerHTML`, `outerHTML`, or `document.write` with user content
|
|
35
|
+
- Use `textContent` for text nodes
|
|
36
|
+
- Sanitize HTML with DOMPurify when rich HTML input is required
|
|
37
|
+
- React, Vue, Angular escape by default — use their escape hatches (`dangerouslySetInnerHTML`) only with pre-sanitized content
|
|
38
|
+
|
|
39
|
+
## CSRF Protection
|
|
40
|
+
|
|
41
|
+
- Use `SameSite=Lax` or `SameSite=Strict` cookies for session tokens
|
|
42
|
+
- Add CSRF tokens to all state-changing form submissions
|
|
43
|
+
- Double-submit cookie pattern for stateless CSRF protection
|
|
44
|
+
|
|
45
|
+
## Subresource Integrity (SRI)
|
|
46
|
+
|
|
47
|
+
Add `integrity` attributes to third-party scripts and styles:
|
|
48
|
+
|
|
49
|
+
```html
|
|
50
|
+
<script src="https://cdn.example.com/lib.js"
|
|
51
|
+
integrity="sha384-abc123..."
|
|
52
|
+
crossorigin="anonymous"></script>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Third-Party Scripts
|
|
56
|
+
|
|
57
|
+
- Audit every third-party script — each is a potential XSS vector
|
|
58
|
+
- Load analytics, chat widgets, etc. with `async` and in a sandboxed context
|
|
59
|
+
- Regularly audit what third-party scripts have access to (use browser devtools)
|