Architecture
Monorepo layout, apps, packages and how data flows through the system
KwadMarket is a pnpm + turborepo monorepo. Three deployable apps share a Prisma database package and a common types package.
Repository layout
Stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 16 (App Router), TanStack Query, react-hook-form + zod, Tailwind, socket.io client |
| API | NestJS (REST, global prefix /api), Passport JWT, class-validator DTOs, Socket.IO gateway |
| Worker | NestJS + BullMQ (Redis), BrightData for scraping |
| Data | PostgreSQL via Prisma, Meilisearch (product search), Redis (queues, sockets), S3-compatible storage (images) |
| Auth | Local email/password + Google + Facebook OAuth; JWT in an HttpOnly cookie set by Next route handlers |
Data flow
- Server components fetch via
apps/web/lib/api/server.ts(serverFetch+ cached helpers). Public data usesrevalidate; authed data isno-store. - Client components call the API through
lib/api/http.ts, which goes through the/api/proxyrewrite so the HttpOnly cookie flows same-origin. Endpoint strings live in exactly onefeatures/*/api.tsper domain. - Real-time: the chat socket lives in
ChatProvider; unread counts are socket-pushed to auser:{id}room. - Scraping:
backowns the catalog and enqueues jobs;scraperconsumes BullMQ jobs, talks to BrightData, and writes onlyScraper*/ScrapedProducttables. Catalog writes (Product,Spec,Shop) stay inback'sProductsService.
App boundary rule
apps/scraper must never import from apps/back/src (and vice versa). Job payload types belong in @marketplace/types, declared once for producer and consumer.
Domain model (core entities)
| Entity | Role |
|---|---|
Product / Spec / Brand / Category | The retail catalog, populated by the scraper + admin |
Shop | A retail listing of a product (price, availability, URL) — powers new-price comparison |
Deal | A user's secondhand listing; links to catalog products via DealProduct; moderated (DRAFT → PENDING → PUBLISHED/DECLINED → SOLD/ARCHIVED/EXPIRED) |
Discussion / Message | Buyer–seller chat per deal, real-time via Socket.IO |
ScrapedProduct | Raw scraper output awaiting review/import into the catalog |
ProductComponent | Parent/component relation for drone builds |
Where things run
| Service | Dev | Notes |
|---|---|---|
| Web | localhost:3000 | Next.js dev server |
| API | localhost:3001 | Global prefix /api |
| PostgreSQL, Redis, Meilisearch | Docker Compose | See root compose files |
| Docs (this site) | localhost:3000 (pnpm --filter docs dev) | Docker: apps/docs/docker-compose.yml maps host port 3002 |