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.
- 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.
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.