Planned features, known limitations, and open questions — grouped
by category. Status tells you whether something is just an idea, being
actively researched, in progress, or blocked on something external.
— view shipped changes →
Identification & Matching
Confidence-scored scan chain with fallback
in-progress
M
v0.14.0 partial: composite confidence score is computed (see confidence.py) — image similarity 40%, AI agreement 30%, OCR/back-stamp text overlap 20%, AI confidence-note language 10%. Surfaced as a 0-100 score with color-coded label on the scan results page. Still TODO: actually use the low-confidence threshold to trigger a fallback wider search (currently just warns the user). Open question: what to escalate to — Claude Opus deep with extra context? Google search via Gemini grounding?
Cross-validate AI-claimed catalog IDs against catalog images
in-progress
M
v0.14.0 partial: Pin&Pop side is now wired — the new-pin scan page computes cosine similarity between user scan and the Pin&Pop catalog's first reference image (via existing DINOv2 embeddings, no extra API calls). Surfaced in the new Match Confidence panel. PinPics side is blocked pending either bookmarklet imports (which the user already controls) or the Playwright path above. Composite confidence also factors in cross-provider agreement on pinandpop_id and OCR-vs-back-stamp text overlap.
Better auto-checklists from set membership
done
S
Done (v0.14.42 + v0.14.44). Inline /new-pin Series create now passes scan_id to /api/collections and seeds the new Series with set members from three sources (chosen-AI set_members + Pin&Pop series scrape + PinPics linked_pins), name-keyed deduped across sources. Background image enrichment runs for each seeded pin so checklist thumbnails populate after a refresh. Also: /series/{cid}/refresh-from-url for re-running the same logic on existing Series.
Local catalog database (scrape Pin&Pop / PinPics)
done
L
Done (v0.14.48). New CatalogPin table + catalog_ingest.py module. Pre-warm a Pin&Pop series URL on the /catalog page and the app fetches every pin, downloads the front image to catalog_uploads/, and computes a DINOv2 embedding. Idempotent re-runs (existing rows updated, no dupes). Used for local visual search on /new-pin via catalog_search.py. Still TODO: PinPics-side pre-warm (PinPics doesn't expose a clean series-page structure so would need a separate scraper); incremental refresh strategy for series that gain new pins over time.
Headless-browser scraping for JS-rendered catalog pages
in-progress
M
v0.14.3: Playwright wiring shipped as opt-in module (headless_scrape.py) with lazy import. New catalog_sites.fetch_pinpics() uses it as a fallback when the cheap requests-based path hits a Cloudflare challenge. Setup: pip install playwright && playwright install chromium (one-time, ~200MB). Browser launched once per process, reused across calls (~300-500ms warm). Known risk: Cloudflare Turnstile / managed challenges may still block Chromium without a stealth plugin. The bookmarklet route remains the most reliable path for PinPics-authenticated data. Still TODO: integrate playwright-stealth if Turnstile becomes a recurring problem in practice.
Higher-resolution pin photos & guided capture
idea
S
Encourage / require higher-resolution uploads — warn when incoming images are below some minimum (e.g. 1024px on the long side). On mobile, the camera capture flow could offer a guided framing overlay so users center the pin and avoid glare. Tied to fake-pin detection: high-res photos are needed for the edge/surface analysis in pin_authenticity.py to deliver good signal.
Barcode / pin-code scanning at entry
done
M
Disney pins often have a SKU barcode on the packaging or a printed pin code on the backstamp. Adding ZXing / QuaggaJS (browser) or pyzbar (server) for barcode extraction would let the user scan a barcode directly for instant catalog lookup — much faster than image-based AI identification when the barcode is visible. Surfaces: home-page Quick Add, /scan, new-pin form, and the ‘Add missing pin’ flow on Series detail. Open question: how much of Disney's pin catalog actually ships with a stable scannable barcode? Some mystery sets have a generic set-level barcode rather than per-pin.
CLIP embeddings on catalog mirror + text→image search
done
L
Done in v0.15.78. embeddings_clip.py uses openai/clip-vit-base-patch32 to encode catalog images + text queries into the same 512-dim space. New catalog_pins.embedding_clip column + /catalog/backfill-clip-embeddings route. /catalog/text-search?q=... ranks catalog rows by semantic similarity to the query text. ~200ms for a top-K scan over ~100k rows via vectorized numpy.
Cross-source catalog ID cross-reference
done
M
Done in v0.15.79. _cross_reference_catalog_ids() in main.py fills blank catalog IDs on /new-pin when the local mirror has a sibling row from another source matching by canonical (name + year-or-series). Surfaced as a blue “Cross-referenced” banner above the IDs row with confidence (exact vs fuzzy).
eBay UPC search on barcode-no-match
idea
S
v0.15.82: when a barcode scan finds no local-catalog match, the user gets web-search buttons (Google, eBay active, eBay sold, Disney Pins Blog, Barcode Lookup) but no inline matches. Worth trying: fire an eBay UPC-search query inline and surface the top 2-3 listings with thumbnails so the user can one-click “Use this as a scan hint”. Caveats: Disney pin packaging UPCs are rarely indexed by sellers in eBay listings, so hit-rate would be low. PinPics + Pin&Pop do NOT support UPC lookup (those sites organize by pin name/year/series, not retailer barcodes), so this is eBay-only. Measure hit-rate on a small batch (~20 scans) before investing in UI.
Fake Detection
Fake pin detection (big feature)
in-progress
XL
v0.14.46 + v0.14.48 partial. Tiers 1 + 2 + community DB shipped:
· Tier 1 (local CV): pin_authenticity.analyze_edge_quality() (Pillow FIND_EDGES + numpy variance) + compare_colors_to_reference() (LAB ΔE).
· Tier 2 (AI visual review): compare_pins_via_ai() sends user photo + catalog ref to Gemini Flash with structured scrapper-detection prompt.
· Community-flagged DB: scrapper_db.py + KnownScrapper table + admin UI for configurable forum/Reddit sources. Banner on visual-auth panel when a pin's catalog ID is in the known list.
Still backlogged (Tier 3): local trained CNN on labeled (real, fake) pairs. Needs a labeling habit first — could bootstrap by tagging pins as “confirmed_authentic” (bought from Disney direct) over time. Data shape in compute_authenticity_score() already accommodates a future ML finding without schema changes. Drew's ask: handle different angles, lighting variations, shiny finishes, and back-of-pin views.
Back-stamp validation
done
M
Done (v0.14.46). pin_authenticity.extract_backstamp_text() uses Gemini Flash vision to read the backstamp text, returning structured JSON: text, © year, manufacturer code, pin code, trademark_present, depth_quality, confidence, notes. Renders in the visual-authenticity panel under “Backstamp OCR”. Far more reliable than EasyOCR for stylized backstamp fonts. Auto-runs when a back-view photo exists on the pin. Still TODO: actively compare the extracted © year + mfr code against the catalog's expected values and flag mismatches explicitly.
pintradingdb.com as alt scrapper / catalog source
done
S
Done in v0.15.35 + v0.15.77. v0.15.35 added PTDB as a first-class crawler source alongside PinPics + Pin&Pop — rows land in catalog_pins with source='ptdb' and feed the local mirror enrichment + set-members linking. v0.15.77 promoted Pin.ptdb_id to a primary identifier on the Pin model so PTDB IDs route through the same vote/veto/override machinery as the other two sources. The /catalog-crawler page has a PTDB toggle alongside PinPics + Pin&Pop.
Background-remove pin before visual authenticity analysis
done
S
pin_authenticity.analyze_edge_quality() currently assumes the pin is the dominant edge structure in the photo — works on clean backgrounds but a busy carpet / desk / wood-grain shot lights up the edge map and inflates the roughness score, leading to false “concerning” verdicts. Fix: run the user's front photo through rembg (already an optional scan-time dep) before calling the edge + color analyzers. The catalog reference image is usually already background-free, so this makes the comparison apples-to-apples. Same treatment would help the color-extraction step (_dominant_colors currently includes background pixels in its palette). Surfaces a flag if rembg isn't installed so the analysis degrades to “include background” rather than failing.
Pricing & Value
eBay sold-listings (Marketplace Insights API)
blocked
S
Sold/completed listings need the Marketplace Insights API which requires production-tier approval. Currently only Browse API (active listings) is available. Active listings are useful for asking price but don't reflect actual sale prices. Blocked on eBay developer approval.
Rarity score per pin
done
M
Done. rarity.py ships compute_rarity(pin) which returns a tier + score from edition size, year, set membership, and eBay-listing count. Rendered as a badge on /pins cards, the /new-pin preview card (using a synthesized pin shape before save), and the pin detail page. Registered as a Jinja global so templates can call rarity_for(pin) directly.
Highest-selling pins Top List
done
M
New Top List ranking pins by recent sold price across the catalog (not just pins the user already owns). Data sources to combine: (1) eBay sold listings — we already have per-pin fetch_sold_listings() via the existing scraper, would need to bulk-run it across the local CatalogPin mirror and cache the median sold price per pin; (2) Pin&Pop “trade value” if their pages expose it (unclear — would need to inspect); (3) PinPics “Cash” / “Trade” values that users contribute. eBay is the most reliable signal but the slowest to gather (one HTTP request per pin); could run as a background refresh on a per-day schedule, storing median + sample-count + last-fetched-at on the CatalogPin row. Surfaces on /top-lists as “Hottest pins right now (by recent sold price)”.
Platform & Distribution
Native Android app talking to the server
idea
L
Phone is where pin photos get taken. Options: (1) PWA — easiest, leverages existing web UI, no app store; (2) React Native — real native UI, more work, can leverage device camera APIs; (3) Kotlin native — most native, most effort. PWA route gets us 80% there with installable home-screen icon, offline shell, and access to camera via the existing getUserMedia flow.
Public server deployment / remote access
idea
M
Currently runs on LAN only. For phone access while out shopping for pins, expose via Tailscale or Cloudflare Tunnel — both let you reach your home server from anywhere without opening ports. Open question: do we need authentication added if reachable from the internet? Yes, even via Tailscale, basic password protection is prudent.
Server-side browser for catalog scraping
idea
M
Some catalog sites require JS execution to render content. Already partially solved via regex on raw HTML for Pin&Pop, but PinPics fully blocks server-side scraping (CAPTCHA-protected). Browser-in-the-cloud (Playwright with stealth plugin, or hosted browser-as-a-service) is the heavy-handed fix. The bookmarklet / extension flow side-steps this by running in the user's already-authenticated browser — that's the current path.
PWA install + offline shell
done
S
Done in v0.15.79. manifest.webmanifest + sw.js served from the root so the SW scope is the whole origin. DisPindable can be added to home screen and runs in standalone mode; service worker caches the shell (CSS, favicon) so cold launch is instant. HTML and API responses pass-through so dynamic content stays fresh. Requires https or localhost (the LAN URL silently skips SW registration).
UX & UI Polish
Mobile testing pass + UI cleanup
idea
M
Drew flagged: nav menus, page padding, button sizes, and overall clunkiness on phone viewports. v0.14.40 added the 768px + 480px media-query block in base.html but it was never end-to-end tested across the actual flows (scan / new-pin / series detail / catalog admin). Walk every page on a real phone and capture concrete issues. Also: tap-target sizes on the checklist cards and toggle buttons may be too small.
Phone-camera capture flow: extensive testing
idea
M
Distinct from the general mobile UI pass — this is the camera pipeline specifically. Things to validate on an actual phone: (1) getUserMedia + the “use camera” button on /scan and Quick Add, across iOS Safari and Android Chrome; (2) auto-focus / exposure behavior on close-up pin shots (most phones default to face-detection focus which misses pins); (3) multi-image capture flow — can the user take front + back + macro in one session without leaving the page; (4) retake behavior when the first shot is blurry; (5) image-quality preview before upload (the existing _compute_scan_quality heuristic could warn the user before they hit Save); (6) orientation handling — portrait-mode photos sometimes come through rotated thanks to EXIF strip variance.
Test out the new visual-authenticity validation (Tier 1 + Tier 2)
idea
S
QA task for the v0.14.46 visual-authenticity panel. Run the “Analyze now” button against a mix of pins: (1) a pin known to be authentic from Disney direct — should score 80+; (2) a pin known to be a scrapper / fake if Drew has one in the collection — should score below 40 and surface red flags; (3) a pin with a busy / non-white background photo — important to see how lighting and background interfere with the Tier 1 edge + color analysis (related: “Background-remove pin before visual authenticity analysis” backlog item); (4) a pin with no catalog reference image — should gracefully skip Tier 2 with a clear “no reference available” note; (5) a pin with a back photo on file — should also surface the backstamp OCR results. Capture failure cases so we know what to tune.
End-to-end test pass for Series + Collection add flows
idea
S
Drew's “TEST COLLECTION ADD — LINK, NEW PIN, ETC.” All paths to creating a Series: (1) /series → + Add Series form; (2) /series/new-from-pinandpop preview flow; (3) /series/import-url one-shot; (4) inline + Create from /new-pin; (5) /series/{cid}/refresh-from-url on existing. Plus manual /collections add. Each path has slightly different field handling and a smoke-test checklist would catch drift before users hit it.
Better colors + scannability
idea
S
Pico CSS defaults are clean but the dark-mode contrast on muted-color text + secondary borders is sometimes too subtle. Audit text contrast ratios + tune the muted color palette. Also: the four left-border accent colors used on panels (teal for visual-auth, purple for confidence, red for eBay sold, etc.) are currently arbitrary — a consistent semantic palette would help.
UI redesign A/B test (vs Claude-designed alt)
idea
M
Drew's ask: have Claude propose a redesign of one or two key pages (likely /new-pin and /scan, since those are where the most clutter and the highest decision-load live) and ship them as an A/B togglable variant. Implementation options: (1) feature-flag in app_settings — ui_variant=claude swaps templates at render time; (2) parallel template files in templates/v2/ that subclass base.html differently. Approach: ask Claude to redesign one focused page (e.g. /new-pin), produce a parallel template, ship both behind a toggle, A/B in your own usage, keep the winner. Specifically watch: information hierarchy, panel ordering, color usage, default-collapsed vs default-expanded choices, mobile breakpoints. Backlog rather than next-up because it's open-ended — a single session producing one variant is the right first step.
Sort-by across collections/series/pins
done
S
Currently /pins, /series, /collections all default to name-asc with no user control. Add a sort dropdown: by name, by year, by recently-added, by acquired-date, by value, by completion %. Persists via URL param so the sort survives navigation.
“Recently added” flag on pins / series / collections
done
S
Highlight rows added in the last N days with a small “NEW” badge so the user can quickly see what they've added recently. N configurable in Settings (default 7 days). Pairs well with sort-by-recently-added above.
Hide / collapse advanced UI areas
done
S
The /new-pin page in particular has accumulated a lot of disclosure panels (AI provider cards, PinPics candidates, Pin&Pop candidates, visual-similarity, set members, linked-pins, reference-image selection, and now local-catalog matches). Default many of these to collapsed via <details> and let the user expand. Power users can flip a setting to default-expand.
Rationalize the AI scan-type matrix
idea
S
Six providers (Claude / Opus / Gemini / Gemini Flash / OpenAI / OpenAI Deep) + cheap-mode toggle. The current scan/identify UI surfaces all of them with toggles, which is overwhelming. Consolidate into a smaller set of presets (“fast and cheap” / “balanced” / “throw everything at it”) with an advanced mode that exposes the full matrix for people who want it.
Mobile-responsive validation
idea
M
Promoted from OPEN_QUESTIONS v0.15.81. The web UI works on phones via Pico CSS defaults, but heavy-data pages (scan results with all the AI panels + Pin&Pop block + Lens result) get tight on small screens. Needs a focused mobile pass: hit /scan/N/new-pin on a real phone with real data, list what breaks (overflow, unreachable buttons, tiny tap targets), fix in one version bump.
Pin detail page redesign (tab split)
done
L
Done in v0.15.80. The 2063-line monolith of pin_detail.html split into five tabbed panels: Overview, Photos, Authenticity, Catalog, History. Progressive enhancement — all content still renders server-side; JS toggles hidden. URL hash drives the active tab (#tab=photos); back-button works.
/new-pin skeleton-hydrate (eBay async-load)
done
M
Done in v0.15.80. The eBay active + sold scrapes (2-5s each, blocking) moved to /scan/{scan_id}/ebay-async with a skeleton placeholder + JS hydration. v0.15.81 cleanup deleted the dead synchronous block + the ebay_data / ebay_sold_data placeholder variables. Other heavy /new-pin sections (AI fan-out, set members, visual similarity) still render synchronously but are either cached or DB-local so they don't block meaningfully.
Things flagged that need a decision before they can become proper
backlog items. Either answer them or tell me they don't matter and
I'll drop them.
Fallback escalation strategy
When the new confidence score is low (<40%), what should the scan chain do? Options: (1) escalate to Claude Opus deep with explicit 'previous providers were uncertain' context, (2) trigger an extra grounded web search, (3) just warn the user with no escalation. Currently doing (3). (1) is roughly the same cost as a normal deep scan; (2) is free if we already called Gemini once.
Set member auto-add UX
When the catalog tells us a pin belongs to a set of 8, should we (a) silently auto-create 7 missing-pin rows, (b) show a 'Build out this set' button on the new-pin page that does it on click, or (c) leave it manual? Recommend (b) — auto-creating could surprise users with rows they didn't ask for, but a one-click action is valuable for checklist completeness.