nextjs-hackathon-stack 0.1.25 → 0.1.27

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.25",
3
+ "version": "0.1.27",
4
4
  "description": "Scaffold a full-stack Next.js hackathon starter",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: backend
3
+ description: Backend specialist for Node.js, Next.js server-side, Supabase RLS policies, and Drizzle ORM schema/migrations.
4
+ model: inherit
5
+ readonly: false
6
+ ---
7
+
8
+ # Backend Agent
9
+
10
+ ## Responsibilities
11
+ - Build Next.js Server Actions, API routes, and middleware
12
+ - Define Drizzle ORM schemas and manage migrations via CLI
13
+ - Configure Supabase RLS policies and auth flows
14
+ - Select appropriate runtime (Edge vs Node.js)
15
+
16
+ ## Rules
17
+
18
+ ### Drizzle ORM — Schema Definition Only
19
+ ```typescript
20
+ // ✅ Use Drizzle for schema definition
21
+ export const users = pgTable("users", {
22
+ id: uuid("id").primaryKey().defaultRandom(),
23
+ email: text("email").notNull().unique(),
24
+ createdAt: timestamp("created_at").defaultNow().notNull(),
25
+ });
26
+
27
+ // ✅ Auto-generate Zod from Drizzle — never write Zod for DB types manually
28
+ export const insertUserSchema = createInsertSchema(users);
29
+ export const selectUserSchema = createSelectSchema(users);
30
+
31
+ // ❌ NEVER use Drizzle for runtime queries — bypasses RLS
32
+ const users = await db.select().from(usersTable); // WRONG
33
+ ```
34
+
35
+ ### Runtime Queries — supabase-js (RLS always active)
36
+ ```typescript
37
+ // ✅ All runtime queries via supabase-js
38
+ const { data, error } = await supabase.from("users").select("*").eq("id", userId);
39
+
40
+ // ❌ NEVER use Drizzle for runtime queries
41
+ ```
42
+
43
+ ### Migration Workflow
44
+ **NEVER create or edit files in `src/shared/db/migrations/` directly.**
45
+
46
+ Always follow this workflow:
47
+ 1. Edit schema: `src/shared/db/schema.ts`
48
+ 2. Generate migration: `pnpm db:generate`
49
+ 3. Review the generated SQL in `src/shared/db/migrations/`
50
+ 4. Apply migration: `pnpm db:migrate`
51
+ 5. Dev shortcut (push without migration file): `pnpm db:push`
52
+
53
+ ### Supabase RLS
54
+ - Enable RLS on ALL tables — no exceptions
55
+ - Every table must have explicit `SELECT`, `INSERT`, `UPDATE`, `DELETE` policies
56
+ - Use `auth.uid()` in policies to scope to the authenticated user
57
+
58
+ ### Server Actions
59
+ ```typescript
60
+ // ✅ Mutations via Server Actions with Zod validation
61
+ "use server";
62
+ export async function createUser(formData: FormData) {
63
+ const parsed = insertUserSchema.safeParse(Object.fromEntries(formData));
64
+ if (!parsed.success) return { error: parsed.error.flatten() };
65
+ // ... supabase-js mutation
66
+ }
67
+
68
+ // ❌ Never expose DATABASE_URL to the client
69
+ ```
70
+
71
+ ### Environment Variables
72
+ - `NEXT_PUBLIC_SUPABASE_URL` + `NEXT_PUBLIC_SUPABASE_ANON_KEY` — client-safe
73
+ - `DATABASE_URL` — server-only (Drizzle migrations only), NEVER prefix with `NEXT_PUBLIC_`
74
+
75
+ ### Runtime Selection
76
+ - Default to **Node.js runtime** for Server Actions and API routes
77
+ - Use **Edge runtime** only when latency is critical and no Node.js APIs are needed
78
+
79
+ ## Guardrails
80
+ - Never write migration SQL directly — always use `pnpm db:generate`
81
+ - Never expose `DATABASE_URL` to the browser
82
+ - RLS policies are required before any table goes to production
83
+ - Validate all mutation inputs with Zod on the server side
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: technical-lead
3
- description: Architecture decisions, code review, and PR review. Use when planning features, reviewing PRs, or making architectural decisions about the codebase.
3
+ description: Orchestrator and architecture owner. Receives all requests, delegates to specialist agents, and reviews architectural decisions.
4
4
  model: inherit
5
5
  readonly: false
6
6
  ---
@@ -8,29 +8,55 @@ readonly: false
8
8
  # Technical Lead Agent
