Admin, Landing & Demo
Admin / operator dashboard (/admin)
PIN-gated (requireAdminSession). Tabs in admin-dashboard-client.tsx:
- Overview — aggregate metrics across all stores.
- Merchants — per-store metrics + operator actions: set qualified trial, reset usage,
grant Shopify credit, create custom plan, change AI model, refresh Web Pixel. Toggle
Cards ⇄ Table (cards default:
StoreAvatarmonogram/favicon + headline metrics); a card or the row name links to the per-store detail page (below). - Generations — generation log.
- Logs — structured
app_logswith level control. - Demo Leads — landing demo email captures (
captured_emailswheresource=landing_demo), CSV export. - Inquiries — contact-form submissions (
source=contact_inquiry).
Custom plan creation
Admin → Merchants → ”★ Custom plan” calls POST /api/admin/billing
{ action: 'create_custom_plan', … } → createShopifySubscription with custom
price/limits → returns a confirmationUrl to send to the merchant. On approval it activates
like any plan; the store’s custom_plan fields drive limits/overage.
Per-store detail page (/admin/store/[storeId])
A dedicated, admin-auth-gated page for one store (mirrors the admin/page.tsx session guard).
Reuses existing endpoints — no new DB or API-shape changes:
- Data:
/api/admin/metrics(pick the store bystoreId),/api/admin/billing-history?storeId=,/api/admin/generations?storeId=,/api/admin/logs?search=<shopDomain>&level=error. - Sections: header (avatar, name, domain, health/plan/sub badges, install/last-active/last-sync,
quick actions Sync/Pixel/Shopify/Dashboard), KPI row, conversion funnel (clicks → sessions →
generated → purchases via
computeStoreFunnel), config & billing (change model, mark/unmark test, reset usage, qualified trial, grant credit, custom plan — same endpoints as the Merchants row), billing history, recent generations, recent errors. - Shared code:
lib/client/store-detail.ts(purestoreAvatar/computeStoreFunnel, unit-tested),lib/client/admin-types.ts(canonicalMerchant/AdminMetrics/…),lib/client/admin-format.ts(formatters + status helpers),components/store-avatar.tsx(monogram + best-effort favicon). - Out (v2): per-day time-series trend charts; real Shopify Brand-API logo; view/override of merchant widget settings.
Marketing landing (/)
Single client component components/landing/landing-page.tsx (Syne + DM Sans, violet→fuchsia
brand). Sections: Nav (auto-hide on scroll, mobile drawer), Hero (before/after slider +
floating metrics), TrustedBy (Icedout), Problem, HowItWorks, Integration, Features, LiveDemo,
Comparison, VideoDemo, Results, ROICalculator, Pricing, FinalCTA, FAQ, Footer. Smooth-scroll
anchors with a sticky-header offset; overflow-x: clip + global box-sizing: border-box.
Nav/Footer are exported and reused by /contact, /privacy, /terms.
Standalone live demo
The landing live demo is fully decoupled from the demo store. It calls the AI provider directly — no store, billing, session, or storefront rate limits.
- Products: curated Icedout set in
lib/demo-products.ts(sunglasses, necklace, bracelet, ring, watch), self-hosted images inpublic/landing/demo/. POST /api/demo/try-on{ personImageDataUrl, productId }→ resolves the garment from the allowlist,createTryOnTaskdirectly, per-IP in-memory throttle. ReturnstaskId.GET /api/demo/try-on-status?taskId=→getTaskSnapshotdirectly.POST /api/demo/capture-email→captured_emails(source=landing_demo).- Client gate: 2 free generations (localStorage), then email.
Contact form
/contact → POST /api/contact → stores in captured_emails (source=contact_inquiry,
metadata: name/storeUrl/message/type). No email service configured — read submissions in the
admin Inquiries tab.