Wheerli
Building useful visual search, from retrieval to release decisions.
- Status
- Live iOS product; Android release work continues
- Year
- 2026
- My role
- Founder and product engineer
- Stack
- TypeScript, Python, Cloudflare Workers, Vectorize, Cloud Run, Image embeddings, Jev, SwiftUI, Flutter
The problem
A shopper starts with an outfit photo, but a similar-looking image is not necessarily the right garment or an available product. Useful search needs good candidate coverage, reliable product data and a clear distinction between visual resemblance and a verified offer.
How I approached it
I separate retrieval from model ranking and product validation, then measure each stage. This lets me investigate whether a poor result came from missing candidates, incorrect comparison, unavailable images or incomplete offer data. Deployment decisions depend on the complete product experience.
- Select a garment from an outfit photo
- Retrieve catalogue and external candidates
- Check candidate identity and available evidence
- Rank image similarity with bounded model calls
- Return results with explicit missing or unverified data
What I built
- TypeScript search services on Cloudflare Workers, vector retrieval and a Python embedding service on Google Cloud Run, connected to SwiftUI and Flutter clients.
- A catalogue pipeline that preserves product identity, validates publication counts, batches cache persistence and skips unchanged feeds.
- Evaluation tools for model review and retrieval comparisons, including fixed result slots, failures, deadlines, usage and incomplete evidence.
- Controlled rollout and explicit outcome states, so an unscored candidate or experimental result is not silently treated as verified.
Engineering evidence
A production repair: make catalogue publication reliable
Reused supplier IDs could overwrite staged products, leaving publication waiting for a count it could never reach. I preserved established page identities, assigned distinct IDs to conflicting pages and added bounded readiness checks. The verified run published 1,268 products. A subsequent unchanged-feed check completed in 16.24 seconds without reprocessing the catalogue.
An evaluation decision: keep the current retrieval route
On 20 October I compared the existing visual-search provider with browser-based retrieval using the same 12 garment crops and unchanged Jev ranking. The protocol retained missing and failed slots, with organic and sponsored results assessed separately. Browser organic retrieval looked promising, but missing thumbnails, corrupted currency evidence and a server-side challenge prevented a release decision.
A deliberate operating trade-off
Catalogue polling moved from 24 launches to four per day, with bounded job and readiness timeouts. That cuts scheduled launches by 83.3% while allowing up to six hours to detect a supplier update. It is an operational change; an equivalent cloud-bill saving has not been established.
Retrieval experiment: useful visual results in the first five slots
12 previously reviewed development crops; five fixed slots per query. Missing slots remain in the denominator. Same model-ranking policy across all routes.
| Retrieval route | Useful visual slots |
|---|---|
| Existing visual retrieval | 27 / 60 |
| Browser organic retrieval | 34 / 60 |
| Browser sponsored retrieval | 20 / 60 |
Provider/score-blind provisional AI review, not independent human ground truth or a holdout. Visual resemblance can include editorial images and does not establish purchasability. Browser currency accuracy, equivalent complete-search latency and deployed cost remained unresolved. This experiment did not change the app.
Where it stands
The iOS product and search backend are live; Android release work continues. The catalogue repair has operational verification. Retrieval experiments remain separate from production until complete quality, latency and cost checks support a change. I do not claim validated public-user adoption or an end-to-end search speedup.
What it taught me
The useful result of an experiment can be a decision not to ship. Keeping missing results and failures visible prevents a faster-looking or cheaper-looking route from winning because it did less work. The next evidence to collect is independent human review, complete search latency and genuine user feedback.