nextjs-hackathon-stack 0.1.40 → 0.1.42
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 +3 -63
- package/package.json +1 -1
- package/template/.claude/agents/backend.md +54 -0
- package/template/.claude/agents/business-analyst.md +195 -0
- package/template/.claude/agents/code-reviewer.md +76 -0
- package/template/.claude/agents/frontend.md +85 -0
- package/template/.claude/agents/security-researcher.md +54 -0
- package/template/.claude/agents/technical-lead.md +92 -0
- package/template/.claude/agents/test-qa.md +85 -0
- package/template/.claude/rules/architecture.mdc +48 -0
- package/template/.claude/rules/coding-standards.mdc +120 -0
- package/template/.claude/rules/components.mdc +49 -0
- package/template/.claude/rules/data-fetching.mdc +115 -0
- package/template/.claude/rules/forms.mdc +100 -0
- package/template/.claude/rules/general.mdc +54 -0
- package/template/.claude/rules/migrations.mdc +11 -0
- package/template/.claude/rules/nextjs.mdc +71 -0
- package/template/.claude/rules/security.mdc +108 -0
- package/template/.claude/rules/supabase.mdc +70 -0
- package/template/.claude/rules/testing.mdc +136 -0
- package/template/.claude/settings.json +16 -0
- package/template/.claude/skills/build-feature/SKILL.md +198 -0
- package/template/.claude/skills/build-feature/references/server-action-test-template.md +103 -0
- package/template/.claude/skills/create-api-route/SKILL.md +62 -0
- package/template/.claude/skills/discover-feature/SKILL.md +200 -0
- package/template/.claude/skills/memory/SKILL.md +208 -0
- package/template/.claude/skills/review-branch/SKILL.md +43 -0
- package/template/.claude/skills/review-branch/references/review-checklist.md +36 -0
- package/template/.claude/skills/security-audit/SKILL.md +40 -0
- package/template/.claude/skills/security-audit/references/audit-steps.md +41 -0
- package/template/.claude/skills/supabase/SKILL.md +105 -0
- package/template/.claude/skills/supabase/assets/feedback-issue-template.md +17 -0
- package/template/.claude/skills/supabase/references/skill-feedback.md +17 -0
- package/template/.claude/skills/supabase-postgres-best-practices/SKILL.md +65 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp__contributing.md +170 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp__sections.md +39 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp__template.md +34 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_advanced-full-text-search.md +55 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_advanced-jsonb-indexing.md +49 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-idle-timeout.md +46 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-limits.md +44 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-pooling.md +41 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-prepared-statements.md +46 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-batch-inserts.md +54 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-n-plus-one.md +53 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-pagination.md +50 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-upsert.md +50 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-advisory.md +56 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-deadlock-prevention.md +68 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-short-transactions.md +50 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-skip-locked.md +54 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_monitor-explain-analyze.md +45 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_monitor-pg-stat-statements.md +55 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_monitor-vacuum-analyze.md +55 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-composite-indexes.md +44 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-covering-indexes.md +40 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-index-types.md +48 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-missing-indexes.md +43 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-partial-indexes.md +45 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-constraints.md +80 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-data-types.md +46 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-foreign-key-indexes.md +59 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-lowercase-identifiers.md +55 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-partitioning.md +55 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-primary-keys.md +61 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_security-privileges.md +54 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_security-rls-basics.md +50 -0
- package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_security-rls-performance.md +57 -0
- package/template/.cursor/agents/business-analyst.md +197 -0
- package/template/.cursor/agents/technical-lead.md +3 -3
- package/template/.cursor/mcp.json +6 -2
- package/template/.cursor/skills/build-feature/SKILL.md +20 -21
- package/template/.cursor/skills/discover-feature/SKILL.md +118 -29
- package/template/.cursor/skills/supabase/SKILL.md +104 -0
- package/template/.cursor/skills/supabase/assets/feedback-issue-template.md +17 -0
- package/template/.cursor/skills/supabase/references/skill-feedback.md +17 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/SKILL.md +64 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp__contributing.md +170 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp__sections.md +39 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp__template.md +34 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_advanced-full-text-search.md +55 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_advanced-jsonb-indexing.md +49 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-idle-timeout.md +46 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-limits.md +44 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-pooling.md +41 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-prepared-statements.md +46 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-batch-inserts.md +54 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-n-plus-one.md +53 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-pagination.md +50 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-upsert.md +50 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-advisory.md +56 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-deadlock-prevention.md +68 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-short-transactions.md +50 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-skip-locked.md +54 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_monitor-explain-analyze.md +45 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_monitor-pg-stat-statements.md +55 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_monitor-vacuum-analyze.md +55 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-composite-indexes.md +44 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-covering-indexes.md +40 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-index-types.md +48 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-missing-indexes.md +43 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-partial-indexes.md +45 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-constraints.md +80 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-data-types.md +46 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-foreign-key-indexes.md +59 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-lowercase-identifiers.md +55 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-partitioning.md +55 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-primary-keys.md +61 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_security-privileges.md +54 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_security-rls-basics.md +50 -0
- package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_security-rls-performance.md +57 -0
- package/template/.mcp.json +16 -0
- package/template/.opencode/agents/backend.md +72 -0
- package/template/.opencode/agents/business-analyst.md +153 -0
- package/template/.opencode/agents/code-reviewer.md +80 -0
- package/template/.opencode/agents/frontend.md +84 -0
- package/template/.opencode/agents/security-researcher.md +58 -0
- package/template/.opencode/agents/technical-lead.md +131 -0
- package/template/.opencode/agents/test-qa.md +103 -0
- package/template/.opencode/memory/architecture-snapshot.md +127 -0
- package/template/.opencode/skills/build-feature/SKILL.md +208 -0
- package/template/.opencode/skills/create-api-route/SKILL.md +63 -0
- package/template/.opencode/skills/discover-feature/SKILL.md +194 -0
- package/template/.opencode/skills/memory/SKILL.md +199 -0
- package/template/.opencode/skills/review-branch/SKILL.md +43 -0
- package/template/.opencode/skills/security-audit/SKILL.md +40 -0
- package/template/.opencode/skills/supabase/SKILL.md +105 -0
- package/template/.opencode/skills/supabase/assets/feedback-issue-template.md +17 -0
- package/template/.opencode/skills/supabase/references/skill-feedback.md +17 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/SKILL.md +65 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp__contributing.md +170 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp__sections.md +39 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp__template.md +34 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_advanced-full-text-search.md +55 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_advanced-jsonb-indexing.md +49 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-idle-timeout.md +46 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-limits.md +44 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-pooling.md +41 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-prepared-statements.md +46 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-batch-inserts.md +54 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-n-plus-one.md +53 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-pagination.md +50 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-upsert.md +50 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-advisory.md +56 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-deadlock-prevention.md +68 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-short-transactions.md +50 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-skip-locked.md +54 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_monitor-explain-analyze.md +45 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_monitor-pg-stat-statements.md +55 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_monitor-vacuum-analyze.md +55 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-composite-indexes.md +44 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-covering-indexes.md +40 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-index-types.md +48 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-missing-indexes.md +43 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-partial-indexes.md +45 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-constraints.md +80 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-data-types.md +46 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-foreign-key-indexes.md +59 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-lowercase-identifiers.md +55 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-partitioning.md +55 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-primary-keys.md +61 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_security-privileges.md +54 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_security-rls-basics.md +50 -0
- package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_security-rls-performance.md +57 -0
- package/template/.requirements/README.md +1 -1
- package/template/AGENTS.md +1 -1
- package/template/CLAUDE.md +1 -1
- package/template/Dockerfile.memory +7 -0
- package/template/README.md +15 -2
- package/template/_gitignore +3 -0
- package/template/docker-compose.yml +28 -0
- package/template/ia-flow.md +341 -0
- package/template/opencode.json +23 -0
- package/template/.cursor/agents/business-intelligence.md +0 -83
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: test-qa
|
|
3
|
+
description: Testing specialist. Use when writing tests, enforcing TDD workflow, fixing coverage gaps, or debugging test failures. Always write tests BEFORE implementation. Triggers: writing tests, TDD workflow, coverage gaps, test failures, mock setup.
|
|
4
|
+
mode: subagent
|
|
5
|
+
model: inherit
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Test & QA Agent
|
|
9
|
+
|
|
10
|
+
## First Step — Load Context via MCP Memory
|
|
11
|
+
|
|
12
|
+
1. Read `package.json` to get the project name (`<project-name>`)
|
|
13
|
+
2. Call `search_memory` with `tags: ["project:<project-name>", "domain:patterns"]` and `query: "test mock supabase"` — canonical test references and mock setup
|
|
14
|
+
3. **Fallback**: if the memory service is unavailable or returns no results, read `.opencode/memory/architecture-snapshot.md` directly
|
|
15
|
+
|
|
16
|
+
After reading test patterns, save findings to MCP memory:
|
|
17
|
+
```
|
|
18
|
+
store_memory({
|
|
19
|
+
content: "Test pattern: <description of what was found>",
|
|
20
|
+
metadata: {
|
|
21
|
+
type: "architecture",
|
|
22
|
+
tags: ["project:<project-name>", "domain:patterns", "category:pattern", "pattern:test"]
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Import `makeChain` and `makeSupabaseMock` from `@/shared/test-utils/supabase-mock` — never recreate the mock chain from scratch.
|
|
28
|
+
|
|
29
|
+
## TDD Workflow
|
|
30
|
+
|
|
31
|
+
1. **RED** — write failing test that describes the desired behavior
|
|
32
|
+
2. **GREEN** — write minimum code to make test pass
|
|
33
|
+
3. **REFACTOR** — clean up while keeping tests green
|
|
34
|
+
4. **VERIFY** — run `pnpm test:coverage` and confirm thresholds met
|
|
35
|
+
|
|
36
|
+
## Verification Gates (mandatory — show output, do not just claim)
|
|
37
|
+
|
|
38
|
+
| Gate | Command | Expected output |
|
|
39
|
+
|------|---------|-----------------|
|
|
40
|
+
| After RED | `pnpm test:unit` | All new tests **FAIL** (red) |
|
|
41
|
+
| After GREEN | `pnpm test:unit` | All tests **PASS** (green) |
|
|
42
|
+
| After VERIFY | `pnpm test:coverage` | ≥95% statements/functions/lines, ≥90% branches |
|
|
43
|
+
|
|
44
|
+
**Never say "tests pass" or "tests fail" without showing the actual output.**
|
|
45
|
+
**Do NOT write any implementation code until the RED gate output confirms failures.**
|
|
46
|
+
|
|
47
|
+
## Coverage Requirement
|
|
48
|
+
```
|
|
49
|
+
branches: 90%
|
|
50
|
+
functions: 95%
|
|
51
|
+
lines: 95%
|
|
52
|
+
statements: 95%
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Use `/* v8 ignore next */` for genuinely unreachable defensive branches only.
|
|
56
|
+
|
|
57
|
+
## Supabase Mock Pattern
|
|
58
|
+
|
|
59
|
+
Always use the shared helpers — never inline mock chain construction:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { makeChain, makeSupabaseMock } from "@/shared/test-utils/supabase-mock";
|
|
63
|
+
|
|
64
|
+
// Unauthenticated
|
|
65
|
+
const { mockClient } = makeSupabaseMock({ user: null });
|
|
66
|
+
|
|
67
|
+
// Authenticated + DB success
|
|
68
|
+
const { mockClient, mockFrom } = makeSupabaseMock({ user: { id: "user-1" } });
|
|
69
|
+
mockFrom.mockReturnValue(makeChain({ data: [...], error: null }));
|
|
70
|
+
|
|
71
|
+
// DB error
|
|
72
|
+
mockFrom.mockReturnValue(makeChain({ error: { message: "db error" } }));
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Test Plan Compliance
|
|
76
|
+
|
|
77
|
+
When the Technical Lead provides a test plan, follow it:
|
|
78
|
+
- Use the specified test files, `describe` block names, and mock setup
|
|
79
|
+
- Flag missing edge cases to the TL **before** adding unplanned tests
|
|
80
|
+
- If the plan is ambiguous, ask for clarification rather than guessing
|
|
81
|
+
|
|
82
|
+
## AAA Pattern
|
|
83
|
+
|
|
84
|
+
Every test must use the Arrange-Act-Assert pattern with labeled comments:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
it("should do X when Y", () => {
|
|
88
|
+
// Arrange
|
|
89
|
+
const input = ...;
|
|
90
|
+
|
|
91
|
+
// Act
|
|
92
|
+
const result = doSomething(input);
|
|
93
|
+
|
|
94
|
+
// Assert
|
|
95
|
+
expect(result).toBe(expected);
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Guardrails
|
|
100
|
+
- Never write implementation without a failing test first
|
|
101
|
+
- Never mock internal project code — only external deps
|
|
102
|
+
- Verify all edge cases: empty states, errors, loading states
|
|
103
|
+
- AAA pattern with labeled comments in every test
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Architecture Snapshot
|
|
2
|
+
|
|
3
|
+
> Auto-updated after each feature. Agents MUST read this before exploring the codebase.
|
|
4
|
+
|
|
5
|
+
## Installed shadcn/ui Components
|
|
6
|
+
|
|
7
|
+
button, card, input, label, spinner
|
|
8
|
+
|
|
9
|
+
_Add new components here after `shadcn add <component>`_
|
|
10
|
+
|
|
11
|
+
## DB Schema
|
|
12
|
+
|
|
13
|
+
| Table | Columns |
|
|
14
|
+
|-------|---------|
|
|
15
|
+
| `profiles` | id (uuid PK), email (text unique), createdAt, updatedAt |
|
|
16
|
+
| `todos` | id (uuid PK), userId (uuid), title (text), completed (bool), createdAt |
|
|
17
|
+
|
|
18
|
+
_Add new tables here after `pnpm db:generate && pnpm db:migrate`_
|
|
19
|
+
|
|
20
|
+
## Existing Features
|
|
21
|
+
|
|
22
|
+
| Feature | Path | Description |
|
|
23
|
+
|---------|------|-------------|
|
|
24
|
+
| auth | `src/features/auth/` | Login/logout, cookie-based sessions via Supabase |
|
|
25
|
+
| todos | `src/features/todos/` | CRUD todos with Supabase RLS |
|
|
26
|
+
|
|
27
|
+
_Add new features here after implementation_
|
|
28
|
+
|
|
29
|
+
## Canonical Pattern References
|
|
30
|
+
|
|
31
|
+
Read these files to understand the project's proven patterns before writing new code:
|
|
32
|
+
|
|
33
|
+
| Pattern | File |
|
|
34
|
+
|---------|------|
|
|
35
|
+
| Server Action | `src/features/todos/actions/todos.action.ts` |
|
|
36
|
+
| Query (repository) | `src/features/todos/queries/todos.queries.ts` |
|
|
37
|
+
| Client component | `src/features/todos/components/todo-list.tsx` |
|
|
38
|
+
| Action test | `src/features/todos/__tests__/todos.action.test.ts` |
|
|
39
|
+
| Component test | `src/features/todos/__tests__/todo-list.test.tsx` |
|
|
40
|
+
| Supabase mock chain | `src/shared/test-utils/supabase-mock.ts` |
|
|
41
|
+
|
|
42
|
+
## Key Rules (summary)
|
|
43
|
+
|
|
44
|
+
- Runtime queries: Supabase client only — Drizzle is schema/migrations only
|
|
45
|
+
- All mutations: Server Actions returning `ActionResult` from `@/shared/lib/action-result`
|
|
46
|
+
- Auth check first in every Server Action: `supabase.auth.getUser()`
|
|
47
|
+
- Toast feedback required for every mutation (success + error) via `sonner`
|
|
48
|
+
- RLS must be enabled on every table before a feature is considered complete
|
|
49
|
+
- UI text: Spanish | Code-level text: English (test descriptions, variable names)
|
|
50
|
+
- Coverage threshold: 95% statements/functions/lines, 90% branches — use `/* v8 ignore next */` for genuinely unreachable defensive branches
|
|
51
|
+
|
|
52
|
+
## Shared Utilities
|
|
53
|
+
|
|
54
|
+
Reuse these before writing new helpers:
|
|
55
|
+
|
|
56
|
+
| Utility | Location | Purpose |
|
|
57
|
+
|---------|----------|---------|
|
|
58
|
+
| `formFieldText(formData, key)` | `src/shared/lib/form-utils.ts` | Safe `FormData` text extraction — avoids `no-base-to-string` lint error |
|
|
59
|
+
| `firstZodIssueMessage(error)` | `src/shared/lib/zod-utils.ts` | Extract first Zod validation error message |
|
|
60
|
+
| `readUploadFileBuffer(file)` | `src/shared/lib/upload-utils.ts` | Read a `File`/`Blob` upload to `ArrayBuffer` safely |
|
|
61
|
+
|
|
62
|
+
## Strict Rules Reference
|
|
63
|
+
|
|
64
|
+
Read this before writing any code. These are the rules that most often cause post-hoc fix cycles.
|
|
65
|
+
|
|
66
|
+
### TypeScript Compiler (`tsconfig.json`)
|
|
67
|
+
|
|
68
|
+
`"strict": true` plus additional flags:
|
|
69
|
+
|
|
70
|
+
| Flag | What it enforces | How to comply |
|
|
71
|
+
|------|-----------------|---------------|
|
|
72
|
+
| `noUncheckedIndexedAccess` | `arr[i]` / `obj[key]` return `T \| undefined` | Guard: `const val = arr[0]; if (val) { ... }` |
|
|
73
|
+
| `exactOptionalPropertyTypes` | Cannot assign `undefined` to optional props | Omit the key entirely; never write `{ prop: undefined }` |
|
|
74
|
+
| `noImplicitOverride` | Subclass overrides need `override` keyword | `override render() {}` |
|
|
75
|
+
| `noFallthroughCasesInSwitch` | Every `case` needs `break`/`return`/`throw` | Add `break` to every case |
|
|
76
|
+
| `noImplicitReturns` | Every code path must return | Add explicit `return` in all branches |
|
|
77
|
+
| `noUnusedLocals` / `noUnusedParameters` | No unused vars/params | Prefix unused params with `_` |
|
|
78
|
+
| `useUnknownInCatchVariables` | `catch (e)` → `e` is `unknown` | Narrow: `if (e instanceof Error)` before `.message` |
|
|
79
|
+
|
|
80
|
+
### ESLint — Rules That Most Often Trip AI Agents
|
|
81
|
+
|
|
82
|
+
Preset: `tseslint.configs.strictTypeChecked` + `stylisticTypeChecked`. Runs with `--max-warnings 0` (warnings = errors).
|
|
83
|
+
|
|
84
|
+
**Unsafe-any family (all "error"):**
|
|
85
|
+
- `no-unsafe-assignment`, `no-unsafe-member-access`, `no-unsafe-call`, `no-unsafe-return`, `no-unsafe-argument`
|
|
86
|
+
- Never let `any` flow through. Cast `JSON.parse()` results. Type all mock returns explicitly.
|
|
87
|
+
|
|
88
|
+
**Promise handling:**
|
|
89
|
+
- `no-floating-promises`: Every Promise must be `await`ed, returned, or `void`-prefixed
|
|
90
|
+
- `no-misused-promises`: Async functions in React event handlers need a `void` wrapper: `onClick={() => void handleSubmit()}`
|
|
91
|
+
- `require-await`: `async` functions must contain `await`; remove `async` if not needed
|
|
92
|
+
- `return-await`: Must use `return await` inside `try/catch`
|
|
93
|
+
|
|
94
|
+
**Type safety:**
|
|
95
|
+
- `no-explicit-any`: Use `unknown` and narrow; never use `any`
|
|
96
|
+
- `no-non-null-assertion`: Cannot use `!` postfix; narrow with conditionals
|
|
97
|
+
- `no-base-to-string`: Objects without `toString()` cannot appear in template literals or string concatenation — use `formFieldText()` for `FormData` values
|
|
98
|
+
- `restrict-template-expressions`: Template literals only accept `string | number | boolean`
|
|
99
|
+
- `no-unnecessary-condition`: Don't check conditions that are always truthy/falsy per types
|
|
100
|
+
- `unbound-method`: Don't detach methods from objects; bind or use arrow functions
|
|
101
|
+
- `only-throw-error`: Only throw `Error` instances, never strings or plain objects
|
|
102
|
+
- `use-unknown-in-catch-callback-variable`: `.catch(err => ...)` — `err` must be `unknown`
|
|
103
|
+
|
|
104
|
+
**Imports & style:**
|
|
105
|
+
- `consistent-type-imports`: Use `import type { X }` for type-only imports
|
|
106
|
+
- `import-x/order`: Imports grouped (builtin → external → internal → parent → sibling → index), alphabetized, blank lines between groups
|
|
107
|
+
- `no-inferrable-types`: Don't annotate types TS can infer (`const count: number = 0` → `const count = 0`)
|
|
108
|
+
- `prefer-optional-chain`: Use `?.` instead of `&&` chains
|
|
109
|
+
- `prefer-nullish-coalescing`: Use `??` instead of `||` for nullable defaults
|
|
110
|
+
- `consistent-type-definitions`: Prefer `interface` over `type` for object shapes
|
|
111
|
+
- `array-type`: Use `T[]` not `Array<T>`
|
|
112
|
+
|
|
113
|
+
**React-specific:**
|
|
114
|
+
- `react-hooks/rules-of-hooks`: Hooks only at top level of components/custom hooks
|
|
115
|
+
- `react-hooks/exhaustive-deps`: All reactive values must be in hook dependency arrays
|
|
116
|
+
|
|
117
|
+
**Console:**
|
|
118
|
+
- `no-console`: warn — but `--max-warnings 0` makes it an error. Only allowed in `**/error.tsx`.
|
|
119
|
+
|
|
120
|
+
**Test files (`.test.ts`, `.test.tsx`):**
|
|
121
|
+
- `vitest/expect-expect`: Every test must have an assertion
|
|
122
|
+
- `vitest/no-identical-title`: Test titles must be unique
|
|
123
|
+
- `vitest/no-conditional-expect`: No `expect()` inside conditionals
|
|
124
|
+
|
|
125
|
+
### File-specific exceptions
|
|
126
|
+
- `**/error.tsx`: `no-console` disabled (Next.js error boundaries)
|
|
127
|
+
- `src/shared/lib/supabase/server.ts`, `middleware.ts`: `no-deprecated` disabled (Supabase SSR)
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-feature
|
|
3
|
+
description: Plan and implement a new feature following TDD — tech-lead planning, backend + frontend in parallel, review gate, and memory sync. Run in a fresh conversation after /discover-feature. Triggers: 'build feature', 'implement feature', 'start building', 'build from requirements'. NOT for: bug fixes, refactors, or API-only routes (use /create-api-route).
|
|
4
|
+
compatibility: opencode
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Build Feature Skill
|
|
8
|
+
|
|
9
|
+
> **Invoke as:** `/build-feature @.requirements/<feature-name>-<timestamp>.md`
|
|
10
|
+
> Run in a **fresh conversation** (not the same one where you ran `/discover-feature`).
|
|
11
|
+
|
|
12
|
+
## IMPORTANT: Fresh Conversation Required
|
|
13
|
+
|
|
14
|
+
If this conversation already contains requirements gathering, **start a new conversation** first. Reusing the same context risks hitting the token limit mid-implementation.
|
|
15
|
+
|
|
16
|
+
If context usage exceeds 60% at any point, stop and tell the user to continue in a new conversation referencing the current step.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Process
|
|
21
|
+
|
|
22
|
+
### Step 1 — Read the Requirements
|
|
23
|
+
|
|
24
|
+
Read `.requirements/<feature-name>-<timestamp>.md`. Confirm the spec exists and has:
|
|
25
|
+
- Acceptance criteria
|
|
26
|
+
- Functional task list
|
|
27
|
+
- Technical task list (with parallel groups)
|
|
28
|
+
|
|
29
|
+
If no spec exists, tell the user to run `/discover-feature <description>` first.
|
|
30
|
+
|
|
31
|
+
### Step 2 — Tech Lead: Load Architecture Context via MCP Memory
|
|
32
|
+
|
|
33
|
+
Load project context with targeted queries (token-efficient):
|
|
34
|
+
|
|
35
|
+
1. Read `package.json` to get the project name (`<project-name>`)
|
|
36
|
+
2. `search_memory` with `tags: ["project:<project-name>", "domain:ui"]` — installed shadcn/ui components
|
|
37
|
+
3. `search_memory` with `tags: ["project:<project-name>", "domain:database"]` — existing schema
|
|
38
|
+
4. `search_memory` with `tags: ["project:<project-name>", "domain:features"]` — existing features and paths
|
|
39
|
+
5. `search_memory` with `tags: ["project:<project-name>", "domain:patterns"]` — canonical pattern references
|
|
40
|
+
6. `search_memory` with `tags: ["project:<project-name>", "domain:rules"]` — active lint/TS rules
|
|
41
|
+
|
|
42
|
+
**Fallback**: if memory service is unavailable, read `.opencode/memory/architecture-snapshot.md` directly.
|
|
43
|
+
|
|
44
|
+
After reading any codebase files, save findings to MCP memory:
|
|
45
|
+
```
|
|
46
|
+
store_memory({
|
|
47
|
+
content: "<what was learned>",
|
|
48
|
+
metadata: {
|
|
49
|
+
type: "architecture",
|
|
50
|
+
tags: ["project:<project-name>", "domain:<domain>", "category:<category>"]
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Also read `eslint.config.ts` and `tsconfig.json`** to confirm active rules and compiler flags before writing any code.
|
|
56
|
+
|
|
57
|
+
**Dependency pre-flight:**
|
|
58
|
+
```bash
|
|
59
|
+
pnpm ls drizzle-orm # Confirm installed version
|
|
60
|
+
pnpm typecheck # Confirm baseline passes — fix pre-existing errors first
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Step 3 — Tech Lead: Planning (Get User Approval)
|
|
64
|
+
|
|
65
|
+
Before any code is written, produce a technical plan and get user approval.
|
|
66
|
+
|
|
67
|
+
Using the requirements + MCP memory context:
|
|
68
|
+
|
|
69
|
+
1. **Map technical tasks to agents** (from the requirements file's Technical Task List):
|
|
70
|
+
- Identify which tasks can run in parallel (Group A + Group B from the plan)
|
|
71
|
+
- Identify which tasks are sequential (Group C gates)
|
|
72
|
+
|
|
73
|
+
2. **Plan the test structure upfront**:
|
|
74
|
+
- List which test files will be created
|
|
75
|
+
- One `describe` block per acceptance criterion
|
|
76
|
+
- Which mocks are needed (`makeSupabaseMock`, HTTP mocks, etc.)
|
|
77
|
+
- Which edge cases map to which criteria
|
|
78
|
+
|
|
79
|
+
3. **Identify reuse**:
|
|
80
|
+
- Which canonical patterns to copy (from MCP memory results)
|
|
81
|
+
- Which shadcn components are already installed vs need installing
|
|
82
|
+
- Which shared utilities apply (`formFieldText`, `firstZodIssueMessage`, etc.)
|
|
83
|
+
|
|
84
|
+
4. **Present the plan to the user** and wait for approval before proceeding.
|
|
85
|
+
|
|
86
|
+
> Present as: what backend will do, what frontend will do, which tests will be written, any risks or decisions needing user input.
|
|
87
|
+
|
|
88
|
+
### Step 4 — Create Feature Structure
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
src/features/<feature-name>/
|
|
92
|
+
├── components/
|
|
93
|
+
├── actions/
|
|
94
|
+
├── queries/
|
|
95
|
+
├── hooks/
|
|
96
|
+
├── api/
|
|
97
|
+
├── lib/
|
|
98
|
+
└── __tests__/
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Step 5 — Pre-Test Setup
|
|
102
|
+
|
|
103
|
+
Update `vitest.config.ts` to exclude files that cannot be meaningfully tested in jsdom:
|
|
104
|
+
- Drizzle schema files (`src/shared/db/*.schema.ts`)
|
|
105
|
+
- Pure type-only files
|
|
106
|
+
- Portal/browser-API-dependent UI wrappers (e.g., `src/shared/components/ui/sonner.tsx`)
|
|
107
|
+
|
|
108
|
+
### Step 6 — TDD: RED Phase (@test-qa)
|
|
109
|
+
|
|
110
|
+
Delegate to `@test-qa` to write ALL test files first — zero implementation code at this stage:
|
|
111
|
+
- `__tests__/<component>.test.tsx` — component tests
|
|
112
|
+
- `__tests__/use-<feature>.test.ts` — hook tests (if applicable)
|
|
113
|
+
- `__tests__/<action>.action.test.ts` — action tests
|
|
114
|
+
- `__tests__/<feature>.queries.test.ts` — query tests
|
|
115
|
+
|
|
116
|
+
Provide `@test-qa` with the full test plan from Step 3 (files, `describe` names, mocks, edge cases).
|
|
117
|
+
|
|
118
|
+
**BLOCKING GATE — do not proceed until this passes:**
|
|
119
|
+
Run `pnpm test:unit` and paste the output. All new tests must **FAIL** (red). If any new test passes without implementation, the test is wrong — fix it before continuing.
|
|
120
|
+
|
|
121
|
+
### Step 7 — TDD: GREEN Phase (parallel)
|
|
122
|
+
|
|
123
|
+
Launch **@backend and @frontend in parallel** — they work on independent files:
|
|
124
|
+
|
|
125
|
+
| @backend handles | @frontend handles |
|
|
126
|
+
|-----------------|-------------------|
|
|
127
|
+
| `actions/` | `components/` |
|
|
128
|
+
| `queries/` | `page.tsx` |
|
|
129
|
+
| `schema.ts` changes | shadcn component installs |
|
|
130
|
+
| RLS policies | Loading/empty states |
|
|
131
|
+
|
|
132
|
+
Do NOT serialize these — they touch different files.
|
|
133
|
+
|
|
134
|
+
After each agent completes, they must save their findings to MCP memory.
|
|
135
|
+
|
|
136
|
+
**Do NOT run intermediate verification between sub-tasks.** Complete all GREEN phase work, then verify in Step 9.
|
|
137
|
+
|
|
138
|
+
**BLOCKING GATE — do not proceed until this passes:**
|
|
139
|
+
Run `pnpm test:unit` and paste the output. All tests must **PASS** (green).
|
|
140
|
+
|
|
141
|
+
### Step 8 — Refactor
|
|
142
|
+
|
|
143
|
+
Clean up while keeping tests green.
|
|
144
|
+
|
|
145
|
+
### Step 9 — Verify & Self-Check
|
|
146
|
+
|
|
147
|
+
Run all three **together** (single pass) and paste output:
|
|
148
|
+
```bash
|
|
149
|
+
pnpm test:coverage # Must meet thresholds: 95% statements/functions/lines, 90% branches
|
|
150
|
+
pnpm lint # Must pass with 0 warnings
|
|
151
|
+
pnpm typecheck # Must pass with 0 errors
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
If issues are found, fix **all** of them, then run the full trio again once.
|
|
155
|
+
|
|
156
|
+
Before moving to the review gate, verify manually:
|
|
157
|
+
- [ ] No `any` types: `grep -r ": any" src/features/<feature>/`
|
|
158
|
+
- [ ] No `eslint-disable` comments
|
|
159
|
+
- [ ] All UI text in Spanish, all `it()`/`describe()` text in English
|
|
160
|
+
- [ ] No file over 200 lines
|
|
161
|
+
- [ ] No function over 20 lines
|
|
162
|
+
- [ ] AAA pattern (`// Arrange`, `// Act`, `// Assert`) in every test
|
|
163
|
+
- [ ] `ActionResult` returned from every Server Action mutation
|
|
164
|
+
- [ ] Toast feedback (`toast.success` / `toast.error`) for every mutation
|
|
165
|
+
- [ ] RLS policies written for every new table
|
|
166
|
+
|
|
167
|
+
### Step 10 — Review Gate (parallel)
|
|
168
|
+
|
|
169
|
+
Launch **@code-reviewer and @security-researcher in parallel** on the changed files. Fix any findings before marking the feature complete.
|
|
170
|
+
|
|
171
|
+
This step is not optional. The feature is not done until both reviewers pass.
|
|
172
|
+
|
|
173
|
+
> **Note for time-critical work:** if the user explicitly says to skip the review gate, flag the skipped step so it can be done as a follow-up.
|
|
174
|
+
|
|
175
|
+
### Step 11 — Update Architecture Snapshot & MCP Memory
|
|
176
|
+
|
|
177
|
+
Update `.opencode/memory/architecture-snapshot.md`:
|
|
178
|
+
- Add new DB tables to the schema table
|
|
179
|
+
- Add new shadcn components to the installed list
|
|
180
|
+
- Add the new feature to the Existing Features table
|
|
181
|
+
- Add any new canonical pattern references
|
|
182
|
+
|
|
183
|
+
Then run `/memory sync` to persist all changes to MCP memory so future sessions load context efficiently.
|
|
184
|
+
|
|
185
|
+
Mark all functional and technical tasks in `.requirements/<feature-name>-<timestamp>.md` as complete.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Common Issues
|
|
190
|
+
|
|
191
|
+
| Problem | Cause | Fix |
|
|
192
|
+
|---------|-------|-----|
|
|
193
|
+
| MCP memory returns no results | Memory not synced yet | Run `/memory sync` first, then retry |
|
|
194
|
+
| Test passes without implementation (RED fails) | Test asserts on falsy/default values | Ensure the test expects a specific truthy result that only a real implementation can produce |
|
|
195
|
+
| `pnpm typecheck` fails on schema file | Schema imported in test without mock | Add the schema file to `coverage.exclude` in `vitest.config.ts` |
|
|
196
|
+
| Context exceeds 60% mid-build | Feature too large for one conversation | Stop, note the current step, start a new conversation referencing it |
|
|
197
|
+
| `lint-staged` blocks commit | ESLint warnings treated as errors | Fix all warnings; never use `eslint-disable` inline |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Guardrails
|
|
202
|
+
- NEVER start implementation before the user approves the plan (Step 3)
|
|
203
|
+
- NEVER start implementation before the RED gate is confirmed with actual test output
|
|
204
|
+
- Coverage threshold: 95% statements/functions/lines, 90% branches
|
|
205
|
+
- Follow `features/* → shared/*` dependency direction
|
|
206
|
+
- RLS is mandatory for every new table — not a post-step
|
|
207
|
+
- All agents must save codebase findings to MCP memory after reading files
|
|
208
|
+
- Write lint-compliant code from the start — read the Strict Rules Reference before the first line of code
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-api-route
|
|
3
|
+
description: Create a new Next.js API route with Zod validation, auth check, and TDD tests. Use when adding API endpoints to a feature. Triggers: 'create API route', 'add endpoint', 'new route handler', 'API endpoint'. NOT for: Server Actions (those go in features/*/actions/).
|
|
4
|
+
compatibility: opencode
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Create API Route Skill
|
|
8
|
+
|
|
9
|
+
## Process
|
|
10
|
+
|
|
11
|
+
### 1. Define Schema
|
|
12
|
+
```typescript
|
|
13
|
+
const requestSchema = z.object({ /* fields */ });
|
|
14
|
+
const responseSchema = z.object({ /* fields */ });
|
|
15
|
+
type RequestBody = z.infer<typeof requestSchema>;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 2. Write Test First (TDD)
|
|
19
|
+
```typescript
|
|
20
|
+
describe("POST /api/my-route", () => {
|
|
21
|
+
it("returns 400 on invalid input", async () => { ... });
|
|
22
|
+
it("returns 401 when unauthenticated", async () => { ... });
|
|
23
|
+
it("returns 200 with valid input", async () => { ... });
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Run test — must FAIL (RED).
|
|
28
|
+
|
|
29
|
+
### 3. Implement Route
|
|
30
|
+
```typescript
|
|
31
|
+
// Determine runtime:
|
|
32
|
+
// - AI routes: export const runtime = "edge"
|
|
33
|
+
// - DB routes: no export (Node.js default)
|
|
34
|
+
|
|
35
|
+
export async function POST(request: Request) {
|
|
36
|
+
const supabase = await createClient();
|
|
37
|
+
const { data: { user } } = await supabase.auth.getUser();
|
|
38
|
+
if (!user) return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
39
|
+
|
|
40
|
+
const body = await request.json() as unknown;
|
|
41
|
+
const parsed = requestSchema.safeParse(body);
|
|
42
|
+
if (!parsed.success) return Response.json({ error: "Invalid input" }, { status: 400 });
|
|
43
|
+
|
|
44
|
+
// business logic...
|
|
45
|
+
|
|
46
|
+
return Response.json(result);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 4. Verify
|
|
51
|
+
```bash
|
|
52
|
+
pnpm test:unit
|
|
53
|
+
pnpm lint
|
|
54
|
+
pnpm typecheck
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Checklist
|
|
58
|
+
- [ ] Zod schema for request/response
|
|
59
|
+
- [ ] Auth check (unless public endpoint)
|
|
60
|
+
- [ ] Input validation
|
|
61
|
+
- [ ] Correct runtime (`edge` for AI, `nodejs` default for DB)
|
|
62
|
+
- [ ] Tests written BEFORE implementation
|
|
63
|
+
- [ ] ≥95% statement/function/line coverage, ≥90% branch coverage
|