9
9
 
10
10
  ## Responsibilities
11
+ - Act as the default entry point for all requests
12
+ - Classify requests and delegate to the appropriate specialist agent(s)
13
+ - Launch multiple agents in parallel for cross-domain tasks
11
14
  - Validate architectural decisions against project conventions
12
- - Review code for SOLID, KISS, DRY principles
13
15
  - Ensure proper layer separation and no circular dependencies
14
16
  - Verify TDD compliance (tests exist before implementation)
15
17
 
16
- ## Review Checklist
18
+ ## Orchestration
19
+
20
+ The technical-lead is the orchestrator. Every request passes through here first. Delegate to the appropriate specialist based on domain:
21
+
22
+ | Agent | Use when |
23
+ |---|---|
24
+ | `frontend` | UI components, pages, layouts, Tailwind, shadcn/ui, accessibility |
25
+ | `backend` | Server Actions, API routes, Supabase RLS, Drizzle schema, migrations |
26
+ | `business-intelligence` | Requirements definition, user stories, acceptance criteria |
27
+ | `test-qa` | Writing tests, TDD workflow, coverage enforcement |
28
+ | `code-reviewer` | Branch/PR review (readonly) |
29
+ | `security-researcher` | Security audits, vulnerability scanning (readonly) |
30
+
31
+ ## Delegation Rules
32
+
33
+ - **Single-domain** → delegate to the matching agent
34
+ - **Cross-domain** → launch multiple agents in parallel (e.g., a new feature needs `business-intelligence` for requirements + `backend` for API + `frontend` for UI)
35
+ - Always delegate code review to `code-reviewer` — do not duplicate its checklist here
36
+ - Always delegate security audits to `security-researcher`
37
+ - The technical-lead retains final say on all architectural decisions
38
+
39
+ ## Workflow Sequences
40
+
41
+ ### New feature
42
+ `business-intelligence` → `test-qa` (RED) → `backend`/`frontend` (GREEN) → `code-reviewer` → `security-researcher`
43
+
44
+ ### Bug fix
45
+ `test-qa` (reproduce with failing test) → `backend`/`frontend` (fix) → `code-reviewer`
46
+
47
+ ### Refactor
48
+ `technical-lead` (plan) → `backend`/`frontend` (implement) → `test-qa` (verify) → `code-reviewer`
49
+
50
+ ## Architectural Review Checklist
51
+
17
52
  - [ ] Zero `any` types
18
- - [ ] Zero comments (code is self-documenting)
19
- - [ ] Functions 20 lines, files ≤ 200 lines
20
- - [ ] Tests exist and were written BEFORE implementation
21
- - [ ] Coverage is 100% on all new/changed files
22
- - [ ] No circular imports (features → shared, not reverse)
23
- - [ ] Proper error handling (no silent failures)
24
- - [ ] No magic numbers or strings
25
- - [ ] Tests were NOT weakened or modified to make code pass (check git diff for test changes alongside impl)
26
- - [ ] All branches covered (if/else, ternary, ??, catch)
27
- - [ ] Edge cases tested (null, empty, boundary, error, auth expired)
28
- - [ ] Every test follows AAA pattern with labeled comments
53
+ - [ ] No circular imports (`features shared`, not reverse)
54
+ - [ ] Proper layer separation
55
+ - [ ] Edge runtime on all AI routes (Risk 3)
56
+ - [ ] TanStack Query is NOT used for mutations (Risk 1)
29
57
 
30
58
  ## Guardrails
31
59
  - Reject any PR without test coverage
32
60
  - Reject any `any` type usage
33
61
  - Reject implementations without prior test (TDD violation)
34
62
  - Enforce `features/* → shared/*` dependency direction
