Remove the temporary listing-level image count from the schema, validation, DTO, and draft contract. Publication now requires the persisted inventory image repository count. Add migration 0009 and update listing tests and implementation status. Verification: npm test passed 62 tests and integration passed 14 tests. No build script is configured in this repository.
Pokémon Inventory & Sales Reference Catalog
A personal Pokémon inventory and sales reference catalog for documenting owned Pokémon products, comparing market pricing from supported providers, and presenting public asking prices.
Scope
This is a catalog and sales-reference application, not an e-commerce platform.
The application supports:
- Pokémon trading cards
- Pokémon merchandise
- Sealed products
- Accessories
- Pokémon Worlds / Pokémon Center merchandise
- Other Pokémon-related products
The public site communicates what is available, what the market suggests it is worth, and what the seller is asking. Transactions occur outside the application.
Core domain model
Product → Inventory Item → Listing → Sale
- Product: what an item is.
- Inventory Item: an individual physical copy owned by the seller.
- Listing: the current public offer for an inventory item.
- Sale: a manual record of an external transaction.
Products remain in the database after inventory is sold.
Technology
- Vue 3 + Vite
- Modern JavaScript / latest ECMAScript
- Vue Router
- Pinia where justified
- Node.js + Fastify
- PostgreSQL + Drizzle ORM
- Redis + BullMQ
- REST API under
/api/v1 - Docker + Docker Compose
- GitHub Actions
- PostgreSQL-backed search behind a
SearchService - Pluggable image storage and pricing-provider adapters
- Automated unit, integration, component, E2E, and accessibility tests
- WCAG 2.2 AA target
TypeScript is not used unless a documented technical justification establishes a concrete benefit that cannot reasonably be achieved with modern JavaScript.
Repository layout
apps/web— Vue frontendapps/api— Fastify APIapps/worker— asynchronous jobspackages/*— genuinely shared contracts, validation, and safe utilitiesdatabase— migrations and seedsdocs— source-of-truth project documentation.github— Copilot instructions and CI
Read AGENTS.md and .github/copilot-instructions.md before implementing features.
Implementation Status
Start future work from docs/IMPLEMENTATION-STATUS.md. It records the completed foundation, the next bounded milestone, the overall roadmap, and verification commands.
Database Development
- Copy
.env.exampleto.envand replacechange-mewith a local-only password in both connection URLs. - Run
npm install,npm run db:up, andnpm run db:migrateto prepare the development database and Redis. - Create and migrate the isolated
pokemon_inventory_testdatabase before running integration tests. - Run
TEST_DATABASE_URL='postgresql://...' TEST_REDIS_URL='redis://...' npm run test:integration.
Integration tests reject database names not ending in _test and truncate their tables before each test. The Redis limiter test uses a unique temporary key prefix and does not modify application session data.
Initial Administrator
After the development database is migrated, set INITIAL_ADMIN_EMAIL, INITIAL_ADMIN_PASSWORD, and INITIAL_SELLER_NAME in your local .env, then run npm run provision:admin once. The command creates the only initial administrator and linked Seller; it refuses to run after any User exists.
Password Recovery
Set SMTP_URL, SMTP_FROM, and PASSWORD_RESET_URL in the local .env before starting the API. Password reset tokens are delivered only through SMTP, expire after one hour, are stored as hashes, and are single use.
MFA Secret Protection
Set MFA_ENCRYPTION_KEY to a base64-encoded 32-byte key before starting the API. Generate one with openssl rand -base64 32; keep it in secret management and retain it for as long as enrolled MFA methods must remain readable.