Runbooks
Operational procedures for common situations.
Deploy the web app
cd apps/web && npx vercel --prodGitHub auto-deploy is unreliable — always deploy via CLI. Verify with the health check:
curl -s https://app.tryvio.ai/api/health # expect 200 {"status":"ok"}Releasing the storefront widget + API (backward-compat is law)
The storefront widget is a theme app extension: its JS/CSS are hosted on Shopify’s CDN,
versioned per app version (shopify app deploy), and propagate to storefronts with a
Shopify-side lag we do not control. The API (Vercel) deploys instantly. So at any time —
for weeks, across merchants — old, cached widgets call the new API.
Rules:
- API changes are additive-only / backward-compatible. Add fields, endpoints, or optional params (safe defaults). Never remove/rename a field an old widget reads, change a response shape, or break an endpoint contract. A breaking change ships as a new versioned endpoint; retire the old only once no storefront runs the old widget.
- Deploy order: API first → then the widget (
shopify app deploy --force). Never widget-first. - Never rename widget asset files to bust cache. Shopify versions assets automatically; renaming breaks the scripts’ self-location and can pin a storefront to a broken version.
- Test the widget on a dev store / preview theme before deploying. A broken widget version can get pinned on a storefront.
Verify what a storefront actually serves (the version is in the asset URL):
# public CDN asset for a version:
curl -sI "https://cdn.shopify.com/extensions/<extension-uuid>/<versionTag>/assets/tryvio-theme.js"
# read a password-protected dev store's real page:
curl -s -c cj -L "https://<shop>.myshopify.com/password" -o pw.html # grab authenticity_token
curl -s -b cj -c cj -L -X POST "https://<shop>.myshopify.com/password" \
--data-urlencode form_type=storefront_password --data-urlencode password=<pw>
curl -s -b cj "https://<shop>.myshopify.com/products/<handle>" | grep -oE 'extensions/[^/]+/tryvio-ai-[0-9]+'If a storefront is stuck on an old version: toggle / remove+re-add the app embed, or duplicate+publish the theme, to force re-resolution.
A merchant’s billing UI looks wrong
The /billing page self-reconciles against Shopify on every load. If a merchant reports a
stuck state, have them reload /billing. To inspect: check app_logs
(billing.reconciled_from_shopify, billing.no_active_subscription).
Debugging billing (trace events)
Set app_config.log_level to debug for a full step trace (default info only logs
anomalies). Pull app_logs filtered by requestId or clientTraceId to read one merchant
action front-to-back. Key events: billing.reconcile.*, billing.subscribe.*,
billing.callback.*, webhook.{received,reconcile_by_domain,processed,cancelled_others},
shopify.token.{refreshed,recovered_after_race,needs_reconnect},
shopify.graphql.auth_retry, and the browser-side client.billing.subscribe.* /
client.dashboard.metrics.* events. See
Billing Pipeline → Observability for the full
event list.
Reset a store’s usage / grant relief
Admin → Merchants → expand the store:
- Reset usage — zeroes
try_ons_used+overage_pending. - Grant credit — issues a Shopify app credit.
- ★ Custom plan — create a tailored subscription (sends a confirmation URL).
Debug a stuck generation
- Find the session in
tryon_sessions/ the job intryon_provider_jobs(external task id). - Check the provider snapshot via
getTaskSnapshot(taskId). - KIE results land on
tempfile.aiquickdraw.com; the callback persists to Supabase Storage. If the callback never fired, the client keeps pollingtry-on-status.
The landing live demo is failing
- Confirm the demo garment images resolve:
https://app.tryvio.ai/landing/demo/<id>.jpg. /api/demo/try-onhas an in-memory per-IP cap (12/hr per warm instance) — not the issue for normal traffic.- It does not touch the demo store; check
app_logsdemo.tryon.*.
Read demo leads / contact inquiries
Admin → Demo Leads (CSV export) and Inquiries tabs. Both are rows in
captured_emails filtered by source.
Rotate a key
Update the value in Vercel env (tryvio-shopify project) → redeploy (vercel --prod).
For TOKEN_ENCRYPTION_KEY, rotating invalidates stored tokens — avoid unless necessary.
Deploy docs
cd apps/docs && npx vercel --prod --scope mihogv-1894s-projects # public
cd apps/docs-internal && npx vercel --prod --scope mihogv-1894s-projects # internal