Try-On Pipeline
The storefront try-on is asynchronous: create a session, kick off a provider task, the provider calls back, the client polls for the result.
Storefront flow
- Session —
POST /api/storefront/session{ shopDomain, productHandle }→ creates atryon_sessionsrow, checks widget-enabled access, returns a serversessionId+ product snapshot (incl. primary reference image URL). - Try-on —
POST /api/storefront/try-on{ shopDomain, productHandle, sessionId, personImageDataUrl }:- Billing gate (
checkBillingGate), IP abuse limit (enforceAuditWindowLimit), per-shopper rate limit (with email-gate bonus). - Resolve product + primary garment image.
- Persist the person image (
persistInputImage→TRYVIO_STORAGE_INPUT_BUCKET). createTryOnProviderClient(...).createTryOnTask({ personImageUrl, garmentImageUrl, callBackUrl })→ provider task id stored intryon_provider_jobs.- Returns
{ status: 'pending', pollAfterMs }.
- Billing gate (
- Callback — the provider calls
/api/storefront/try-on/callback(signed token) when done; the output is persisted (persistOutputImage→ output bucket). - Status — client polls
POST /api/storefront/try-on-status{ sessionId, … }→ returns{ status, outputImageUrl? }once succeeded.
Why async
generateTryOn (the synchronous variant) polls the provider until complete (~60–90s),
which exceeds serverless limits. Production uses createTryOnTask + provider callback +
client polling instead.
Storage buckets
| Env var | Bucket |
|---|---|
TRYVIO_STORAGE_INPUT_BUCKET | uploaded person images (short retention) |
TRYVIO_STORAGE_OUTPUT_BUCKET | generated results |
TRYVIO_STORAGE_MERCHANT_BUCKET | merchant-provided images |
The storage-cleanup cron expires old input/output rows after
TRYVIO_TEMP_FILE_MAX_AGE_HOURS.
Result hosting note
KIE.AI returns result URLs on tempfile.aiquickdraw.com; fal.ai on fal.media/cdn.fal.ai.
The app persists outputs to Supabase Storage for durability.