nextjs-hackathon-stack 0.1.35 → 0.1.37
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/dist/index.js +33 -14
- package/package.json +1 -1
- package/template/.cursor/agents/backend.md +6 -3
- package/template/.cursor/agents/business-intelligence.md +5 -3
- package/template/.cursor/agents/code-reviewer.md +3 -3
- package/template/.cursor/agents/frontend.md +6 -3
- package/template/.cursor/agents/security-researcher.md +1 -1
- package/template/.cursor/agents/technical-lead.md +8 -4
- package/template/.cursor/agents/test-qa.md +17 -11
- package/template/.cursor/memory/architecture-snapshot.md +78 -1
- package/template/.cursor/rules/architecture.mdc +1 -0
- package/template/.cursor/rules/coding-standards.mdc +4 -4
- package/template/.cursor/rules/forms.mdc +2 -0
- package/template/.cursor/rules/general.mdc +2 -3
- package/template/.cursor/rules/supabase.mdc +1 -1
- package/template/.cursor/rules/testing.mdc +7 -5
- package/template/.cursor/skills/build-feature/SKILL.md +199 -0
- package/template/.cursor/skills/create-api-route/SKILL.md +1 -1
- package/template/.cursor/skills/discover-feature/SKILL.md +111 -0
- package/template/.cursor/skills/memory/SKILL.md +208 -0
- package/template/.cursor/skills/review-branch/SKILL.md +1 -1
- package/template/.cursor/skills/security-audit/SKILL.md +1 -1
- package/template/.cursor/skills/security-audit/references/audit-steps.md +1 -1
- package/template/AGENTS.md +29 -1
- package/template/CLAUDE.md +31 -9
- package/template/README.md +216 -2
- package/template/drizzle.config.ts +1 -1
- package/template/src/features/todos/components/todo-list.tsx +1 -1
- package/template/src/shared/__tests__/schema.test.ts +1 -1
- package/template/src/shared/db/index.ts +4 -1
- package/template/src/shared/db/profiles.schema.ts +15 -0
- package/template/src/shared/db/schema.ts +2 -29
- package/template/src/shared/db/todos.schema.ts +16 -0
- package/template/vitest.config.ts +4 -4
- package/template/.cursor/skills/create-feature/SKILL.md +0 -136
- /package/template/.cursor/skills/{create-feature → build-feature}/references/server-action-test-template.md +0 -0
package/template/README.md
CHANGED
|
@@ -98,5 +98,219 @@ Husky runs `vitest --coverage` on every commit. The commit is blocked if coverag
|
|
|
98
98
|
Cursor rules, agents, and skills are preconfigured in `.cursor/`:
|
|
99
99
|
|
|
100
100
|
- **Rules** (11): always-on guardrails for coding standards, architecture, security, and more
|
|
101
|
-
- **Agents** (7): specialized roles (technical-lead
|
|
102
|
-
- **Skills** (
|
|
101
|
+
- **Agents** (7): specialized roles (`technical-lead`, `frontend`, `backend`, `test-qa`, `business-intelligence`, `code-reviewer`, `security-researcher`)
|
|
102
|
+
- **Skills** (5): `/discover-feature`, `/build-feature`, `/create-api-route`, `/review-branch`, `/security-audit`
|
|
103
|
+
|
|
104
|
+
### Initial Setup (once per project)
|
|
105
|
+
|
|
106
|
+
**1. Install mcp-memory-service** (if not already installed):
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# macOS
|
|
110
|
+
brew install pipx && pipx ensurepath
|
|
111
|
+
pipx install mcp-memory-service
|
|
112
|
+
|
|
113
|
+
# Linux / Windows
|
|
114
|
+
pip install pipx
|
|
115
|
+
pipx install mcp-memory-service
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
> **macOS note:** If you see `SQLite extension loading not supported`, run:
|
|
119
|
+
> `pipx install mcp-memory-service --python $(brew --prefix python@3.12)/bin/python3.12`
|
|
120
|
+
|
|
121
|
+
**2. Populate MCP memory** so agents load context efficiently:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
/memory sync
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This parses `.cursor/memory/architecture-snapshot.md` into semantic memory. Agents query only what they need instead of reading the full file.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
### New Feature Workflow
|
|
132
|
+
|
|
133
|
+
Everything runs in **Agent mode**. Only two prompts across two conversations.
|
|
134
|
+
|
|
135
|
+
#### Conversation 1 — Requirements
|
|
136
|
+
|
|
137
|
+
**Prompt:**
|
|
138
|
+
```
|
|
139
|
+
/discover-feature <describe your feature in plain language>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**What happens:**
|
|
143
|
+
1. Loads existing features from MCP memory to identify relationships
|
|
144
|
+
2. Asks you 9 discovery questions (problem, user flows, edge cases, access rules, etc.)
|
|
145
|
+
3. Confirms understanding with you before writing anything
|
|
146
|
+
4. Writes the functional issue to `.requirements/<feature-name>.md`
|
|
147
|
+
5. Stores the requirement in MCP memory
|
|
148
|
+
|
|
149
|
+
**Output:** `.requirements/<feature-name>.md` with user story, acceptance criteria, and functional test cases.
|
|
150
|
+
|
|
151
|
+
> Start a new conversation before the next step.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
#### Conversation 2 — Build (fresh conversation)
|
|
156
|
+
|
|
157
|
+
**Prompt:**
|
|
158
|
+
```
|
|
159
|
+
/build-feature @.requirements/<feature-name>.md
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**What happens (automated, step by step):**
|
|
163
|
+
|
|
164
|
+
| Step | What it does |
|
|
165
|
+
|------|-------------|
|
|
166
|
+
| 1. Read spec | Reads `.requirements/<feature-name>.md` |
|
|
167
|
+
| 2. Load context | Queries MCP memory for schema, features, patterns, rules (targeted — no full file read) |
|
|
168
|
+
| 3. **Plan** | Tech-lead role: maps acceptance criteria to tasks, plans test structure, identifies reusable patterns → **asks your approval before coding** |
|
|
169
|
+
| 4. Feature structure | Creates `src/features/<name>/` directory layout |
|
|
170
|
+
| 5. Pre-test setup | Updates `vitest.config.ts` exclusions |
|
|
171
|
+
| 6. TDD RED | Writes all test files. Runs `pnpm test:unit` → must FAIL |
|
|
172
|
+
| 7. TDD GREEN | Runs `@backend` + `@frontend` in parallel. Runs `pnpm test:unit` → must PASS |
|
|
173
|
+
| 8. Refactor | Cleans up while keeping tests green |
|
|
174
|
+
| 9. Verify | Runs `pnpm test:coverage` + `pnpm lint` + `pnpm typecheck` in single pass |
|
|
175
|
+
| 10. Review gate | Runs `@code-reviewer` + `@security-researcher` in parallel |
|
|
176
|
+
| 11. Memory sync | Updates architecture snapshot + runs `/memory sync` |
|
|
177
|
+
|
|
178
|
+
**Output:** Fully implemented, tested, reviewed feature. Memory updated for the next session.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### Example: Hiring Candidates Feature
|
|
183
|
+
|
|
184
|
+
A real end-to-end walkthrough using the two-conversation workflow.
|
|
185
|
+
|
|
186
|
+
#### Conversation 1 — Requirements
|
|
187
|
+
|
|
188
|
+
**Prompt (Agent mode):**
|
|
189
|
+
```
|
|
190
|
+
/discover-feature Gestión de candidatos de contratación.
|
|
191
|
+
|
|
192
|
+
Vista principal: tabla de candidatos con columnas nombre e identificación (la
|
|
193
|
+
identificación es única por candidato).
|
|
194
|
+
Comportamiento maestro-detalle: al seleccionar una fila de la tabla, mostrar en
|
|
195
|
+
un panel lateral derecho todos los soportes (documentos adjuntos) que pertenecen
|
|
196
|
+
al candidato seleccionado.
|
|
197
|
+
Encima de la tabla, un botón "Agregar candidato" que abre un formulario con los
|
|
198
|
+
campos nombre e identificación. El número de identificación no puede repetirse.
|
|
199
|
+
Toda la UI en español.
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
> **Why this prompt works well:**
|
|
203
|
+
> - One concern per line — table, selection behavior, side panel, add form, uniqueness rule
|
|
204
|
+
> - Names the UI pattern ("maestro-detalle") so the agent picks the right shadcn components (`ResizablePanelGroup`)
|
|
205
|
+
> - Clarifies "soportes" = documentos adjuntos — no ambiguity
|
|
206
|
+
> - States uniqueness constraint explicitly (becomes a DB unique index + validation rule)
|
|
207
|
+
> - Declares language upfront — no back-and-forth later
|
|
208
|
+
|
|
209
|
+
**What happens:** The BI agent asks clarifying questions (upload limits? who can add candidates? pagination?), then writes `.requirements/hiring-candidates.md`.
|
|
210
|
+
|
|
211
|
+
**Output:**
|
|
212
|
+
```
|
|
213
|
+
.requirements/hiring-candidates.md
|
|
214
|
+
├── User Story
|
|
215
|
+
├── Acceptance Criteria (AC1–AC6)
|
|
216
|
+
└── Functional Test Cases (TC1–TC8)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
> Start a new conversation before the next step.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
#### Conversation 2 — Build
|
|
224
|
+
|
|
225
|
+
**Prompt (Agent mode):**
|
|
226
|
+
```
|
|
227
|
+
/build-feature @.requirements/hiring-candidates.md
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**What the automated pipeline produces:**
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
src/features/hiring-candidates/
|
|
234
|
+
├── components/
|
|
235
|
+
│ ├── candidates-table.tsx # Table with row selection
|
|
236
|
+
│ ├── candidate-detail-panel.tsx # Right panel — soportes list
|
|
237
|
+
│ ├── add-candidate-dialog.tsx # Dialog with name + ID form
|
|
238
|
+
│ └── __tests__/
|
|
239
|
+
│ ├── candidates-table.test.tsx
|
|
240
|
+
│ ├── candidate-detail-panel.test.tsx
|
|
241
|
+
│ └── add-candidate-dialog.test.tsx
|
|
242
|
+
├── actions/
|
|
243
|
+
│ ├── candidates.action.ts # createCandidate Server Action
|
|
244
|
+
│ └── __tests__/
|
|
245
|
+
│ └── candidates.action.test.ts
|
|
246
|
+
└── queries/
|
|
247
|
+
├── candidates.queries.ts # getCandidates, getSoportes
|
|
248
|
+
└── __tests__/
|
|
249
|
+
└── candidates.queries.test.ts
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Planning output (step 3 — shown before coding starts):**
|
|
253
|
+
|
|
254
|
+
> Backend: new `candidates` table (name, identification UNIQUE), new `soportes` table (candidateId FK), RLS policies, Server Action for createCandidate with Zod validation.
|
|
255
|
+
> Frontend: ResizablePanelGroup layout, CandidatesTable with row selection state, CandidateDetailPanel, AddCandidateDialog with React Hook Form + zodResolver.
|
|
256
|
+
> Tests: 8 unit tests covering unauthenticated, duplicate ID, DB error, happy path for action; RTL tests for each component.
|
|
257
|
+
> Approve to proceed?
|
|
258
|
+
|
|
259
|
+
**Final output:** Fully tested feature, 0 lint warnings, review gate passed, architecture snapshot updated.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### Other Workflows
|
|
264
|
+
|
|
265
|
+
#### Bug Fix (Agent mode)
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
@test-qa Reproduce this bug: <describe what's broken and where>
|
|
269
|
+
```
|
|
270
|
+
→ Produces a failing test, then:
|
|
271
|
+
```
|
|
272
|
+
@backend Fix the failing test in <file>
|
|
273
|
+
```
|
|
274
|
+
or `@frontend` for UI bugs, then:
|
|
275
|
+
```
|
|
276
|
+
@code-reviewer Review the changes in src/features/<feature>/
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Refactor (Agent mode)
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
@technical-lead Plan refactor for <scope/reason>
|
|
283
|
+
```
|
|
284
|
+
→ Plan output, then:
|
|
285
|
+
```
|
|
286
|
+
@backend Implement the refactor plan
|
|
287
|
+
```
|
|
288
|
+
Then verify + review:
|
|
289
|
+
```
|
|
290
|
+
@test-qa Verify all tests still pass
|
|
291
|
+
@code-reviewer Review the refactor changes
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Find Context Fast (any mode)
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
/memory recall "form validation patterns"
|
|
298
|
+
/memory recall "existing auth tables"
|
|
299
|
+
/memory recall "how are errors handled in actions"
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
### Quick Reference
|
|
305
|
+
|
|
306
|
+
| Task | Mode | Prompt |
|
|
307
|
+
|------|------|--------|
|
|
308
|
+
| Define requirements | Agent | `/discover-feature <description>` |
|
|
309
|
+
| Implement feature | Agent | `/build-feature @.requirements/<name>.md` |
|
|
310
|
+
| Sync memory after changes | Agent | `/memory sync` |
|
|
311
|
+
| Search project knowledge | Any | `/memory recall "query"` |
|
|
312
|
+
| Create API route | Agent | `/create-api-route` |
|
|
313
|
+
| Review a branch or PR | Agent | `/review-branch` |
|
|
314
|
+
| Security audit | Agent | `/security-audit` |
|
|
315
|
+
| Reproduce a bug | Agent | `@test-qa Reproduce: <description>` |
|
|
316
|
+
| Plan an architectural change | Agent | `@technical-lead Plan: <description>` |
|
|
@@ -4,7 +4,7 @@ import { defineConfig } from "drizzle-kit";
|
|
|
4
4
|
loadEnvConfig(process.cwd());
|
|
5
5
|
|
|
6
6
|
export default defineConfig({
|
|
7
|
-
schema: "./src/shared/db
|
|
7
|
+
schema: "./src/shared/db/*.schema.ts",
|
|
8
8
|
out: "./src/shared/db/migrations",
|
|
9
9
|
dialect: "postgresql",
|
|
10
10
|
dbCredentials: {
|
|
@@ -6,7 +6,7 @@ import { toast } from "sonner";
|
|
|
6
6
|
import { deleteTodoAction, toggleTodoAction } from "../actions/todos.action";
|
|
7
7
|
|
|
8
8
|
import { Spinner } from "@/shared/components/ui/spinner";
|
|
9
|
-
import type { SelectTodo } from "@/shared/db/schema";
|
|
9
|
+
import type { SelectTodo } from "@/shared/db/todos.schema";
|
|
10
10
|
|
|
11
11
|
interface TodoListProps {
|
|
12
12
|
items: SelectTodo[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
|
|
3
|
-
import { insertProfileSchema, selectProfileSchema } from "../db/schema";
|
|
3
|
+
import { insertProfileSchema, selectProfileSchema } from "../db/profiles.schema";
|
|
4
4
|
|
|
5
5
|
describe("profiles schema", () => {
|
|
6
6
|
it("insertProfileSchema validates required fields", () => {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { drizzle } from "drizzle-orm/postgres-js";
|
|
2
2
|
import postgres from "postgres";
|
|
3
3
|
|
|
4
|
-
import * as
|
|
4
|
+
import * as profiles from "./profiles.schema";
|
|
5
|
+
import * as todos from "./todos.schema";
|
|
6
|
+
|
|
7
|
+
const schema = { ...profiles, ...todos };
|
|
5
8
|
|
|
6
9
|
const client = postgres(process.env.DATABASE_URL ?? "");
|
|
7
10
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
|
2
|
+
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
|
3
|
+
|
|
4
|
+
export const profiles = pgTable("profiles", {
|
|
5
|
+
id: uuid("id").primaryKey(),
|
|
6
|
+
email: text("email").notNull().unique(),
|
|
7
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
8
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const insertProfileSchema = createInsertSchema(profiles);
|
|
12
|
+
export const selectProfileSchema = createSelectSchema(profiles);
|
|
13
|
+
|
|
14
|
+
export type InsertProfile = typeof profiles.$inferInsert;
|
|
15
|
+
export type SelectProfile = typeof profiles.$inferSelect;
|
|
@@ -1,29 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export const profiles = pgTable("profiles", {
|
|
5
|
-
id: uuid("id").primaryKey(),
|
|
6
|
-
email: text("email").notNull().unique(),
|
|
7
|
-
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
8
|
-
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
export const insertProfileSchema = createInsertSchema(profiles);
|
|
12
|
-
export const selectProfileSchema = createSelectSchema(profiles);
|
|
13
|
-
|
|
14
|
-
export type InsertProfile = typeof profiles.$inferInsert;
|
|
15
|
-
export type SelectProfile = typeof profiles.$inferSelect;
|
|
16
|
-
|
|
17
|
-
export const todos = pgTable("todos", {
|
|
18
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
19
|
-
userId: uuid("user_id").notNull(),
|
|
20
|
-
title: text("title").notNull(),
|
|
21
|
-
completed: boolean("completed").notNull().default(false),
|
|
22
|
-
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
export const insertTodoSchema = createInsertSchema(todos);
|
|
26
|
-
export const selectTodoSchema = createSelectSchema(todos);
|
|
27
|
-
|
|
28
|
-
export type InsertTodo = typeof todos.$inferInsert;
|
|
29
|
-
export type SelectTodo = typeof todos.$inferSelect;
|
|
1
|
+
export * from "./profiles.schema";
|
|
2
|
+
export * from "./todos.schema";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { boolean, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
|
2
|
+
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
|
3
|
+
|
|
4
|
+
export const todos = pgTable("todos", {
|
|
5
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
6
|
+
userId: uuid("user_id").notNull(),
|
|
7
|
+
title: text("title").notNull(),
|
|
8
|
+
completed: boolean("completed").notNull().default(false),
|
|
9
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const insertTodoSchema = createInsertSchema(todos);
|
|
13
|
+
export const selectTodoSchema = createSelectSchema(todos);
|
|
14
|
+
|
|
15
|
+
export type InsertTodo = typeof todos.$inferInsert;
|
|
16
|
+
export type SelectTodo = typeof todos.$inferSelect;
|
|
@@ -12,10 +12,10 @@ export default defineConfig({
|
|
|
12
12
|
coverage: {
|
|
13
13
|
provider: "v8",
|
|
14
14
|
thresholds: {
|
|
15
|
-
branches:
|
|
16
|
-
functions:
|
|
17
|
-
lines:
|
|
18
|
-
statements:
|
|
15
|
+
branches: 90,
|
|
16
|
+
functions: 95,
|
|
17
|
+
lines: 95,
|
|
18
|
+
statements: 95,
|
|
19
19
|
},
|
|
20
20
|
exclude: [
|
|
21
21
|
"node_modules/**",
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: create-feature
|
|
3
|
-
description: Scaffold a new feature following TDD and project conventions. Use when starting a new feature or user story.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Create Feature Skill
|
|
7
|
-
|
|
8
|
-
> **Invoke as:** `/create-feature @.requirements/<feature-name>.md`
|
|
9
|
-
> This skill is orchestrated by the `@technical-lead` agent — do NOT add `use @technical-lead` to the invocation, it is redundant.
|
|
10
|
-
|
|
11
|
-
## IMPORTANT: Run this in a FRESH conversation
|
|
12
|
-
|
|
13
|
-
If this conversation already contains requirements gathering (BI agent output), **start a new conversation** before running `/create-feature`. Reusing the same context risks hitting the token limit mid-implementation.
|
|
14
|
-
|
|
15
|
-
If context usage exceeds 60% at any point during this skill, stop and tell the user to continue in a new conversation, referencing this plan file.
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Process
|
|
20
|
-
|
|
21
|
-
### 1. Requirements First
|
|
22
|
-
- Check `.requirements/` for an existing functional issue
|
|
23
|
-
- If a spec exists, read it and proceed to Step 2
|
|
24
|
-
- **If no spec exists, call @business-intelligence** to run the discovery process and produce a functional issue in `.requirements/<feature-name>.md`
|
|
25
|
-
- Wait for the functional issue to be written and confirmed by the user before proceeding to Step 2
|
|
26
|
-
|
|
27
|
-
### 2. Read the Architecture Snapshot
|
|
28
|
-
|
|
29
|
-
Read `.cursor/memory/architecture-snapshot.md`. This tells you:
|
|
30
|
-
- Which shadcn/ui components are already installed (no need to `shadcn add` duplicates)
|
|
31
|
-
- The current DB schema (what tables exist, what to extend)
|
|
32
|
-
- Existing features and their paths (avoid recreating patterns)
|
|
33
|
-
- Canonical pattern references (copy from these, do not reinvent)
|
|
34
|
-
|
|
35
|
-
### 3. Create Feature Structure
|
|
36
|
-
```
|
|
37
|
-
src/features/<feature-name>/
|
|
38
|
-
├── components/
|
|
39
|
-
├── actions/
|
|
40
|
-
├── queries/
|
|
41
|
-
├── hooks/
|
|
42
|
-
├── api/
|
|
43
|
-
├── lib/
|
|
44
|
-
└── __tests__/
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### 4. Pre-Test Setup (do this before writing any tests)
|
|
48
|
-
|
|
49
|
-
Update `vitest.config.ts` to exclude files that cannot be meaningfully tested in jsdom:
|
|
50
|
-
- Drizzle schema file(s) (`src/shared/db/schema.ts`)
|
|
51
|
-
- Pure type-only files (no runtime logic)
|
|
52
|
-
- Portal/browser-API-dependent UI wrappers (e.g., `src/shared/components/ui/sonner.tsx`)
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
// vitest.config.ts — add to coverage.exclude before writing tests
|
|
56
|
-
exclude: [
|
|
57
|
-
"src/shared/db/schema.ts",
|
|
58
|
-
"src/shared/components/ui/sonner.tsx",
|
|
59
|
-
]
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Configuring exclusions upfront prevents reactive coverage fixes mid-implementation.
|
|
63
|
-
|
|
64
|
-
### 5. TDD: RED Phase
|
|
65
|
-
|
|
66
|
-
Write ALL test files first — zero implementation code at this stage:
|
|
67
|
-
- `__tests__/<component>.test.tsx` — component tests
|
|
68
|
-
- `__tests__/use-<feature>.test.ts` — hook tests (if applicable)
|
|
69
|
-
- `__tests__/<action>.action.test.ts` — action tests (see `references/server-action-test-template.md`)
|
|
70
|
-
- `__tests__/<feature>.queries.test.ts` — query tests
|
|
71
|
-
|
|
72
|
-
Import mock helpers from `@/shared/test-utils/supabase-mock` — do not inline mock chains.
|
|
73
|
-
|
|
74
|
-
**BLOCKING GATE — do not proceed until this passes:**
|
|
75
|
-
Run `pnpm test:unit` and paste the output here. All new tests must **FAIL** (red). If any new test passes without implementation, the test is wrong — fix it before continuing.
|
|
76
|
-
|
|
77
|
-
### 6. TDD: GREEN Phase
|
|
78
|
-
|
|
79
|
-
Launch **@backend and @frontend in parallel** — they work on independent files:
|
|
80
|
-
|
|
81
|
-
| @backend handles | @frontend handles |
|
|
82
|
-
|-----------------|-------------------|
|
|
83
|
-
| `actions/` | `components/` |
|
|
84
|
-
| `queries/` | `page.tsx` |
|
|
85
|
-
| `schema.ts` changes | shadcn component installs |
|
|
86
|
-
| RLS policies | Loading/empty states |
|
|
87
|
-
|
|
88
|
-
Do NOT serialize these — they touch different files.
|
|
89
|
-
|
|
90
|
-
**BLOCKING GATE — do not proceed until this passes:**
|
|
91
|
-
Run `pnpm test:unit` and paste the output. All tests must **PASS** (green).
|
|
92
|
-
|
|
93
|
-
### 7. Refactor
|
|
94
|
-
Clean up while keeping tests green.
|
|
95
|
-
|
|
96
|
-
### 8. Verify & Self-Check
|
|
97
|
-
|
|
98
|
-
Run all three and paste output:
|
|
99
|
-
```bash
|
|
100
|
-
pnpm test:coverage # Must show 100% across all metrics
|
|
101
|
-
pnpm lint # Must pass with 0 warnings
|
|
102
|
-
pnpm typecheck # Must pass with 0 errors
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
Before moving to the review gate, verify manually:
|
|
106
|
-
- [ ] No `any` types: `grep -r ": any" src/features/<feature>/`
|
|
107
|
-
- [ ] No `eslint-disable` comments
|
|
108
|
-
- [ ] All UI text in Spanish, all `it()`/`describe()` text in English
|
|
109
|
-
- [ ] No file over 200 lines
|
|
110
|
-
- [ ] No function over 20 lines
|
|
111
|
-
- [ ] AAA pattern (`// Arrange`, `// Act`, `// Assert`) in every test
|
|
112
|
-
- [ ] `ActionResult` returned from every Server Action mutation
|
|
113
|
-
- [ ] Toast feedback (`toast.success` / `toast.error`) for every mutation
|
|
114
|
-
- [ ] RLS policies written for every new table
|
|
115
|
-
|
|
116
|
-
### 9. Review Gate
|
|
117
|
-
|
|
118
|
-
Run @code-reviewer and @security-researcher **in parallel** on the changed files. Fix any findings before marking the feature complete.
|
|
119
|
-
|
|
120
|
-
This step is not optional. The feature is not done until both reviewers pass.
|
|
121
|
-
|
|
122
|
-
### 10. Update Architecture Snapshot
|
|
123
|
-
|
|
124
|
-
Update `.cursor/memory/architecture-snapshot.md`:
|
|
125
|
-
- Add new DB tables to the schema table
|
|
126
|
-
- Add new shadcn components to the installed list
|
|
127
|
-
- Add the new feature to the Existing Features table
|
|
128
|
-
- Add any new canonical pattern references that differ from existing ones
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## Guardrails
|
|
133
|
-
- NEVER start implementation before the RED gate is confirmed with actual test output
|
|
134
|
-
- 100% coverage before marking done
|
|
135
|
-
- Follow `features/* → shared/*` dependency direction
|
|
136
|
-
- RLS is mandatory for every new table — not a post-step
|
|
File without changes
|