TCG Vault - Trading Card Game Collection Management with OCR Scanning
Find a file
Randall Stillwell 3ac527ef48 architect: ratify decisions + brief for adopt-playwright-smoke
Convoy file:
- status: queued -> in-progress
- New § Decisions (post-IA round): 6 decisions investigated.
  Architect-self-ratifiable: D2 (CI fail-loud predicate mirrors
  rate-limit.js convention), D3 (two projects is a structural
  workflow requirement), D5 (no eslint change — verified `npx
  eslint tests/smoke/app.smoke.spec.ts` exits 0). Operator-
  ratifiable at gate 1: D1 (recommend keep .ts; convention call),
  D4 (recommend defer baseline commit to Linux-Docker follow-up;
  process call), D6 (recommend simple test:smoke/test:visual
  scripts, no auto-boot wrapper; DX call).
- New § Architecture: file plan (5 files), API surface (n/a),
  schema diff (n/a), test plan (3 smoke + 1 visual; vitest 21/21
  + lint baseline 128 held), risk list R1-R9 (request fixture
  header propagation, snapshotPathTemplate alignment, cross-
  platform mismatch, --update-snapshots=none semantics, CI
  predicate variants, bypass trace leak, npm ci lockfile sync,
  eslint future drift, Playwright 1.60.0 freshness).
- New § Decomposition: 1 brief, ~120 LOC, slice_dependencies
  YAML block. Justified single brief because total LOC is
  small and all files are semantically coupled (visual spec
  depends on visual project in config which depends on the
  installed dep).

Brief file (.convoys/adopt-playwright-smoke/brief-1-*.md):
- Goal/Files/Conventions/Acceptance/Manual-verification/
  Boot-the-brief findings/Out-of-scope sections matching the
  fix-vercel-deployment-protection-in-ci/brief-1 shape.
- 8 Boot-the-brief findings: dep resolution clean, .ts lints
  clean, baselines dir MUST NOT be gitignored, extraHTTPHeaders
  propagates to request fixture per docs, /api/health is
  anonymous, ESM shape required, snapshotPathTemplate token set
  has no {platform}, --update-snapshots=none never auto-creates.
- Verbatim playwright.config.js shape with CI fail-loud / dev
  warn predicate, snapshotPathTemplate aligned with workflow's
  artifact upload path, two projects with testMatch partitioning.

