Architecture
System Overview

System Overview

Whole-platform map for Eziseller (EziSeller). Audience: new dev with Node/React experience, no Eziseller context. Every other KB page links back here.

1. Overview

Eziseller (EziSeller) is a multi-channel e-commerce order management platform for small and mid-size merchants in India. A single merchant ("store") can receive orders from a manual dashboard, a public catalog checkout, WhatsApp Business conversations, or Instagram DMs — all of which funnel into one unified Order pipeline with invoicing (GST), inventory, and Shiprocket-backed fulfillment. The platform is built as a split deployment: a Next.js 14 App Router frontend on Vercel and a standalone Express/TypeScript API on Azure App Service, with a shared PostgreSQL database accessed via Prisma. Subscriptions (Razorpay) gate features, and the super-admin portal sits on top of the same API with impersonation support.

2. Architecture

CORS on the API is locked to FRONTEND_URL (backend/server.ts:L61-L64), so browsers never talk to Azure directly in production — they go through Vercel's rewrite. Meta webhooks are the one inbound exception and land on an unauthenticated /webhooks/meta path (backend/server.ts:L130).

3. Data model

Fifty-plus Prisma models organized in clusters. See schema.prisma for the full list.

Model groups: auth/tenancy (User, Store — schema.prisma:L20-L110), catalog (Product, ProductVariant — L316-L400), orders (Order, DraftOrder, OrderItem, Fulfillment — L401-L630), shipping (ShippingProvider, Shipment — L673-L810), messaging (WhatsApp/Instagram credentials, templates, message logs — L814-L1210), billing (Plan, UserSubscription, SubscriptionPayment — L1367-L1490), notifications and audit (L1314-L1570).

4. Key flows

4.1 Request lifecycle (/api/*)

The rewrite rule is in next.config.js:L10-L17. The maintenance-mode short-circuit and the middleware stack are in backend/server.ts:L71-L91.

4.2 Cross-system: WhatsApp order → invoice → shipping label

5. Lifecycle / state machine

6. Key files

7. Env vars & config

Two boundaries: root .env.local for frontend (only NEXT_PUBLIC_* values ship to the browser) and backend/.env for the API. See .env.example for the full list.

VarScopePurposeWhat breaks
NEXT_PUBLIC_API_URLFETarget of /api/* rewriteAll API calls 404 in prod
FRONTEND_URLBECORS allowlistBrowser requests blocked
DATABASE_URLBEPostgres connection stringServer crashes on boot
JWT_SECRETBESigns access + refresh tokensAll sessions invalid
MAINTENANCE_MODEBEBlocks /api/* with 503
NEXT_PUBLIC_MAINTENANCE_MODEFERedirects all pages to /maintenance
CLOUDINARY_*BEImage + PDF storageUploads fail
WHATSAPP_*, INSTAGRAM_*BEMeta Graph API creds (global fallback; per-user creds stored in DB)Webhook verify fails
RAZORPAY_*BESubscription billingCheckout + webhook break

8. Gotchas & troubleshooting

  • Issue: Users are logged out after every backend deploy → Cause: refresh tokens live in an in-process Set (backend/routes/auth.ts:L69), which resets on restart → Fix: users re-login; long-term, move to DB or Redis.
  • Issue: Frontend spams /api/auth/refreshCause: access tokens expire in 1 minute; every stale request triggers a refresh. This is intentional but surprising in dev.
  • Issue: A brute-force attack on /api/orders isn't rate-limited → Cause: express-rate-limit is only wired into auth.ts (backend/routes/auth.ts:L26-L54), not globally. Relies on Azure's front-door limits.
  • Issue: Maintenance mode only partly works → Cause: it's two independent toggles — MAINTENANCE_MODE (backend 503s) and NEXT_PUBLIC_MAINTENANCE_MODE (frontend redirect). Flip both together.
  • Issue: Staff user can't see data → Cause: multi-tenancy uses User.ownerId; queries must scope by owner. OWNER has a 1:1 Store; STAFF inherits via ownerId.
  • Issue: Meta webhook 401s → Cause: CORS isn't the problem — /webhooks/meta is mounted without /api prefix (backend/server.ts:L130) to satisfy Meta's signature checks. Don't move it under /api/*.

9. Extension points

  • New order channel: add a route under backend/routes/, funnel into DraftOrder (not Order directly) so the merchant can review. Reuse lib/draft-order-service.ts and lib/ai-parser.ts.
  • New external integration: put the client in backend/lib/, credentials per-user in a new Prisma model (pattern: WhatsAppUserCredentials, InstagramUserCredentials), webhook route under backend/routes/.
  • New gated feature: add plan flag to Plan model, enforce with middleware/subscription.ts on the route.
  • New background job: add to backend/schedulers/ (cron) or backend/jobs/ (one-shot); wire into server.ts shutdown hooks.

10. Related docs