nextjs-hackathon-stack 0.1.31 → 0.1.32
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/package.json +1 -1
- package/template/.cursor/agents/business-intelligence.md +6 -0
- package/template/.cursor/agents/technical-lead.md +4 -4
- package/template/.cursor/rules/architecture.mdc +3 -2
- package/template/.cursor/rules/coding-standards.mdc +41 -2
- package/template/.cursor/rules/general.mdc +3 -2
- package/template/.cursor/rules/security.mdc +4 -1
- package/template/.cursor/rules/testing.mdc +8 -0
- package/template/.cursor/skills/create-feature/SKILL.md +21 -4
- package/template/CLAUDE.md +17 -1
- package/template/next.config.ts +4 -1
- package/template/tailwind.css +14 -14
package/package.json
CHANGED
|
@@ -52,6 +52,12 @@ As a [user type], I want [goal] so that [reason].
|
|
|
52
52
|
- Every acceptance criterion maps to at least one test case
|
|
53
53
|
- No mention of database tables, API calls, component names, or file paths
|
|
54
54
|
|
|
55
|
+
## Language
|
|
56
|
+
|
|
57
|
+
Write requirements and acceptance criteria in the user's language. However:
|
|
58
|
+
- Acceptance criteria IDs (`AC1`, `AC2`), test case IDs (`TC1`), and technical terms (`ActionResult`, `Server Action`, component names) always remain in English
|
|
59
|
+
- Specify that all code-level text (test `it()` descriptions, variable names, error strings in code) must be written in English — only user-visible strings (UI labels, toast messages, validation messages shown on screen) should be in the target language
|
|
60
|
+
|
|
55
61
|
## Guardrails
|
|
56
62
|
- Always ask questions before writing — never assume
|
|
57
63
|
- Document all requirements in `.requirements/` directory
|
|
@@ -43,7 +43,7 @@ Delegate to the appropriate specialist based on domain:
|
|
|
43
43
|
## Workflow Sequences
|
|
44
44
|
|
|
45
45
|
### New feature
|
|
46
|
-
@business-intelligence (functional issue) → @technical-lead (task breakdown + test plan) → @test-qa (RED) → @
|
|
46
|
+
@business-intelligence (functional issue) → @technical-lead (task breakdown + test plan) → @test-qa (RED) → **@backend + @frontend in parallel** (GREEN) → **@code-reviewer + @security-researcher in parallel**
|
|
47
47
|
|
|
48
48
|
### Bug fix
|
|
49
49
|
@test-qa (reproduce with failing test) → @backend/@frontend (fix) → @code-reviewer
|
|
@@ -62,10 +62,10 @@ When you receive a functional issue from @business-intelligence, do this before
|
|
|
62
62
|
- One `describe` block per acceptance criterion
|
|
63
63
|
- Which mocks are needed (Supabase, HTTP, etc.)
|
|
64
64
|
- Which edge cases map to which criteria
|
|
65
|
-
4. **Delegate in order
|
|
65
|
+
4. **Delegate in order** (parallel where possible):
|
|
66
66
|
- @test-qa gets the test plan → writes failing tests (RED)
|
|
67
|
-
- @
|
|
68
|
-
-
|
|
67
|
+
- **@backend + @frontend simultaneously** — they work on independent files, no need to serialize (GREEN)
|
|
68
|
+
- **@code-reviewer + @security-researcher simultaneously** — independent review passes, run in parallel
|
|
69
69
|
|
|
70
70
|
### TDD efficiency guardrails
|
|
71
71
|
- Plan test structure before delegating to @test-qa — never send "write tests for this feature" without a plan
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Code quality standards.
|
|
3
|
-
alwaysApply:
|
|
2
|
+
description: Code quality standards. Applies to TypeScript/TSX source files.
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
globs: ["src/**/*.ts", "src/**/*.tsx"]
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Coding Standards
|
|
@@ -63,6 +64,44 @@ const items = schema.parse(data);
|
|
|
63
64
|
const items = data as SupportListItem[];
|
|
64
65
|
```
|
|
65
66
|
|
|
67
|
+
## Language Rules
|
|
68
|
+
|
|
69
|
+
- **Code-level text must be in English**: test `it()` descriptions, `describe()` block names, variable names, code comments, developer-facing `Error` constructor messages (never shown to users), `console` output
|
|
70
|
+
- **User-facing text stays in the target language**: UI labels, placeholders, toast messages, form validation messages shown on screen, `ActionResult` error/success strings that end up displayed in the UI
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// ✅ Code-level: English
|
|
74
|
+
it("returns error when candidate is not found", async () => { ... });
|
|
75
|
+
throw new Error("Unexpected DB response shape"); // developer-facing, never shown in UI
|
|
76
|
+
|
|
77
|
+
// ✅ User-facing: target language (Spanish)
|
|
78
|
+
return { success: false, error: "Candidato no encontrado" }; // shown in toast
|
|
79
|
+
toast.error("No se pudo guardar el cambio");
|
|
80
|
+
|
|
81
|
+
// ❌ Wrong: code-level in wrong language
|
|
82
|
+
it("retorna error si el candidato no existe", async () => { ... });
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Coverage Exclusions (configure upfront, not reactively)
|
|
86
|
+
|
|
87
|
+
Before writing tests, add exclusions to `vitest.config.ts` for:
|
|
88
|
+
- Drizzle schema definition files (`src/shared/db/schema.ts`)
|
|
89
|
+
- Pure type files (files with only `type`/`interface` exports, no runtime logic)
|
|
90
|
+
- Third-party UI wrapper components that rely on portals or browser APIs not supported in jsdom (e.g., `sonner.tsx`, toast providers)
|
|
91
|
+
|
|
92
|
+
Configure these exclusions **before writing tests** to avoid reactive coverage fixes mid-implementation.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
// vitest.config.ts
|
|
96
|
+
coverage: {
|
|
97
|
+
exclude: [
|
|
98
|
+
"src/shared/db/schema.ts",
|
|
99
|
+
"src/shared/components/ui/sonner.tsx",
|
|
100
|
+
// add other portal/type-only files here
|
|
101
|
+
],
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
66
105
|
## Pre-commit Quality Gates
|
|
67
106
|
Every commit must pass two sequential gates:
|
|
68
107
|
1. **lint-staged** — runs `eslint --max-warnings 0` on staged `.ts/.tsx` files. Any lint warning or error blocks the commit immediately (before the slower test suite runs).
|
|
@@ -94,7 +94,10 @@ const next = searchParams.get("next") ?? "/";
|
|
|
94
94
|
"script-src 'self' 'unsafe-inline'", // TODO: replace with nonce-based CSP
|
|
95
95
|
"style-src 'self' 'unsafe-inline'",
|
|
96
96
|
|
|
97
|
-
//
|
|
97
|
+
// ✅ Dev-only — unsafe-eval for React debugging features (silences installHook.js warning)
|
|
98
|
+
`script-src 'self' 'unsafe-inline'${isDev ? " 'unsafe-eval'" : ""}`,
|
|
99
|
+
|
|
100
|
+
// ❌ Never — unsafe-eval unconditionally in production
|
|
98
101
|
"script-src 'self' 'unsafe-eval' 'unsafe-inline'",
|
|
99
102
|
```
|
|
100
103
|
|
|
@@ -111,6 +111,14 @@ For every function, ask: what happens with...
|
|
|
111
111
|
|
|
112
112
|
If any of these apply, write a test for it. No exceptions.
|
|
113
113
|
|
|
114
|
+
## jsdom Known Limitations (avoid rework cycles)
|
|
115
|
+
|
|
116
|
+
jsdom does not implement all browser APIs. Hitting these in tests causes failures that require full component rewrites — avoid them upfront:
|
|
117
|
+
|
|
118
|
+
- **No `HTMLDialogElement` methods** — `dialog.showModal()` and `dialog.close()` throw in jsdom. Use state-controlled visibility (`isOpen` prop / conditional render) instead of the native `<dialog>` API.
|
|
119
|
+
- **No portal-based components in unit tests** — components like `<Toaster>` (sonner), `<Tooltip>`, `<Popover>` render outside the React tree and are unreliable in jsdom. Exclude their wrapper files from coverage; test toast behavior indirectly via the action's `ActionResult`.
|
|
120
|
+
- **Run `pnpm lint` before finishing** — do not leave lint errors to a separate pass. Fix inline as you go.
|
|
121
|
+
|
|
114
122
|
## Coverage Thresholds
|
|
115
123
|
```typescript
|
|
116
124
|
// vitest.config.ts
|
|
@@ -25,7 +25,24 @@ src/features/<feature-name>/
|
|
|
25
25
|
└── __tests__/
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
### 3.
|
|
28
|
+
### 3. Pre-Test Setup (do this before writing any tests)
|
|
29
|
+
|
|
30
|
+
Update `vitest.config.ts` to exclude files that cannot be meaningfully tested in jsdom:
|
|
31
|
+
- Drizzle schema file(s) (`src/shared/db/schema.ts`)
|
|
32
|
+
- Pure type-only files (no runtime logic)
|
|
33
|
+
- Portal/browser-API-dependent UI wrappers (e.g., `src/shared/components/ui/sonner.tsx`)
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// vitest.config.ts — add to coverage.exclude before writing tests
|
|
37
|
+
exclude: [
|
|
38
|
+
"src/shared/db/schema.ts",
|
|
39
|
+
"src/shared/components/ui/sonner.tsx",
|
|
40
|
+
]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Configuring exclusions upfront prevents reactive coverage fixes mid-implementation.
|
|
44
|
+
|
|
45
|
+
### 4. TDD: RED Phase
|
|
29
46
|
Write ALL test files first:
|
|
30
47
|
- `__tests__/<component>.test.tsx` — component tests
|
|
31
48
|
- `__tests__/use-<feature>.test.ts` — hook tests
|
|
@@ -34,16 +51,16 @@ Write ALL test files first:
|
|
|
34
51
|
|
|
35
52
|
Run `pnpm test:unit` — all tests must FAIL (RED).
|
|
36
53
|
|
|
37
|
-
###
|
|
54
|
+
### 5. TDD: GREEN Phase
|
|
38
55
|
Implement minimum code to pass each test:
|
|
39
56
|
- Components → actions → hooks → API routes
|
|
40
57
|
|
|
41
58
|
Run `pnpm test:unit` — all tests must PASS (GREEN).
|
|
42
59
|
|
|
43
|
-
###
|
|
60
|
+
### 6. Refactor
|
|
44
61
|
Clean up while keeping tests green.
|
|
45
62
|
|
|
46
|
-
###
|
|
63
|
+
### 7. Verify
|
|
47
64
|
```bash
|
|
48
65
|
pnpm test:coverage # Must show 100%
|
|
49
66
|
pnpm lint # Must pass with 0 warnings
|
package/template/CLAUDE.md
CHANGED
|
@@ -19,10 +19,26 @@ Read these rules when working on related files:
|
|
|
19
19
|
|
|
20
20
|
This project uses specialist agents in `.claude/agents/`. Follow the technical-lead workflow:
|
|
21
21
|
|
|
22
|
-
- **New feature**: requirements (`business-intelligence`) → task breakdown (`technical-lead`) → tests first (`test-qa`) → implementation (`backend
|
|
22
|
+
- **New feature**: requirements (`business-intelligence`) → task breakdown (`technical-lead`) → tests first (`test-qa`) → implementation (`backend` + `frontend` **in parallel**) → review (`code-reviewer` + `security-researcher` **in parallel**)
|
|
23
23
|
- **Bug fix**: reproduce with failing test (`test-qa`) → fix (`backend`/`frontend`) → review (`code-reviewer`)
|
|
24
24
|
- **Refactor**: plan (`technical-lead`) → implement (`backend`/`frontend`) → verify (`test-qa`) → review (`code-reviewer`)
|
|
25
25
|
|
|
26
|
+
## Recommended: 2-Conversation Workflow for New Features
|
|
27
|
+
|
|
28
|
+
Split new feature work across two conversations to avoid context exhaustion (hitting >80% context mid-implementation):
|
|
29
|
+
|
|
30
|
+
**Conversation 1 — Requirements** (low context, can be discarded after)
|
|
31
|
+
```
|
|
32
|
+
@business-intelligence → write .requirements/<feature-name>.md → confirm with user
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Conversation 2 — Implementation** (fresh context, reads spec from file)
|
|
36
|
+
```
|
|
37
|
+
/create-feature → reads .requirements/<feature-name>.md → full TDD pipeline
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The `/create-feature` skill reads the requirements file directly, so the BI conversation history is not needed during implementation. This keeps each conversation well under 50% context usage.
|
|
41
|
+
|
|
26
42
|
# File Naming
|
|
27
43
|
|
|
28
44
|
- Server Actions: `name.action.ts` with `"use server"` at top
|
package/template/next.config.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { NextConfig } from "next";
|
|
2
2
|
|
|
3
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
4
|
+
|
|
3
5
|
const nextConfig: NextConfig = {
|
|
4
6
|
typedRoutes: true,
|
|
5
7
|
logging: {
|
|
@@ -21,7 +23,8 @@ const nextConfig: NextConfig = {
|
|
|
21
23
|
value: [
|
|
22
24
|
"default-src 'self'",
|
|
23
25
|
// TODO: replace 'unsafe-inline' with nonce-based CSP
|
|
24
|
-
|
|
26
|
+
// 'unsafe-eval' is added in dev only for React's debugging features (never in production)
|
|
27
|
+
`script-src 'self' 'unsafe-inline'${isDev ? " 'unsafe-eval'" : ""}`,
|
|
25
28
|
"style-src 'self' 'unsafe-inline'",
|
|
26
29
|
"img-src 'self' data: blob: https:",
|
|
27
30
|
"font-src 'self'",
|
package/template/tailwind.css
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
|
|
3
3
|
@theme {
|
|
4
|
-
--color-background:
|
|
5
|
-
--color-foreground:
|
|
6
|
-
--color-primary:
|
|
7
|
-
--color-primary-foreground:
|
|
8
|
-
--color-secondary:
|
|
9
|
-
--color-secondary-foreground:
|
|
10
|
-
--color-muted:
|
|
11
|
-
--color-muted-foreground:
|
|
12
|
-
--color-accent:
|
|
13
|
-
--color-accent-foreground:
|
|
4
|
+
--color-background: #ffffff;
|
|
5
|
+
--color-foreground: #111111;
|
|
6
|
+
--color-primary: #022633;
|
|
7
|
+
--color-primary-foreground: #ffffff;
|
|
8
|
+
--color-secondary: #f6a623;
|
|
9
|
+
--color-secondary-foreground: #ffffff;
|
|
10
|
+
--color-muted: #f5f5f5;
|
|
11
|
+
--color-muted-foreground: #666666;
|
|
12
|
+
--color-accent: #044a68;
|
|
13
|
+
--color-accent-foreground: #ffffff;
|
|
14
14
|
--color-destructive: hsl(0 84.2% 60.2%);
|
|
15
|
-
--color-destructive-foreground:
|
|
16
|
-
--color-border:
|
|
17
|
-
--color-input:
|
|
18
|
-
--color-ring:
|
|
15
|
+
--color-destructive-foreground: #ffffff;
|
|
16
|
+
--color-border: #e5e5e5;
|
|
17
|
+
--color-input: #e5e5e5;
|
|
18
|
+
--color-ring: #022633;
|
|
19
19
|
--radius: 0.5rem;
|
|
20
20
|
}
|