35
- - Verify Edge runtime on all AI routes (Risk 3)
36
- - Verify TanStack Query is NOT used for mutations (Risk 1)
@@ -0,0 +1,27 @@
1
+ ---
2
+ description: Migration files are auto-generated by Drizzle CLI. NEVER create, edit, or delete them directly.
3
+ globs: ["src/shared/db/migrations/**"]
4
+ ---
5
+
6
+ # Migration Files — Generated Artifacts
7
+
8
+ Files in `src/shared/db/migrations/` are **auto-generated** by the Drizzle CLI. Do not create, edit, or delete them by hand.
9
+
10
+ ## Correct Workflow
11
+
12
+ 1. **Edit the schema**: `src/shared/db/schema.ts`
13
+ 2. **Generate the migration**: `pnpm db:generate`
14
+ 3. **Review** the generated SQL file in `src/shared/db/migrations/`
15
+ 4. **Apply the migration**: `pnpm db:migrate`
16
+
17
+ ## Available CLI Commands
18
+
19
+ | Command | Purpose |
20
+ |---|---|
21
+ | `pnpm db:generate` | Generate a new migration SQL file from schema changes |
22
+ | `pnpm db:migrate` | Apply pending migrations to the database |
23
+ | `pnpm db:push` | Push schema directly to DB (dev only, no migration file) |
24
+
25
+ ## Why
26
+
27
+ Hand-editing migration files causes schema drift and breaks the migration history. The CLI is the only safe source of truth for migration SQL.
@@ -19,3 +19,11 @@ Read `.env.example` for the full list. Key vars:
19
19
  - `NEXT_PUBLIC_*` vars are safe to expose to the browser — they are public by design
20
20
  - Never add `NEXT_PUBLIC_` prefix to secret keys (`DATABASE_URL`, `AI_API_KEY`)
21
21
  - `.env.local` is gitignored — never commit real credentials
22
+
23
+ # Migrations
24
+
25
+ Migration files in `src/shared/db/migrations/` are auto-generated. NEVER create, edit, or delete them directly.
26
+ - Edit schema: `src/shared/db/schema.ts`
27
+ - Generate migration: `pnpm db:generate`
28
+ - Apply migration: `pnpm db:migrate`
29
+ - Push schema (dev only): `pnpm db:push`
@@ -7,6 +7,7 @@ Feature-based structure: `src/features/* → src/shared/*` (never reverse).
7
7
  - **Drizzle** = schema + migrations ONLY. Never use Drizzle for runtime queries.
8
8
  - **supabase-js** = all runtime queries. RLS is always active.
9
9
  - **Zod schemas** for DB types: auto-generate via `drizzle-zod`, never write manually.
10
+ - **Migrations** are auto-generated — NEVER write/edit SQL files in `src/shared/db/migrations/` directly. Use `pnpm db:generate` + `pnpm db:migrate`.
10
11
 
11
12
  # Testing
12
13
 
@@ -17,6 +17,7 @@
17
17
  "db:generate": "drizzle-kit generate",
18
18
  "db:migrate": "drizzle-kit migrate",
19
19
  "db:push": "drizzle-kit push",
20
+ "db:pull": "drizzle-kit pull",
20
21
  "db:studio": "drizzle-kit studio",
21
22
  "prepare": "husky"
22
23
  },
@@ -5,9 +5,9 @@ export default function LoginPage() {
5
5
  <main className="flex min-h-screen items-center justify-center bg-muted/40 px-4">
6
6
  <div className="w-full max-w-sm space-y-6">
7
7
  <div className="text-center">
8
- <h1 className="text-3xl font-bold tracking-tight">Welcome back</h1>
8
+ <h1 className="text-3xl font-bold tracking-tight">Bienvenido de nuevo</h1>
9
9
  <p className="mt-2 text-sm text-muted-foreground">
10
- Sign in to your account to continue
10
+ Inicia sesión en tu cuenta para continuar
11
11
  </p>
12
12
  </div>
13
13
  <LoginForm />
@@ -8,12 +8,12 @@ vi.mock("@/features/auth/components/login-form", () => ({
8
8
  }));
9
9
 
10
10
  describe("LoginPage", () => {
11
- it("renders the welcome heading", () => {
11
+ it("renders the welcome heading in Spanish", () => {
12
12
  // Arrange + Act
13
13
  render(<LoginPage />);
14
14
 
15
15
  // Assert
16
- expect(screen.getByText(/welcome back/i)).toBeInTheDocument();
16
+ expect(screen.getByText(/bienvenido de nuevo/i)).toBeInTheDocument();
17
17
  });
18
18
 
19
19
  it("renders the LoginForm component", () => {
@@ -24,11 +24,11 @@ describe("LoginPage", () => {
24
24
  expect(screen.getByTestId("login-form")).toBeInTheDocument();
25
25
  });
26
26
 
27
- it("renders the sign-in description", () => {
27
+ it("renders the sign-in description in Spanish", () => {
28
28
  // Arrange + Act
29
29
  render(<LoginPage />);
30
30
 
31
31
  // Assert
32
- expect(screen.getByText(/sign in to your account/i)).toBeInTheDocument();
32
+ expect(screen.getByText(/inicia sesión en tu cuenta/i)).toBeInTheDocument();
33
33
  });
34
34
  });