-
-
hoose from what the shop actually sells, not an endless palette of colours.
-
How it works: five steps from a budget to one purchase-ready decision.
-
Step 1: pick lipstick, blush or eyeshadow, set a budget and a finish. Matching products appear instantly.
-
Step 2: shortlist up to three in-stock products. Out-of-stock items can't be selected.
-
Step 3: add a photo or use the sample photo. Nothing is sent until you tick the consent box.
-
Step 4: each shade is applied to the same original photo, with the original alongside. AI previews are labelled.
-
Step 5: the comparison receipt and a product-only purchase card with shade code, price, note and shop contact.
Inspiration
Virtual try-on usually offers every colour imaginable, but a shopper can only buy what is actually on the shelf, at a price they can afford.
CounterReady starts from one shop's real catalogue and the shopper's budget, and uses the AI preview only to choose between a handful of genuine options.
What it does
- Pick a product type and budget. Lipstick, blush or eyeshadow, a maximum budget in PKR, a finish and an optional colour family. Matching products appear immediately. If nothing matches, the app says which filter caused it instead of quietly showing over-budget items.
- Shortlist up to three in-stock products. Out-of-stock items can't be selected.
- Add a photo with explicit consent, or use the built-in sample photo.
- Compare. Every shade is applied to the same original photo, same crop, with the original beside the results. A failed preview can be retried on its own. No shade is ever generated from another preview.
- Decide. Choose a favourite, add a note, and get a comparison receipt plus an exportable purchase card with the shop contact and a reminder to confirm availability and the physical colour. The card is product-only by default; the shopper's face appears only if they switch it on.
Same photo, different shades



Top: the original photo. Middle: Sample Rosewood (CR-04, satin). Bottom: Sample Cherry Pop (CR-03, matte). Both are real results from the YouCam AI Makeup API on the same photo. Digital colour is approximate.
How we use the YouCam API
POST /s2s/v2.0/file signed upload of the photo, once per photo
POST /s2s/v2.0/task/makeup-vto one lip_color, blush or eye_shadow effect per shade
GET /s2s/v2.0/task/makeup-vto/{id} polling until the result is ready
Colour and texture come from the catalogue. All 17 in-stock shades across the three product types were run against the live API. Results are downloaded, compressed and stored, because the provider's result URL is short-lived.
Honest by design
- The shop is a manually maintained sample catalogue of 20 made-up products, labelled as such everywhere. It is not a live retailer feed.
- Preview colours are rendering settings, not calibrated matches to a physical product.
- Product facts, the shopper's choices and AI imagery are kept separate and labelled.
- No skin analysis, no suitability score, no chatbot, no claim of exact shade matching.
- We don't promise that YouCam deletes uploaded photos immediately, because we haven't verified their retention.
How we built it
Next.js 16, TypeScript (strict), Tailwind CSS and Zod. Neon Postgres through the serverless driver and Drizzle holds sessions, preview records and a usage ledger.
The demo credit budget is enforced in the database (an advisory-locked ledger), with:
- an input-hash result cache
- refunds for tasks that never started
- rate limits and image checks by file signature
- server-enforced consent and a delete-my-data endpoint
- 28 unit tests and end-to-end browser tests
The demo video is animated with Remotion and narrated with an ElevenLabs voice.
Code: github.com/s-a-b-i/CounterReady
Challenges
- The API docs describe image size limits inconsistently, so we tested the real API and settled on a 1080 px long side.
- Keeping a shared demo key alive for judges led to the database-enforced budget and a pre-warmed cache for the sample photo, so judges spend no credits.
- A failing test showed our "no matches" message was vague when no single filter was to blame. It now explains what does exist.
What we learned
Preview effects differ a lot by product type: textures, required fields and how visible the result is. Eyeshadow, for example, is subtle on photos where the eyes are partly covered.
What's next
A real product feed and photography, calibrated shade data from the brand, and a shop-side view of which shades get shortlisted.
Built With
- drizzle-orm
- framer-motion
- neon
- next.js
- postgresql
- react
- sharp
- tailwindcss
- typescript
- vercel
- youcam-api
- zod

Log in or sign up for Devpost to join the conversation.