Documentación técnica · DOC-ARQ-01
Arquitectura de Solución
Stack, diagrama de capas, modelo de datos y pipeline CI/CD del marketplace Plazi
Audiencia
CTO · Engineering
2 · Diagrama de capas
Cómo se conecta todo end-to-end
┌─────────────────────────────────────────────────────────────────────┐
│ USUARIO FINAL │
│ 📱 Comprador (mobile/web) 🏪 Vendedor (mobile/web) 🛡 Admin │
└──────────────┬──────────────────────────────┬──────────────────────┘
│ │
┌───────▼────────┐ ┌────────▼─────────┐
│ APP NATIVA │ │ SITIO WEB + │
│ Expo SDK 52 │ │ PWA Next.js 15 │
│ iOS · Android │ │ (React 19) │
│ │ │ │
│ • Push notifs │ │ • PWA /app │
│ • Cámara │ │ • Panel vendedor │
│ • Biométrico │ │ • Admin │
│ • Share WA │ │ • Checkout │
└────────┬───────┘ └────────┬─────────┘
│ │
│ Bearer JWT (mobile) │ Cookies httpOnly (web)
│ ─────────────────► │ ────────────────────►
│ │
┌────────▼──────────────────────────────▼───────────────────┐
│ API REST (Next.js Route Handlers) │
│ │
│ /api/products /api/orders /api/push /api/wishlist │
│ /api/addresses /api/notifications /api/admin/* │
│ │
│ ・ Server Actions (mutations) │
│ ・ Notificaciones inbox + push (best-effort) │
└────────────────────────┬───────────────────────────────────┘
│
│ Service role + RLS
│
┌────────────────────────▼───────────────────────────────────┐
│ SUPABASE (Postgres) │
│ │
│ profiles · sellers · products · product_variants │
│ orders · order_items · reviews · addresses · cities │
│ wishlists · notifications · coupons · outbox_events │
│ │
│ Storage: bucket product-images (público con RLS upload) │
│ Auth: OTP correo (ES256) + sesiones │
└─────────────┬──────────────────────────────┬───────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ WOMPI (pagos) │ │ RESEND (emails) │
│ Nequi · PSE · Card │ │ OTP · órdenes · push │
└──────────────────────────┘ └──────────────────────────┘
Notas del diagrama
- Mobile autentica con Bearer JWT en el header Authorization. La web usa cookies httpOnly de Supabase.
- Server Actions se usan para mutations desde el cliente Next.js (checkout, cambio de status pedido, CRUD producto).
- Notificaciones tienen doble canal: inbox (tabla
notifications) + push nativo (Expo Push API). Best-effort, no bloquea el flujo principal.
- RLS (Row Level Security) protege todas las tablas. Las APIs usan service role solo para operaciones cross-user (notificar a un seller).
DOC-ARQ-01 · Página 2
4 · Flujo end-to-end de compra
De la búsqueda hasta el pago y la notificación
[1] 🔍 Comprador navega catálogo
└─► GET /api/products · SSR con generateMetadata · OG dinámico
[2] 🛒 Agrega al carrito (cookie state)
└─► server action addToCart() · escribe cookie httpOnly
[3] 💳 Checkout /pagar (o mobile /api/orders/place)
├─► verifica auth · hidrata items
├─► calcula subtotal + envío + descuento de cupón (si aplica)
├─► insert en orders + order_items
├─► insert en outbox_events (order.created)
├─► notifySellersNewOrder() · push Expo + inbox notifications
└─► sendOrderConfirmationEmail() via Resend (Wompi confirma async)
[4] 💰 Wompi procesa el pago
└─► webhook → /api/wompi/webhook · actualiza status orden
[5] 📦 Vendedor recibe push y nota en inbox
└─► abre /(panel)/pedidos/[number] · marca como packing/shipped/delivered
[6] 🚚 Status cambia → trigger
├─► insert en outbox_events (order.status_changed)
├─► notifyBuyerOrderStatusInbox() · escribe en notifications
├─► notifyBuyerOrderStatus() · push Expo al comprador
└─► sendOrderStatusEmail() via Resend
[7] ✅ Comprador recibe push, abre el detalle
└─► /order/[number] (mobile) o /app/pedidos/[number] (PWA)
Idempotencia: los triggers de notificación son best-effort (catch silencioso). Si la tabla notifications no existe (migración pendiente), el flujo principal de compra no se interrumpe.
DOC-ARQ-01 · Página 4
5 · Pipeline CI/CD
Del commit a producción
┌──────────────────┐ git push ┌──────────────────┐
│ Desarrollador │ ────────────────►│ GitHub master │
│ (local) │ │ SebasInvent/plazi│
└──────────────────┘ └────────┬─────────┘
│
webhook GitHub │
▼
┌────────────────────────────┐
│ Vercel CI/CD │
│ • pnpm install │
│ • turbo build (filter) │
│ • Next.js build │
│ • Deploy preview/prod │
└─────────────┬──────────────┘
│
┌─────────────▼──────────────┐
│ Producción · Vercel │
│ https://plazi.co │
│ Edge CDN + Fluid Compute │
└────────────────────────────┘
┌────────────────────────────────────────────────────────────┐
│ Mobile (independiente de Vercel) │
│ │
│ Desarrollador → eas-cli build → EAS Cloud → APK/IPA │
│ ↓ │
│ expo.dev (download) │
│ │
│ OTA: eas-cli update --branch preview → user app updates │
└────────────────────────────────────────────────────────────┘
Ramificación
- master · única rama. Cada commit a master → deploy a producción
- Pull requests · generan preview deployment automático (URL única por PR)
- Hotfixes · commit directo a master con tag
fix: en el mensaje
Comandos clave
# Web
pnpm dev # arranca local (Next.js dev)
pnpm build # build de producción
pnpm typecheck # check de tipos web + mobile
# Mobile
pnpm --filter @plazi/mobile dev # Expo dev server
pnpm --filter @plazi/mobile test # 30 smoke tests
eas build --platform android --profile preview # APK Beta
# Deploy
git push origin master # Vercel auto-deploy
Observabilidad
- Vercel Logs · 100% de las invocaciones server (route handlers + server actions)
- outbox_events · audit trail completo en Postgres (visible en
/admin/reportes)
- Vercel Analytics · core web vitals y tráfico (opcional)
DOC-ARQ-01 · Página 5 (final)