Identity that supports two entry points
Email/password accounts and Google OAuth converge on the same user model. JWTs work through an httpOnly browser cookie or a Bearer token for API clients.
A full-stack trading card collection and marketplace platform.
Scan cards, catalog what you own, show it off in your binder, and trade with collectors—on your terms, directly.







The portfolio build uses deterministic mock data and local browser state to reconstruct the application's major workflows without calling the original infrastructure.
Validate and normalize an upload, extract text, rank catalog matches, then confirm the card before it enters the binder.
02Organize cards in tactile 3×3 pages, manage card details and visibility, and turn owned cards into listings.
03Browse condition-aware listings, inspect seller profiles, and open conversations tied to the exact card being discussed.
04Keep buyers and sellers informed through status changes, unread notifications, and post-transaction reviews.
Run a simulated scan, save the result to a binder, filter listings, message a seller, clear notifications, and leave a review. Every action is local, reversible, and clearly labeled.
Launch browser demoThe deployed application used a Next.js client, a FastAPI domain API, and an independently deployable FastAPI scanner. PostgreSQL held durable state; Redis, AWS, and Google provided supporting capabilities.
The source repository preserves the full implementation: application code, migrations, tests, containers, API specifications, and deployment configuration.
Email/password accounts and Google OAuth converge on the same user model. JWTs work through an httpOnly browser cookie or a Bearer token for API clients.
Binder inventory is the source for listings. Listing states, buyer/seller ownership, scoped conversations, notifications, and reviews form one connected domain.
The scanner has its own FastAPI boundary and resource profile: image normalization, S3 upload, Rekognition OCR, and fuzzy matching against a local card catalog.
Docker health checks, Nginx request and connection limits, Redis-backed registration throttling, durable usage caps, and environment-driven configuration control runtime risk and cost.
This is a source-backed summary, not a claim of formal certification. Each item below maps to an implemented control in the preserved application.
Passwords are hashed with bcrypt through Passlib. Password-reset tokens are generated with a cryptographic RNG and stored as HMAC-SHA-256 digests rather than raw tokens.
Signed JWT access tokens carry issued-at and expiry claims. Browser sessions use an httpOnly, SameSite=Lax cookie with a configurable Secure flag; API clients may use Bearer auth.
Protected FastAPI dependencies resolve active users from validated tokens, while binder, marketplace, chat, notification, profile, and review routes enforce resource ownership and participant checks.
Credentialed CORS uses configured origin allowlists. Nginx applies endpoint-specific body, request, and connection limits; Redis and PostgreSQL back application-level rate and usage limits.
Runtime credentials are read from environment-backed settings. The committed example file contains key names and safe defaults, while the real .env path is ignored by Git.
The production proxy is configured for HTTPS through Certbot. Upload paths constrain request sizes and accepted formats, and the scanner decodes, rotates, converts, and bounds images before OCR.
Use the browser demo for the product story, then inspect the repository for the original services, domain models, migrations, tests, infrastructure, and API contracts.