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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextjs-hackathon-stack",
3
- "version": "0.1.31",
3
+ "version": "0.1.32",
4
4
  "description": "Scaffold a full-stack Next.js hackathon starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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) → @backend/@frontend (GREEN) → @code-reviewer @security-researcher
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
- - @backend/@frontend implements to make tests pass (GREEN)
68
- - @code-reviewer and @security-researcher review the result
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: Feature-based architecture rules. Always applies.
3
- alwaysApply: true
2
+ description: Feature-based architecture rules. Applies to all source files.
3
+ alwaysApply: false
4
+ globs: ["src/**"]
4
5
  ---
5
6
 
6
7
  # Architecture Rules
@@ -1,6 +1,7 @@
1
1
  ---
2
- description: Code quality standards. Always applies to all files.
3
- alwaysApply: true
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).
@@ -1,6 +1,7 @@
1
1
  ---
2
- description: Stack overview and project conventions. Always applies.
3
- alwaysApply: true
2
+ description: Stack overview and project conventions. Applies to all source files.
3
+ alwaysApply: false
4
+ globs: ["src/**"]
4
5
  ---
5
6
 
6
7
  # Stack Overview
@@ -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
- // Never — unsafe-eval is forbidden
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. TDD: RED Phase
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
- ### 4. TDD: GREEN Phase
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
- ### 5. Refactor
60
+ ### 6. Refactor
44
61
  Clean up while keeping tests green.
45
62
 
46
- ### 6. Verify
63
+ ### 7. Verify
47
64
  ```bash
48
65
  pnpm test:coverage # Must show 100%
49
66
  pnpm lint # Must pass with 0 warnings
@@ -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`/`frontend`) → review (`code-reviewer`) security (`security-researcher`)
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
@@ -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
- "script-src 'self' 'unsafe-inline'",
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'",
@@ -1,20 +1,20 @@
1
1
  @import "tailwindcss";
2
2
 
3
3
  @theme {
4
- --color-background: hsl(0 0% 100%);
5
- --color-foreground: hsl(222.2 84% 4.9%);
6
- --color-primary: hsl(222.2 47.4% 11.2%);
7
- --color-primary-foreground: hsl(210 40% 98%);
8
- --color-secondary: hsl(210 40% 96.1%);
9
- --color-secondary-foreground: hsl(222.2 47.4% 11.2%);
10
- --color-muted: hsl(210 40% 96.1%);
11
- --color-muted-foreground: hsl(215.4 16.3% 46.9%);
12
- --color-accent: hsl(210 40% 96.1%);
13
- --color-accent-foreground: hsl(222.2 47.4% 11.2%);
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: hsl(210 40% 98%);
16
- --color-border: hsl(214.3 31.8% 91.4%);
17
- --color-input: hsl(214.3 31.8% 91.4%);
18
- --color-ring: hsl(222.2 84% 4.9%);
15
+ --color-destructive-foreground: #ffffff;
16
+ --color-border: #e5e5e5;
17
+ --color-input: #e5e5e5;
18
+ --color-ring: #022633;
19
19
  --radius: 0.5rem;
20
20
  }