The Merch App is a standalone Vite SPA that powers the fan-facing custom merchandise experience. It supports three distinct conceptual journeys:
The app runs at apps/zooly-merch/ (thin Vite wrapper) with client code in packages/merch/client/, server logic in packages/merch/srv/, admin builder in packages/merch-admin/, payment integration via @zooly/srv-stripe-payment, and a Drizzle-backed API on apps/zooly-app/.
isPersonalized). Personalized designs utilize selfies and AI generation; Branded designs skip selfie-capture and generation entirely to apply template artwork directly.catalogProductIds./create route combines AI generation, art selection, cart review, and reselfie — internal states (loading, art selection, cart) without extra navigations; reselfie is an inline overlay.catalog_renderer_config, including media-managed preview/clean outputs and background-mask reuse./cart deep link; admins triage remaining carts in zooly-stats. See Abandoned Cart Recovery.apps/zooly-merch/ is a thin Vite wrapper. All React code lives in packages/merch/client/ (@zooly/merch-client) — 15 page routes, 22 components, 6 hooks, MerchContext for state management. Styled with DM Sans font and --merch-* CSS custom properties.
20 Next.js API routes (thin wrappers) handling campaign config, session management, image upload/verification, AI generation, art candidate selection, mockup rendering, pricing, payment, and order completion.
@zooly/merch-srv — 25 service files covering AI art generation, image processing pipeline, order creation, email delivery, lifecycle FSM, and analytics tracking.
@zooly/srv-stripe-payment handles merch payment processing: createMerchPaymentIntent for PI creation with audit trail and idempotency, and completePaymentFromClient for server-side payment verification and revenue distribution.
V2 campaign builder with URL-routed tabs (Setup, Design, Simulation, Translation, Benchmark). Uses Zustand for state management. The Design tab supports a 3-level hierarchy: Design (base settings) → Product Variation → Demographic Variation, with config merging at each level.
The Benchmark tab (/benchmark) mounts @zooly/merch-benchmark-client for AI model/prompt comparison runs through the production generation pipeline. See Image Generation Benchmark.
25 Drizzle tables across two schema files, 19 enums, 14 access files. Campaign data is normalized into satellite tables (branding, studio, legal, config, copy). Designs support a 3-level hierarchy with config inheritance. Covers campaigns, products, sessions, selfies, cart items, designs, generation cache, orders, analytics, tracking, AI models, and audit logs.
| Domain | App | Purpose |
|---|---|---|
merch.zooly.ai | reverse proxy to app.zooly.ai/merch-app | Production merch |
localhost:3008 | Vite dev server | Local development |
localhost:3004 | zooly-app | Backend API |
Fan browser (Vite SPA, port 3008)
| fetch() with CORS
zooly-app API routes (port 3004)
| delegates to @zooly/merch-srv + @zooly/srv-stripe-payment
PostgreSQL (merch_* + stripe_payments tables)
| S3 (media), FAL.AI (generation), Stripe (payments), SendGrid (email)