Installs the three-layer agent-pipeline scaffold (https://github.com/varutasu/agent-pipeline @ v0.5.0): L1 — Context (curated brain) - AGENTS.md: orientation, conventions, 8 explicit gotchas - .cursor/rules/: no-go-zones, api-routes, auth-and-permissions, db-and-schema, ui-and-theming, schema-map - .cursor/skills/: add-api-route, add-page recipes - docs/agent-context/README.md: layer explainer - docs/SCHEMA_MAP.md: hand-curated Neon Postgres reference (replaces Prisma schema map since stack is raw SQL) L2 — Subagent roles (copied verbatim from upstream templates) - 9 .cursor/agents/role-*.md files: Conductor, IA-Architect, UX-Reviewer, Architect, Implementer, Reviewer, Design-System-Auditor, A11y-Auditor, Doc-Writer L3 — Pipeline scaffolding (Vercel variant) - CI: lint + schema-map-drift only (no duplicate build — Vercel handles it). Test job commented out until vitest lands. - preview-smoke + visual-diff via wait-for-vercel-preview - pr-health-rollup sticky comment aggregator - agent-context-drift weekly cron - PULL_REQUEST_TEMPLATE, CODEOWNERS (auth/admin paths tagged) - .convoys/ folder + seed ship-readiness.md review - lib/flags/index.js (JS — converted from TS template) - scripts/wt.sh (Cursor 3.2 deprecation stub), scripts/log-convoy-event.sh - tests/smoke/app.smoke.spec.ts (Playwright skeleton) Manifest - .agent-context-manifest.yml: tracks 31 artifacts by sha256 for future sync-agent-context drift detection Review - .convoys/ship-readiness.md: 16 findings (7 P0 ship-blockers, 5 P1 quality-bar, 4 P2 refactor, P3 UX/IA/a11y/docs) with proposed 13-convoy launch sequence. No production code changed in this commit. All findings in the ship-readiness review will be addressed in follow-up convoys starting with fix-auth-bypass. Structural brain: user-code-review-graph MCP has indexed the codebase (122 files, 628 nodes, 5602 edges, 11 communities, 84 flows). Per-developer; not committed. Co-authored-by: Cursor <cursoragent@cursor.com>
6.4 KiB
AGENTS.md — AI collaboration (tcg-vault)
Guidance for agents and humans working in this repo. Prefer existing patterns over new abstractions.
Branding note: the repo, README, and seed data say "TCG Vault" and
admin@tcgvault.com, but the Layout component renders "Deck Hearth". Pick one before launch — see.convoys/for tracking.
1. Project overview
A web app for managing trading-card-game collections (Magic, Pokémon, Lorcana). Users authenticate, build collections + decks, scan physical cards via a camera+AI-OCR flow, and share publicly. Admin users curate the card database.
- Framework: Next.js 15 (Pages router) + React 18, JavaScript (not TypeScript)
- Data: Neon Postgres, accessed two different ways —
@neondatabase/serverless(lib/database.js) AND raw@vercel/postgres(pages/api/**). Pick ONE; see Gotcha #1. - Auth: Custom JWT (jsonwebtoken + bcryptjs), token stored in
localStorage, sent asAuthorization: Bearer …. No NextAuth. - UI: Tailwind CSS + custom CSS variables for theming (light/dark via
lib/theme-context.js) - Hosting: Vercel (
vercel.json,.vercel/present)
2. Architecture quick reference
| Area | Path | Notes |
|---|---|---|
| Pages router views | pages/*.js |
Public + auth views; uses components/Layout.js |
| API routes | pages/api/**/*.js |
Express-style handler(req, res). 30+ handlers depend on lib/permission-middleware.js::getUserFromRequest |
| Shared UI | components/*.js |
Layout, CardItem, CameraScanner, modal family |
| Auth + DB libs | lib/*.js |
auth-context, admin-auth, use-auth (three parallel auth surfaces), database, permission-middleware |
| Migration scripts | scripts/*.js |
27+ one-off "add column" / "seed" scripts. No formal migration tool |
| Card-import jobs | pages/api/cards/import-*.js, scripts/import-*.js |
Scryfall / Lorcana / Pokémon TCG APIs |
| Database schema | scripts/setup-neon-db.js |
Bootstrap SQL DDL — the source of truth until a real migration tool lands |
| Schema map | docs/SCHEMA_MAP.md |
Hand-curated; regenerate after schema changes |
Code graph is indexed by user-code-review-graph MCP (122 files, 628 nodes, 5602 edges). Ask: "what calls getUserFromRequest?" before refactoring auth.
3. Key conventions
- Auth (server):
import { getUserFromRequest } from '../../lib/permission-middleware'→ returns{ userId, email, role }ornull. IMPORTANT: the current implementation returns a hardcoded admin user when no Bearer token is present — treat that as a known prod bug, do NOT copy the pattern. - Auth (client):
import { useAuth } from '../lib/use-auth'. Avoidlib/auth-context.jsandlib/admin-auth.jsfor new code — they are legacy parallel implementations. - Auth helper (JWT only):
import { ... } from '../../lib/api/auth-utils'(generateToken,verifyToken,hashPassword,verifyPassword). - Permission gate for collection routes: wrap handlers with
withCollectionPermission('viewer' | 'editor' | 'owner')fromlib/permission-middleware.js. - DB access: Use tagged-template style —
import { sql } from '@vercel/postgres'. Avoid the legacylib/database.jsdb.query(string, params)API; its parameter interpolation usessql.unsafeand is a SQL-injection vector. - Activity logging:
logCollectionActivity(collectionId, userId, action, details)— call it from any handler that mutates a collection. - File names:
kebab-case.jsfor libs/scripts;PascalCase.jsfor React components. - Imports: No path aliases configured; use relative imports.
- Slugs:
lib/slug-utils.js::generateUniqueSlugfor any user-facing identifier (collections, decks). - CSS theme tokens: Components read
var(--bg-primary),var(--text-primary),var(--accent-ember), etc. — defined instyles/. Don't hardcode hex colors.
4. Common gotchas
- #1 — Two SQL clients live in parallel.
@neondatabase/serverless(used bylib/database.js) and@vercel/postgres(used by mostpages/api/**handlers). New code: prefer@vercel/postgrestagged templates. Migration to a single client is tracked in.convoys/. - #2 —
getUserFromRequesthas a dev fallback shipped to prod. When no Bearer token is present it returns user 1 as admin. This is a critical security issue, NOT a feature. Don't rely on it; treat unauthenticated requests as 401. - #3 — JWT_SECRET default is hardcoded across 7 files. If
process.env.JWT_SECRETis unset, tokens are signed with'your-secret-key-change-in-production'. The Vercel project MUST setJWT_SECRET; CI/staging too. - #4 — Default admin credentials are in the seed.
admin@tcgvault.com/admin123fromscripts/setup-neon-db.js. Change the password immediately after running setup. - #5 —
pages/api/setup-database.jsis a public endpoint. Anyone hitting it triggers DB DDL. Either delete or gate behind admin auth before public launch. - #6 — Migrations are bare scripts.
scripts/add-*.jsandscripts/fix-*.jsare run-once jobs with no idempotency tracking. Adoptnode-pg-migrate,kysely, ordrizzle-kitbefore more schema changes. - #7 — Dual
is_publicsemantics. Collections and decks both haveis_publiccolumns; check which controls discovery vs. anonymous read in the relevant route. - #8 — Layout has hardcoded default user.
Layout({ user = { email: 'me@randallstillwell.com', role: 'user' } }). Anything rendering Layout without passinguserwill impersonate the maintainer. Passuserexplicitly from every page.
5. Running locally
- Runtime: Node 20 (Vercel default).
- Setup:
npm install, copy.env.localtemplate (POSTGRES_URL + JWT_SECRET + RESEND_API_KEY + BLOB_READ_WRITE_TOKEN), thennpm run setup-dbonce. - Dev server:
npm run dev→ http://localhost:3000.
6. Testing
- Runner: None yet. Adding
vitest+@playwright/testis in.convoys/. Until then: manual smoke perTESTING_GUIDE.md.
7. Deployment
- Vercel auto-deploys
mainand creates Preview deployments for every PR.vercel.jsonand.vercel/are committed. CI in.github/workflows/runs lint + types (no duplicate build — Vercel handles it).
8. Code graph
A local code-knowledge-graph MCP server (user-code-review-graph) is set up for this repo. Ask "what calls X?" or "show me the flow from /api/auth/login" instead of grepping. See docs/agent-context/README.md.