No code changes (read-only architect pass). No push.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 17:56:20 -05:00
.convoys architect: ratify decisions + brief for adopt-playwright-smoke 2026-05-24 17:56:20 -05:00
.cursor docs: post-convoy cleanup for drop-public-setup 2026-05-23 17:06:35 -05:00
.github fix(ci): plumb VERCEL_AUTOMATION_BYPASS_SECRET into preview-smoke + visual-diff (#17) 2026-05-24 16:26:22 -05:00
components fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
docs bootstrap: agent pipeline v0.5.0 + ship-readiness review 2026-05-23 02:31:26 -05:00
lib fix(auth): tighten public auth surface — CORS + rate limit (Brief 4 of fix-auth-bypass) 2026-05-23 10:57:49 -05:00
pages fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
public Major redesign: Enhanced card display with particle effects, improved filters, and search functionality 2025-07-23 21:26:54 -05:00
scripts fix(seed): convert scripts/setup-neon-db.js from CJS to ESM (Node 22.x compat) 2026-05-23 17:02:44 -05:00
styles 🚀 Implement Mobile-First Navigation System 2025-08-01 18:18:21 -05:00
test fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
tests/smoke bootstrap: agent pipeline v0.5.0 + ship-readiness review 2026-05-23 02:31:26 -05:00
.agent-context-manifest.yml bootstrap: agent pipeline v0.5.0 + ship-readiness review 2026-05-23 02:31:26 -05:00
.gitignore bootstrap: agent pipeline v0.5.0 + ship-readiness review 2026-05-23 02:31:26 -05:00
.npmrc Fix build compatibility issues 2025-07-22 10:32:15 -05:00
AGENTS.md docs: post-convoy cleanup for fix-vercel-deployment-protection-in-ci 2026-05-24 16:32:45 -05:00
eslint.config.mjs bump: next 15.4.3 -> 16.2.6, ESLint flat config (v9 fallback), typescript devDep 2026-05-23 02:31:26 -05:00
next.config.js bump: next 15.4.3 -> 16.2.6, ESLint flat config (v9 fallback), typescript devDep 2026-05-23 02:31:26 -05:00
package-lock.json fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
package.json fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00
postcss.config.js Major redesign: Enhanced card display with particle effects, improved filters, and search functionality 2025-07-23 21:26:54 -05:00
README.md feat(seed): require ADMIN_INITIAL_PASSWORD env var; strip admin123 from README 2026-05-23 17:02:44 -05:00
tailwind.config.js Ultra-Smooth Hover System with Expanding Actions 2025-07-26 09:00:26 -05:00
TESTING_GUIDE.md 🎨 Restructured Layout System 2025-07-25 11:28:04 -05:00
vercel.json Simplify Vercel config to resolve API routing issues 2025-07-23 09:22:14 -05:00
vitest.config.js fix(layout+pages): default user=null + page audit sweep (P0 #7) (#15) 2026-05-24 14:31:37 -05:00

TCG Vault

A modern trading card game collection manager built with Next.js and Neon Database.

🚀 Features

  • Card Management: Track your MTG, Pokémon, and Lorcana cards
  • Collection Organization: Create and manage card collections
  • Deck Building: Build and share decks
  • Authentication: Secure user accounts with JWT
  • Admin Panel: Manage cards and users
  • Real-time Pricing: Track card values

🛠️ Tech Stack

  • Frontend: Next.js 16 (Pages router), React 18, JavaScript (TypeScript is a devDep only — see AGENTS.md Gotcha #9)
  • Backend: Next.js API Routes
  • Database: Neon PostgreSQL (serverless)
  • Authentication: JWT with bcrypt (24-hour expiry; lib/auth-secret.js is the single source of truth for JWT_SECRET)
  • Rate limiting: @upstash/ratelimit on /api/auth/login + /api/auth/register (5 attempts / 15 min per IP)
  • Testing: Vitest (unit); Playwright queued
  • Styling: Tailwind CSS
  • Deployment: Vercel

📦 Installation

  1. Clone the repository

    git clone <repository-url>
    cd tcg-vault
    
  2. Install dependencies

    npm install
    
  3. Set up environment variables

    cp .env.example .env.local
    

    Update .env.local with your Neon database URL and a real JWT secret:

    POSTGRES_URL="postgresql://your-username:your-password@your-host/your-database"
    JWT_SECRET="<generate with: openssl rand -hex 32>"
    # Required for `npm run setup-db` — used once to hash the initial admin password.
    # Set in .env.local for local dev, or as a CI secret if you run setup from CI.
    ADMIN_INITIAL_PASSWORD="<generate with: openssl rand -base64 24>"
    # Optional — exercise the rate limiter locally. Without them, `lib/rate-limit.js`
    # warn-and-no-ops in dev. In production these are auto-provisioned by the
    # Vercel Upstash Marketplace integration.
    KV_REST_API_URL="https://<your-upstash-host>.upstash.io"
    KV_REST_API_TOKEN="<your-upstash-rest-token>"
    

    JWT_SECRET is requiredlib/auth-secret.js throws at import time if it's unset. ADMIN_INITIAL_PASSWORD is required for npm run setup-db — the script exits with code 1 if it's unset.

  4. Set up the database

    npm run setup-db
    
  5. Start development server

    npm run dev
    

🗄️ Database Schema

The application uses the following tables:

  • users - User accounts and authentication
  • cards - Card information and metadata
  • user_cards - User's card collections
  • collections - Named card collections
  • collection_cards - Cards in collections
  • decks - Deck definitions
  • deck_cards - Cards in decks

🔧 API Endpoints

Authentication

  • POST /api/auth/register - User registration
  • POST /api/auth/login - User login

Admin

  • GET /api/admin - Admin panel data

Health Check

  • GET /api/health - Application health

Note: Earlier revisions of this README also listed GET /api/test-db (and three other unauthenticated dev endpoints: /api/simple, /api/test-auth, /api/setup-database). All four were deleted in fix-auth-bypass Brief 3 (commit fc0dd73) and CI now blocks their reintroduction. Don't recreate them.

🚀 Deployment

This app is configured for deployment on Vercel:

  1. Connect your repository to Vercel
  2. Set environment variables in Vercel dashboard
  3. Deploy automatically on push to main branch

📁 Project Structure

tcg-vault/
├── pages/                 # Next.js pages and API routes
│   ├── api/              # API endpoints
│   │   ├── auth/         # Authentication routes
│   │   └── admin/        # Admin routes
│   ├── _app.js           # App wrapper
│   └── index.js          # Home page
├── lib/                  # Utility libraries
│   └── database.js       # Database adapter
├── scripts/              # Database setup scripts
├── public/               # Static assets
└── .env.local           # Environment variables

🔐 First-time admin setup

npm run setup-db creates a single admin user the first time it runs. The password is read from the ADMIN_INITIAL_PASSWORD environment variable; the script exits with code 1 (and does not open a database connection) if the variable is unset or empty.

  • Local dev: set ADMIN_INITIAL_PASSWORD in .env.local before running npm run setup-db. Use openssl rand -base64 24 (or any other strong source) to generate the value.
  • CI / Vercel: set ADMIN_INITIAL_PASSWORD as a project secret if setup ever runs from CI. The env var is only read by the seed script; runtime auth uses the per-user password stored in the database.
  • Admin email: the seed creates admin@tcgvault.com. Change the password immediately after first login via the app's profile settings.

Operators of envs that pre-date this change: npm run setup-db is idempotent (ON CONFLICT (email) DO NOTHING) — re-running it with ADMIN_INITIAL_PASSWORD set will not rotate an existing admin row's password. If your environment was set up before this change and still has the prior weak default, rotate the password manually via the app after logging in, or wait for the queued rotate-default-admin follow-up convoy.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

📄 License

MIT License - see LICENSE file for details