2026-09-10 07:40:18 -04:00
2026-09-10 01:36:15 -04:00
2026-09-10 02:06:25 -04:00

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 frontend
  • apps/api — Fastify API
  • apps/worker — asynchronous jobs
  • packages/* — genuinely shared contracts, validation, and safe utilities
  • database — migrations and seeds
  • docs — 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

  1. Copy .env.example to .env and replace change-me with a local-only password in both connection URLs.
  2. Run npm install, npm run db:up, and npm run db:migrate to prepare the development database and Redis.
  3. Create and migrate the isolated pokemon_inventory_test database before running integration tests.
  4. 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.

Local Development

After creating .env, set the required local SMTP and MFA values, then start the complete development stack from the repository root with:

SMTP_URL=smtp://localhost:1025
SMTP_FROM=no-reply@example.test
MFA_ENCRYPTION_KEY=<output from: openssl rand -base64 32>

The MFA key must remain stable while enrolled MFA methods exist. Keep it in local secret storage and do not commit it.

npm run dev

This command starts healthy PostgreSQL and Redis containers, applies migrations, and runs the Fastify API, durable image worker, and Vue/Vite web app together. Open http://localhost:5173/ in a browser. The Vite server proxies /api requests to the API on port 3000.

The command does not provision an administrator automatically. Run npm run provision:admin once after setting the initial administrator variables in .env when admin access is needed. Stop the application processes with Ctrl+C; stop the containers separately with npm run db:down when they are no longer needed.

For a disposable local database reset, use:

npm run db:reset
npm run provision:admin

Or combine both operations with:

npm run db:reset:admin

db:reset removes the local PostgreSQL and Redis volumes, recreates healthy containers, and synchronizes the current Drizzle schema with drizzle-kit push --force. It is destructive and local-development-only. It does not modify .env.

Visual Development

Run Storybook to inspect the authoritative design tokens and mock visual fixtures without requiring API data:

npm run storybook

Open http://localhost:6006/. Use the Storybook theme toolbar to switch between light and dark themes. The accessibility addon is enabled for component review. The fixture showcase is intentionally mock-only and is not part of the production router.

Seed representative API-backed catalog data for browser testing with:

npm run seed:demo

The seed is non-destructive and exits without changes when the demo catalog already exists.

Browser Workflow Tests

With npm run dev running, configured local admin credentials, and demo lookup data available, run the authenticated browser workflow with:

npm run test:e2e

The authenticated workflows cover login, admin overview loading, product and physical inventory creation, image management, listing publication, sales and audited sale correction, settings updates, Saved Views CRUD, and export controls. They skip when INITIAL_ADMIN_EMAIL or INITIAL_ADMIN_PASSWORD is not configured.

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. For local development with an SMTP service listening on port 1025, use SMTP_URL=smtp://localhost:1025 and SMTP_FROM=no-reply@example.test. 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, then paste the output after MFA_ENCRYPTION_KEY= in .env. A command that only runs printf displays the value but does not update .env. Keep the key in secret management and retain it for as long as enrolled MFA methods must remain readable.

S
Description
No description provided
Readme
3 MiB
Languages
JavaScript 79.8%
Vue 15.3%
SCSS 3.4%
Shell 1.4%