Saltar al contenido
← Volver a proyectos

Apps

Mecateo

Mecateo

POS Restaurante

Sistema POS multi-tenant. Pedidos en tiempo real, pagos, cocina (KDS), menú público y dashboard.

Stack

Capa Tech
Monorepo Turborepo + PNPM workspaces
Backend NestJS 11, Prisma 7, PostgreSQL 16, Socket.IO
Frontend Next.js 16, React 19, TanStack Query v5, Tailwind v4
Auth Better Auth (cookie session httpOnly)
Realtime Socket.IO (path /api/socket.io, namespace /ws)

Contrato /api

Un solo contrato para todo el backend. El cliente del navegador siempre habla con el mismo origen del frontend:

Path Sirve
/api/v1/* REST (orders, products, menu, ...)
/api/auth/* Better Auth (login, sign-in, ...)
/api/socket.io/* WebSocket handshake + polling
/static/* Uploads (imágenes, PDFs)
  • Dev: Next.js rewrites /api/* y /static/*INTERNAL_API_URL (Nest interno).
  • Prod: Dokploy/Traefik rutea /api/* y /static/* → servicio api, resto → servicio web. No hay Nginx en el compose.
  • Server-side (RSC): un único helper getApiBase() (en apps/web/lib/api-base.ts) elige entre /api (browser) y INTERNAL_API_URL + /api (server). Sin URLs hardcoded.

Desarrollo local

Requisitos

  • Node.js ≥ 20
  • PNPM ≥ 9 — npm i -g pnpm@9
  • Docker (para PostgreSQL)

Primera vez

pnpm install
cp .env.example .env                # ajusta secretos si quieres
pnpm db:up                          # tú decides cuándo levantar la DB
pnpm --filter @repo/db db:migrate:dev   # nombra la primera migración "init"
pnpm db:seed

El seed crea organización demo, usuario admin y datos de prueba.

Día a día

pnpm db:up                          # si la DB no está corriendo
pnpm dev                            # Next.js + NestJS en paralelo
Servicio URL
Web http://localhost:3000
API (vía web) http://localhost:3000/api/v1/health
API (directo) http://localhost:3001/api/v1/health
Prisma Studio pnpm db:studiohttp://localhost:5555

El navegador siempre va por /api (mismo origen, cookies same-origin). El acceso directo a :3001 existe solo para debug.

Comandos útiles

pnpm --filter api dev               # solo API
pnpm --filter web dev               # solo Next
pnpm build                          # build de todo
pnpm start                          # corre el build (web + api)
pnpm check-types                    # tsc --noEmit en todos
pnpm lint
pnpm --filter api test

Producción (Dokploy)

Arquitectura

Internet → Dokploy/Traefik (TLS, dominio)
             ├── /api/*      → api    (NestJS :3001)
             ├── /static/*   → api    (NestJS :3001)
             └── /*          → web    (Next.js :3000)
                                       └── SSR/RSC → http://api:3001 (red interna)

Setup

  1. Crear el VPS con Dokploy. Conecta este repo de GitHub.

  2. Crear Compose Application apuntando a infra/docker-compose.prod.yml.

  3. Variables de entorno en Dokploy (no commiteadas):

    # Conexion a tu DB externa (Dokploy service de Postgres, RDS, Supabase, etc.)
    DATABASE_URL=postgresql://USER:PASS@HOST:5432/DBNAME
     
    NODE_ENV=production
    PORT=3001
    BETTER_AUTH_SECRET=<openssl rand -base64 32>
    BETTER_AUTH_URL=https://tudominio.com
    CORS_ORIGINS=https://tudominio.com
    UPLOADS_DIR=/var/app/uploads
    PUBLIC_STATIC_URL=https://tudominio.com/static
    LOG_LEVEL=info

    El compose no levanta Postgres. Apunta DATABASE_URL a la DB que prefieras (otro servicio en Dokploy, RDS, Neon, Supabase, etc.).

  4. Configurar dominios en Dokploy (Traefik labels o UI):

    • web recibe el dominio raíz /.
    • api recibe los path-prefixes /api y /static del mismo dominio.
  5. Migraciones (manual la primera vez):

    docker compose -f infra/docker-compose.prod.yml --profile tools run --rm migrate
    docker compose -f infra/docker-compose.prod.yml --profile tools run --rm seed   # opcional
  6. Deploys — push a main → Dokploy webhook → rebuild automático.

Build / start manual (sin Dokploy)

pnpm build
pnpm start

O via Docker:

docker compose -f infra/docker-compose.prod.yml up -d --build

Sin reverse proxy externo, el navegador necesita llegar a web y este rewritea /apiapi por la red interna de Docker. Expón el puerto del servicio web en el host si vas a probar así.


Estructura del monorepo

restaurant-system/
├── apps/
│   ├── api/        # NestJS — modules en src/modules/
│   └── web/        # Next.js 16 App Router
├── packages/
│   ├── db/         # Prisma schema + migrations + seed
│   ├── shared/     # Zod schemas compartidos
│   ├── auth/       # Better Auth config compartida
│   ├── ui/         # shadcn/ui primitivos
│   └── typescript-config/
└── infra/
    └── docker-compose.{yml,prod.yml}

Roles

Rol Acceso
ADMIN Dashboard, productos, categorías, pagos, settings, pedidos
WAITER Pedidos (crear/editar/entregar), cocina, cobrar
superAdmin /admin global + cualquier /{slug}/...

Solución de problemas

Error Causa Solución
ECONNREFUSED al arrancar el API Postgres no corre pnpm db:up
Llamadas XHR caen en :3001 directo URL hardcoded en lugar de helper Usar getApiBase() o ruta relativa /api/...
WS no conecta Path Socket.IO desincronizado Cliente y server deben usar path: '/api/socket.io'
Cannot find module '@prisma/client' Prisma client no generado pnpm --filter @repo/db db:generate
Invalid env Falta BETTER_AUTH_SECRET (32+) Verifica .env y BETTER_AUTH_SECRET