Case Study

Miniatures Cataloger

A Django app built to help a client resell a 16,000-piece miniatures collection on eBay. It identifies a figure from the number stamped on its base, matches it against a 1,140-figure reference catalog I built, and turns the result into a ready-to-post listing. Built to make a slow, expert-knowledge resale workflow fast and repeatable.

Django Data Scraping Reference Database eBay API OAuth

The Problem

A client has a collection of roughly 16,000 pre-painted D&D and Pathfinder miniatures to sell on eBay. Listing one by hand means photographing it, identifying which set it came from and its figure number, researching a fair price against completed sales, writing a description, and filling out the eBay form: about 10 to 15 minutes each. Across the whole collection that is on the order of 3,200 hours of work, with no system tracking status, condition, or pricing.

16,000
miniatures to list
10-15 min
per item, by hand
~3,200 hrs
total manual effort

The Solution

A full-stack Django app with a mobile-friendly capture flow. Photograph a figure, read the number off its base to find it in the reference catalog, confirm the match, then build and post the eBay listing without leaving the app.

Base-Label Lookup

Every figure has a number stamped on its base, like "23/60". The app reads that number and looks it up in the catalog, using the set total (the "/60") to narrow what would otherwise be dozens of matches down to the right set. It is fast, deterministic, and free, which beat image recognition on every count for this job.

Self-Built Reference Catalog

The lookup only works because of the data behind it: roughly 1,140 known figures, assembled by scraping public set checklists (minisgallery, miniscollector, Wikipedia) and reconciling them against each other. A separate scraper backfills a reference photo for each entry so matches can be confirmed by eye.

Listing Builder

Single figures or multi-item bundles. The app auto-generates an eBay-compliant title (capped at 80 characters) and a description from the catalog data, and offers a one-click "completed sales" search to set a fair price. Everything stays editable before posting.

Direct eBay Posting

Listings post straight to eBay through the Inventory API using OAuth, with a sandbox/live toggle for safe testing, daily API-usage tracking, and seller policy IDs stored in the database so credentials can be updated without redeploying.

Where does AI come in? It is an optional fallback, toggleable in settings, for the occasional figure whose base label is worn or missing. When it is off, those go straight to manual entry. The deliberate decision here was that a catalog I controlled was more accurate, cheaper, and more reliable than leaning on image recognition for the common case.

How It Fits Together

Phone Capture
Photograph figure
Django App
Look up + review + list
SQLite DB
Catalog + collection
Catalog Scrapers
Checklists + images
eBay Inventory API
OAuth + posting
Gemini
Optional fallback

Each physical figure moves through a clear status flow (draft, needs review, manual entry, ready) before it can be added to a listing, so the collection is always in a known state.

Inside the App

DnD Mini Lister ◆ Review

Review Queue

Items that need attention before they can be listed. Ready items move to New Listing.

All Needs Review 0 Manual Entry 1 Draft 0
ItemSetConditionStatusAction
Beholder Lich Unhallowed #31 Near Mint Ready
Young Green Dragon Dragon Collector's Set #3 Near Mint Manual Entry Review
Frost Giant Tyranny of Dragons #27 Near Mint Ready
Faceless Stalker Rise of the Runelords #6 Near Mint Ready
Roper Underdark #56 Near Mint Ready
DnD Mini Lister ◆ Young Green Dragon
← Back to queue

Young Green Dragon

Dragon Collector's Set · #3

Front Photo
Front photo of the green dragon miniature
Bottom (base label)
Base label reading Dragon Collector's Set, Young Green Dragon, 3/5
Young Green Dragon
Dragon Collector's Set
3
/
5
not set
Search catalog ?

Near Mint
View sold comps on eBay →
AI price estimate

Mark as Ready Save changes

Reproduced from the app's own templates and styling, using real items from the database. The Young Green Dragon's base label reads 3 / 5: that number is the catalog key the lookup turns into a full identification.

Impact

Tech Stack

Django Python SQLite Web Scraping eBay Inventory API OAuth Gemini (fallback) Gunicorn + systemd

Have a workflow worth automating?

I build practical, custom tools that take the manual grind out of repetitive work, whether that's a business process or a personal project.

Let's talk