Closes P1 #11 of .convoys/ship-readiness.md (launch sequence step 7) —
"No migration tool — scripts/add-*.js graveyard". Schema changes
post-this-convoy ship as node-pg-migrate migrations under migrations/
at the repo root; the legacy 27 scripts/add-*.js / scripts/fix-*.js /
scripts/seed-*.js jobs remain append-only history per the no-go-zones
rule.
Decisions (full record in .convoys/migration-tool.md § Decisions):
D1 — Tool: node-pg-migrate@^8. Rejected drizzle-kit / prisma migrate /
kysely because each forces broader TypeScript surface than AGENTS.md
Gotcha #9 allows (TS is a devDep only). node-pg-migrate is
JavaScript-native, raw-SQL-friendly via pgm.sql(), and ESM-clean for
the post-bump-next-js "type": "module" repo. Brings pg@^8.21.0 as a
peer dep (dev-only; never loaded in the Next.js bundle).
D2 — Migrations directory: migrations/ at the repo root. Separates
the tool-wrapped artifacts from the historical scripts/migrations/
placeholder folder (which housed the lone pre-tool
2026-05-24-rename-admin-email.js migration and remains preserved for
the audit trail). Matches node-pg-migrate's default flag.
D3 — Tracking table: default pgmigrations (no name collision with
the existing 7-table bootstrap; zero CLI noise).
D4 — Backfill strategy: hand-translate scripts/setup-neon-db.js's
DDL into the initial migration verbatim. Each await sql`...` block
becomes one pgm.sql(`...`) call. Each CREATE uses IF NOT EXISTS, so
the migration is idempotent against fresh AND pre-existing envs —
re-running setup-db on an env that already has the schema is a no-op
DDL-wise (only records the pgmigrations row). Documented assumption:
prod has drifted via the 27 historical add-*.js scripts; reconciling
those into the migration history is the queued
reconcile-historical-add-scripts follow-up convoy.
D5 — Bootstrap reconciliation: split. setup-neon-db.js now (1)
validates ADMIN_INITIAL_PASSWORD + POSTGRES_URL, (2) spawns
`npm run migrate up` via child_process with stdio inherited, (3)
seeds the admin row with ON CONFLICT (email) DO NOTHING. The seven
DDL blocks are deleted from setup-neon-db.js; success/error message
copy is updated to mention the migration step explicitly.
D6 — CI integration: defer. Wiring a CI job that runs migrate up
against a test DB needs either a dedicated Neon branch + secret OR a
Postgres service container; both are real work. Surface as
wire-migrate-into-ci follow-up. Risk acknowledged in
.convoys/migration-tool.md § R3.
D7 — Down-migration on the initial backfill: hard stub. Rolling back
the initial schema would drop every user / card / collection / deck
row in the DB. The stub throws with a long-form error pointing at
the recommended alternative (branch the Neon database + forward-apply).
Future migrations that touch one of the seven bootstrap tables write
their own dated migration with a real down().
Verification (pre-PR):
- npm run lint → 128 problems (baseline preserved, zero regression;
migration file is lint-clean, no new ignore patterns)
- npm run test:run → 21/21 pass
- node --check on migrations/1779853647564_initial-schema.js + on
scripts/setup-neon-db.js → exit 0
- Module load + down() throw verified via dynamic import
- npm run migrate -- --help reaches the node-pg-migrate CLI through
the wrapper
Live verification against a Neon branch is deferred (no throwaway
branch available); the operator's optional post-merge sequence is
documented in .convoys/migration-tool.md § Operator runbook.
See .convoys/migration-tool.md § Follow-ups for the queued
wire-migrate-into-ci / reconcile-historical-add-scripts /
retire-graveyard-scripts-after-audit / audit-node-pg-migrate-transitive-deps
/ add-migration-template follow-up convoys.
Co-authored-by: Cursor <cursoragent@cursor.com>
`scripts/create-test-users.js` hardcoded `bcrypt.hash('alice123', 12)`
+ `bcrypt.hash('bob123', 12)` and echoed those literals back to stdout
both per-user and in a final summary block. `TESTING_GUIDE.md`'s Test
Accounts table documented the same `admin123` / `alice123` / `bob123`
trio. These were the last two weak-credential surfaces left in the
helper-script + manual-QA-doc tree after `drop-public-setup` (commits
`ff80753` + `b63b509`) and `fix-reset-db-script` (squash `3ab9bf8`,
PR #25) closed the `setup-neon-db.js` and `reset-db.js` halves of the
umbrella `purge-weak-creds-from-helpers` queued follow-up.
The fix mirrors the post-`drop-public-setup` `setup-neon-db.js`
pattern and the post-PR-#25 `reset-db.js` pattern verbatim, with one
deliberate simplification: a single `TEST_USERS_PASSWORD` env var
covers both alice + bob rather than per-user env vars (risk R2 in the
convoy file argues this — these are fixture users for the
collaboration demo flow, not independent identities, and per-user
sprawl would double the env-var contract for zero security benefit).
`createTestUsers()` now reads `process.env.TEST_USERS_PASSWORD` at the
top of the function body and exits with code 1 BEFORE opening any DB
connection if the var is unset or whitespace-only, with the same
helpful-error wording template the other two scripts use (names the
var, points at `.env.local`, suggests `openssl rand -base64 24`,
references README's "First-time admin setup" section). All four
password-echo `console.log` lines are deleted; the new summary
documents *where* the password comes from without ever printing it.
`TESTING_GUIDE.md`'s Test Accounts table is rewritten to show password
source per user instead of the literal value; the two inline
`Password: alice123` / `Password: bob123` workflow snippets are
replaced with placeholder text. Unlike the previous two convoys, no
CJS→ESM conversion was needed — `create-test-users.js` was already
top-level ESM.
Verification (all static — script is destructive and not live-tested):
`node --check scripts/create-test-users.js` exit 0; `npm run lint` 128
problems (baseline preserved, no regression); `npm run test:run` 21/21
pass; grep `scripts/ TESTING_GUIDE.md` for
`admin123|password123|test123|alice123|bob123` → 0 hits;
`TEST_USERS_PASSWORD` referenced 10 times total (5 script + 5 doc).
Operator caveat: anyone running `node scripts/create-test-users.js`
post-merge must add `TEST_USERS_PASSWORD=<value>` to their
`.env.local` first; existing alice + bob rows in already-seeded
environments are NOT rotated by re-running this script
(`ON CONFLICT (email) DO NOTHING` preserves the old hashes). Same
caveat that applies to the `drop-public-setup` admin row.
Co-authored-by: Cursor <cursoragent@cursor.com>
Fold of two queued follow-ups from pick-a-name architect audit
(convert-reset-db-to-esm + purge-weak-creds-from-helpers). Three bugs
in one file; all three fixed atomically by mirroring the proven post-
drop-public-setup setup-neon-db.js shape (commit b63b509).
Bugs fixed:
1. CJS-in-ESM (lines 10, 12, 142): require('dotenv'), require('@neon...'),
inline require('bcryptjs'). package.json has "type": "module" since
bump-next-js, so npm run reset-db threw ReferenceError on Node 22.x.
Same bug pattern that hit setup-neon-db.js pre-drop-public-setup B2.
2. Hardcoded weak admin password (line 143: bcrypt.hash('admin123', 12)).
Same anti-pattern drop-public-setup B1 removed from setup-neon-db.js.
3. Password echoed to stdout (line 156: console.log('Admin Password:
admin123')). Security anti-pattern; setup-neon-db.js post-DPS does
NOT echo passwords.
Fix shape (verbatim mirror of setup-neon-db.js):
- ESM top-level imports (dotenv, neon, bcrypt)
- Fail-loud ADMIN_INITIAL_PASSWORD env-var check at function top with
helpful error message pointing to README "First-time admin setup"
- bcrypt.hash(adminPassword, 12) instead of literal
- ON CONFLICT (email) DO NOTHING on INSERT (defensive against
double-run, matches setup-neon-db.js line 149)
- No password echo in success block; admin email logged for confirmation
- Updated docstring to flag DESTRUCTIVE + reference required env
Convoy file: .convoys/fix-reset-db-script.md (P2 hygiene, parent-owned,
no architect — this is a proven-pattern fold with no new decisions
to ratify).
Verification:
- node --check scripts/reset-db.js: exit 0
- npm run lint: 128 problems (baseline preserved, no regression)
- npm run test:run: 21/21 pass
- Grep: 0 require( | 0 admin123 | 0 'Admin Password' in scripts/reset-db.js
- Grep: 3 ADMIN_INITIAL_PASSWORD references (docstring, const, error msg)
NOT live-tested (script is destructive — drops all tables). Operator
can optionally run npm run reset-db against a non-prod Neon branch
post-merge to verify end-to-end.
Surfaces follow-up: lint-against-cjs-in-esm-scripts (P3 polish — add
ESLint rule to prevent any future require() in scripts/** under
"type": "module"). Surfaced for future convoy queue.
Co-authored-by: Cursor <cursoragent@cursor.com>
Hotfix to scripts/migrations/2026-05-24-rename-admin-email.js (shipped 2026-05-24 in pick-a-name PR #21). Script crashed on first invocation with 'TypeError: Cannot read properties of undefined (reading length)' at line 44. Root cause: architect designed against @vercel/postgres return shape { rows, rowCount } but the script uses @neondatabase/serverless's neon() tagged template which returns the rows array directly. AGENTS.md Gotcha #1 (two SQL clients in parallel) is exactly this kind of cross-contamination. Fix: drop the { rows: x } destructuring in all 3 sites + add a 4-line why comment block above the first site so the next migration author doesn't repeat. Verified hand-run against prod Neon DB: migrated 3 users (admin id=1, alice id=5, bob id=6) from @tcgvault.com to @deckhearth.com; idempotent re-run prints 'Nothing to migrate.' No data risk on the original crash — script exited at line 44 before reaching the UPDATE at line 54. PR #21 operator action item now complete in prod. Surfaces a P3 follow-up: add-neon-return-shape-rule (or fold into single-sql-client). All CI green: lint 128 baseline, vitest 21/21, Playwright smoke 3/3 in 1m2s, forbidden-cors-headers pass, forbidden-endpoints pass. PR #24, commit 98406fa.
Brief 2 of drop-public-setup. Closes Decision D — pure module-system
conversion of scripts/setup-neon-db.js so `npm run setup-db` actually
runs on Node 22.x where package.json has "type": "module" (added by
bump-next-js for ESLint v9 flat-config support).
Before this commit, `npm run setup-db` threw:
ReferenceError: require is not defined in ES module scope
After this commit, brief 1's ADMIN_INITIAL_PASSWORD env-var gate actually
fires as documented.
Changes (all in scripts/setup-neon-db.js):
- require('dotenv').config(...) → import dotenv + dotenv.config(...)
- require('@neondatabase/serverless') → import { neon }
- inline require('bcryptjs') hoisted to top-of-file import bcrypt
- no functional changes; same DDL, same env-var gate, same console.logs
Smoke verification: see PR description.
Co-authored-by: Cursor <cursoragent@cursor.com>
Closes P0 #3 from .convoys/ship-readiness.md.
scripts/setup-neon-db.js:
- Read ADMIN_INITIAL_PASSWORD env var at the top of setupNeonDatabase()
before any DB connection. Fail loudly (process.exit(1)) with an
actionable message if unset or empty.
- Replace bcrypt.hash('admin123', 12) with bcrypt.hash(adminPassword, 12).
- Delete the two console.log lines that echoed admin user + password to
stdout (R3 - stdout leak into CI logs).
- Keep ON CONFLICT (email) DO NOTHING unchanged. Re-running setup-db
on an env with the admin row already present is a no-op for the
password (R4 - silent rotation prevention). Rotation of existing
weak-hash admin rows is out of scope (Decision A - queued for the
rotate-default-admin follow-up convoy).
README.md:
- Add ADMIN_INITIAL_PASSWORD to the install-step env-example block
with a CI-secret note (and add KV_REST_API_URL/KV_REST_API_TOKEN
for completeness; they're optional for local dev).
- Replace the "Default Admin Account" section with "First-time
admin setup", documenting the env var, openssl rand suggestion,
and the operator rotation note for envs that predate this change.
- Zero occurrences of 'admin123' remain in README.md (the operator
rotation note refers to "the prior weak default" instead of naming
the literal string, so grep verification A2 holds).
Decisions A1 (going-forward only), B (operational change allowed),
C1 (no vitest coverage - manual smoke in PR description) per
.convoys/drop-public-setup.md section Decisions.
Smoke output: see PR description.
Co-authored-by: Cursor <cursoragent@cursor.com>
✨ New Signup Features:
- Added username field with validation (3+ chars, alphanumeric + underscore)
- Profile image upload with file validation (5MB max)
- DiceBear Adventurer Neutral API integration for random avatars
- Generate new random avatar button with dice emoji
- Initial random avatar generation on page load
🔧 Backend Updates:
- Updated registration API to handle all new fields
- Username uniqueness validation with specific error messages
- Profile image URL storage in database
- Enhanced user response with all profile data
🗄️ Database Migration:
- Added first_name, last_name, username, profile_image_url columns
- Unique constraint on username field
- Migration script with existing user updates
- Default values for existing accounts
🎯 User Experience:
- Real-time form validation with error states
- Loading states for image upload/generation
- File type and size validation
- Clean profile image preview with rounded borders
- Consistent styling with existing theme
Ready for enhanced user profiles! 🚀
🐛 Database Schema Fixes:
- Removed non-existent 'updated_at' column from collection_cards operations
- Fixed SQL queries in card ownership API and seeding scripts
- Resolved column does not exist errors
🚫 Hide System Collections from Selection:
- Added 'excludeSystem' parameter to /api/collections endpoint
- Updated CollectionSelectionModal to exclude system collections
- 'All My Cards' no longer appears in card addition modals
✨ Enhanced System Collection Styling:
- Upgraded system collection badge with gradient styling
- Added 🔒 SYSTEM badge with blue-purple gradient
- Added informative tooltip: 'Automatically syncs with your owned cards'
- Made system collections visually distinct and educational
🎯 User Experience Improvements:
- System collections are now clearly identified as special
- Users understand they can't manually add cards to system collections
- Better visual hierarchy and information architecture
- Automatic sync behavior is now clearly communicated
Card ownership should now work without errors! 🚀
🐛 Database Fixes:
- Added unique constraint on user_cards (user_id, card_id)
- Added unique constraint on collection_cards (collection_id, card_id)
- Fixed ON CONFLICT clauses in card ownership API
✨ Auto-Sync Feature:
- Card ownership now automatically syncs with 'All My Cards' collection
- When user marks card as owned → added to system collection
- When user removes ownership → removed from system collection
- Real-time bidirectional sync between user_cards and collection_cards
🔄 Migration Script:
- Cleaned up any duplicate entries
- Added necessary database constraints
- Synced existing owned cards (0 users had existing data)
🎯 API Improvements:
- Simplified card ownership API (removed GET method)
- Better error handling and validation
- Clear success messages for user feedback
- Automatic collection management
Card ownership should now work perfectly! 🚀
✨ New Feature - Automatic System Collection:
- Every user gets an undeletable 'All My Cards' collection on registration
- Contains all cards marked as owned by the user
- Cannot be deleted, renamed, or made public
- Special 🔒 System indicator in the UI
🗃️ Database Changes:
- Added is_system_collection column to collections table
- Migration script created 'All My Cards' for all existing users (5 users)
- Automatic creation in registration API for new users
🛡️ API Protections:
- DELETE: System collections cannot be deleted
- PUT: System collections cannot be renamed or made public
- Added isSystemCollection field to API responses
🎨 Frontend Updates:
- System collections show 🔒 System badge
- Edit/Delete buttons hidden for system collections
- Special visual indicator for protected collections
🎯 Implementation Details:
- Unique slug generation (all-my-cards, all-my-cards-2, etc.)
- Proper permissions setup for each collection
- Error handling for edge cases
- Non-blocking registration if collection creation fails
Ready for users to have their automatic 'All My Cards' collection! 🚀
✨ New Features:
- Created seed-collections-with-cards.js for testing thumbnail layouts
- Seeds database with collections in 3 different states:
😢 Empty collections (crying emoji placeholder)
🃏 Collections with cards (white card boxes with images)
🖼️ Collections with custom thumbnails (uploaded images)
🗂️ Sample Data Created:
- 13 sample cards (MTG, Pokemon, Lorcana with real images)
- 6 collections total (3 for Alice, 3 for Bob)
- Mix of public/private collections with realistic content
- Proper slug generation and permissions setup
🎯 Test Coverage:
- Alice: Power 9 Collection (cards), Pokemon Starters (custom thumb), Empty Future (crying emoji)
- Bob: Budget MTG (cards), Lorcana Heroes (custom thumb), Secret Project (1 card)
- All collections have proper tags, descriptions, and ownership
🔧 Technical Implementation:
- Fixed SQL result structure for Neon database (.rows vs direct array)
- Handles existing cards gracefully (check before insert)
- Generates unique slugs for all collections
- Creates proper permissions and collection_cards relationships
Ready to test all thumbnail layout variations! 🎨✨
🎯 Vanity URLs for Collections:
- Added slug-based URLs like /collection/modern-masters-2021
- Backwards compatible with numeric IDs
- SEO-friendly and memorable URLs
🛠️ Slug System:
- Created lib/slug-utils.js with slug generation and validation
- generateSlug() converts names to URL-friendly format
- generateUniqueSlug() handles duplicates with numeric suffixes
- isValidSlug() validates format (lowercase, hyphens, no special chars)
📊 Database Schema:
- Added slug column to collections table with unique constraint
- Migration script adds slugs to existing collections
- Database constraints ensure slug format and uniqueness
- Performance index on slug column
🔌 API Updates:
- Updated collections API to generate slugs for new collections
- New [identifier].js endpoint handles both slugs and IDs
- Thumbnails API supports both slug and ID lookups
- Smart identifier detection (slug vs numeric ID)
🎨 Frontend Integration:
- Collections page uses slugs for navigation
- Fallback to ID if slug not available (backwards compatibility)
- Updated all collection links to use slugs
- Sample collections created with proper slugs
✨ URL Examples:
- /collection/modern-masters-2021 (new slug format)
- /collection/123 (old ID format still works)
- Automatic redirect potential for future
The collection URLs are now beautiful and shareable! 🚀
🎯 Moved collaboration display from bottom section to hero header:
- Created CollaboratorFacepile component with hover tooltips
- Shows creator + active collaborators in compact format
- Color-coded avatars by role (owner=purple, editor=blue, viewer=green)
- Displays up to 4 faces, then '+N more' for additional collaborators
- Rich hover tooltips showing email and role information
- Responsive text: 'Crafted by X & N others'
🔧 Technical improvements:
- Fixed favorites system database migration (separated SQL commands)
- Fixed favorites API SQL syntax errors
- Integrated facepile into collection metadata section
- Removed redundant CollaborationManager from bottom
- Clean component architecture with proper loading states
🎨 UX enhancements:
- Smooth hover animations with scale effects
- Professional tooltips with arrows
- Proper z-index layering for overlapping elements
- Loading skeleton while fetching collaborators
- Accessible color contrast and typography
Perfect for showing collaboration at a glance! 👥✨
Built out all requested features from top to bottom:
✅ Upload Modal for Hero Images:
- Created UploadImageModal component with drag-and-drop
- Support for both URL input and file upload
- Live preview and validation
- Integrated into collection detail page
✅ Smart TCG Tags:
- Dynamic tags showing only games with cards
- Properly positioned under description
- Clean blue rounded styling
✅ Combined Share & Invite Modal:
- Unified ShareModal replacing separate buttons
- Public access toggle with community visibility
- Email/member search functionality
- Default viewer role for invitations
- Social sharing (Twitter, Facebook, Reddit, Discord)
- User search API endpoint (/api/users/search)
✅ Comprehensive Favorites System:
- Database schema for cards, collections, and decks
- API endpoint (/api/favorites) for CRUD operations
- Real-time favorite status checking
- Working toggle functionality in UI
- Migration script for database setup
✅ CSV Download Functionality:
- Complete card metadata export
- Proper CSV formatting with escaping
- All card fields included (name, set, rarity, etc.)
- Automatic filename generation
- Client-side download implementation
🎯 UI/UX Improvements:
- Removed duplicate buttons and switches
- Clean action bar with proper hierarchy
- Working modals with proper state management
- Error handling and loading states
🛠️ Technical Features:
- JWT authentication for all endpoints
- Proper database relationships and indexes
- CORS headers and error handling
- Optimized queries and performance
All todos completed! Ready for full collection management! 🎮✨
✅ Database & API Fixes:
- Fixed collection detail API to use correct column names (card_type, market_price, image_url)
- Removed all mock data and fallbacks
- Updated field mappings throughout collection detail page
- Fixed hero section to use real collection data with proper image support
�� Test Users Created:
- admin@tcgvault.com / admin123 (Admin)
- alice@tcgvault.com / alice123 (User)
- bob@tcgvault.com / bob123 (User)
🃏 Sample Cards Added:
- Lightning Bolt (MTG) - $2.50
- Black Lotus (MTG) - $25,000
- Pikachu (Pokemon) - $8.50
- Charizard (Pokemon) - $350
- Mickey Mouse (Lorcana) - $45
- Elsa (Lorcana) - $15.75
🔧 Collaboration Features:
- Added CollaborationManager to collection detail page
- Integrated real user permissions (isOwner check)
- Updated hero section with real stats and creator info
🔍 Card Management:
- Created cards search API (/api/cards/search)
- Implemented quick add functionality in empty state
- Real-time card search with dropdown results
- Add cards directly to collection with quantity
�� Ready for Testing:
1. Login as any user to see only their collections
2. Create collections with real data
3. Add cards using search functionality
4. Invite collaborators via email system
5. Switch users to test collaboration workflow
Complete end-to-end testing environment ready! 🚀
🎯 Collections Page Improvements:
- Removed TCG selection from creation modal
- Added image URL field for collection hero images
- Changed public checkbox to visibility dropdown (Private/Invite-Only/Public)
- Added success modal with navigation to created collection
- Integrated real API calls for creating and fetching collections
- Added Permission indicators throughout the interface
🃏 Collection Detail Page Enhancements:
- Created comprehensive empty state for new collections
- Added 'Browse Cards to Add' call-to-action button
- Included quick add search functionality
- Improved filtered results empty state with clear filters option
- Integrated API calls for real collection data
- Distinguished between empty collection vs no search results
🗄️ Database & API Updates:
- Added image column to collections table
- Updated collections API to handle image field
- Enhanced API to return proper collection data structure
- Added fallback to mock data for development
🎨 User Experience:
- Beautiful success confirmation after collection creation
- Direct navigation to newly created collection
- Clear visual distinction between different empty states
- Intuitive call-to-action buttons for collection building
- Permission badges visible on collection cards
Ready for users to create collections with images and start building their card collections! 🚀
✅ ALL FEATURES IMPLEMENTED:
🔐 Advanced Permission System:
- Role-based access control (Owner/Editor/Viewer)
- Permission middleware for all API endpoints
- Granular permissions for collection operations
- Activity logging for complete audit trails
🌍 Collection Visibility Types:
- Private: Owner-only access
- Invite-Only: Controlled collaboration
- Public: Community accessible
- Dynamic permission checking across all endpoints
📧 Complete Email Integration:
- Beautiful HTML invitation templates
- Role-based permission descriptions
- Personal message support
- Accept/decline workflow with proper UX
- Bulk invitation system for multiple users
🎨 Rich User Interface:
- Permission indicators with tooltips
- Activity log component with real-time updates
- Collaboration management dashboard
- Bulk invite modal with batch processing
- Permission gates throughout the UI
⚡ Performance & Security:
- Database indexes for optimal queries
- Comprehensive error handling
- CORS headers and preflight support
- JWT-based authentication integration
- Cascading deletes and data integrity
🚀 Ready for Production:
- All API endpoints protected with permissions
- Complete activity logging system
- Beautiful email templates with Resend
- Responsive UI components
- Error handling and loading states
This system now provides enterprise-level collaboration features for community-driven collection building! 🎯
- Created list-users.js to display all users with roles and details
- Added promote-user-to-admin.js to elevate regular users to admin
- Added demote-admin-to-user.js with safety check for last admin
- All scripts use proper ES modules and dotenv for environment loading
- Scripts validate user existence and current roles before operations
- Added detailed documentation to scripts/README.md
- Includes user-friendly output with emojis and clear status messages
- Tested promotion functionality successfully
- Maintains database integrity with proper error handling
- Built complete admin interface for editing all card properties
- Added card search functionality with live results
- Created comprehensive form with sections for:
* Basic information (name, game, set, rarity, etc.)
* Game mechanics (type, mana cost, power/toughness, colors)
* Card text and oracle text
* Image URLs (primary and stock images)
* Pricing information (current and market prices)
- Added real-time card preview that updates as you edit
- Implemented PUT API endpoint for updating cards
- Added proper validation and error handling
- Added database schema updates (updated_at column)
- Integrated admin navigation between card editor and import tools
- Full responsive design with modern UI components
- Live search with card thumbnails and metadata
- Proper form state management and data persistence
- Updated card detail page to fetch real data from API
- Added ownership tracking with quantity management
- Added favorite system for cards
- Added collection and deck management functionality
- Created API endpoints for ownership, favorites, collections, and decks
- Added database columns for quantity and favorited status
- Shows current collections and decks the card belongs to
- Added proper error handling and loading states
- Integrated with real card data from database
- Added purchase links to TCGPlayer and eBay
- Added wrapper div with max-width constraint to ensure consistent card sizes
- Updated image rendering to use object-cover with proper positioning
- Removed maxWidth from Card3D component since it's now handled by wrapper
- Ensures all cards (MTG, Pokemon, Lorcana) have identical dimensions
- Fixed responsive grid layout to maintain consistent card sizes
- Replaced mock Lorcana import with real API integration
- Uses Lorcast API (https://api.lorcast.com/v0/cards/search) for comprehensive card data
- Added proper set code mapping (tfc->1, rotf->2, ink->3)
- Includes card images, prices, stats, and detailed metadata
- Created dedicated Lorcana import scripts for standalone use
- Maintains duplicate checking and proper error handling
- Supports all 3 Lorcana sets: The First Chapter, Rise of the Floodborn, Into the Inklands
- Added retry logic with exponential backoff for Pokemon API calls
- Created Lorcana import endpoint with placeholder data
- Improved error handling for 504 timeouts and 404 not found errors
- Added longer delays for Pokemon imports to avoid rate limiting
- Enhanced logging for better debugging of import issues
- Fixed response parsing to handle different API response formats
- Redesigned card display with 2.5:3.5 aspect ratio and image-only view
- Added infinite scroll to replace pagination
- Implemented authentic card back placeholders for MTG, Pokemon, and Lorcana
- Added rarity-based particle effects with tiered intensity (mythic/enchanted/rare/uncommon)
- Enhanced hover details panel with structured card information
- Fixed search functionality with debouncing and Enter key support
- Improved filter system with working TCG, rarity, set, and price filters
- Added favorite system for cards in both hover and detail views
- Updated card detail page with comprehensive metadata and actions
- Fixed API filtering with proper Vercel Postgres implementation
- Added particle animations and rarity glow effects
- Improved overall UX with better visual hierarchy and interactions
✨ Features Added:
- User registration and login with JWT authentication
- Role-based access control (user/admin)
- Comprehensive admin panel with user management
- Password hashing with bcrypt
- Session management and token storage
- Protected routes and public routes
- Modern login/register forms with validation
🗄️ Database Schema:
- Users table with profile information
- Roles and permissions system
- User-role junction tables
- Session management tables
- Database triggers and indexes
🎨 UI/UX Improvements:
- Updated navigation with user menu
- Admin badge and access controls
- Responsive authentication forms
- Loading states and error handling
- Role-based UI elements
🔧 API Endpoints:
- /api/auth/login - User authentication
- /api/auth/register - User registration
- /api/admin/users - User management (admin only)
- /api/setup-auth - Database schema setup
🚀 Admin Panel Features:
- User listing with search and pagination
- Role assignment (user/admin)
- User activation/deactivation
- System dashboard with stats
- Card management placeholder
- Real-time user management
- Install @neondatabase/serverless, @vercel/blob, @stackframe/stack
- Add database schema setup script (scripts/setup-database.sql)
- Add JSON to Neon migration script (scripts/migrate-json-to-neon.ts)
- Prepare for user collections, decks, and authentication
- Ready for Neon database population with existing card data