Admin, Landing & Demo

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_logs with level control.
  • Demo Leads — landing demo email captures (captured_emails where source=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 in public/landing/demo/.
  • POST /api/demo/try-on { personImageDataUrl, productId } → resolves the garment from the allowlist, createTryOnTask directly, per-IP in-memory throttle. Returns taskId.
  • GET /api/demo/try-on-status?taskId=getTaskSnapshot directly.
  • POST /api/demo/capture-emailcaptured_emails (source=landing_demo).
  • Client gate: 2 free generations (localStorage), then email.

Contact form

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