✍️ Generado con escritura-markdown-mermaid · CULTIVA IA Productividad
✅ Build passing 🔒 MIT License 🧪 Beta cerrada

MesaOS

SaaS B2B para gestión integral de restaurantes — reservas, caja, cocina, proveedores y analítica en una sola plataforma.

El único sistema que cierra el bucle completo: del comensal a la cocina, de la cocina a la caja, de la caja al proveedor.

📅 Actualizado: 18 jun 2026 👥 Equipo: 4 personas 🏢 3 restaurantes piloto 🌍 Madrid

🚀 Quick start

Requisitos previos

RequisitoVersión mínimaVerificar
Node.js≥ 20.0node --version
PostgreSQL≥ 15psql --version
Redis≥ 7.0redis-cli --version
pnpm≥ 8.0pnpm --version

Instalar y arrancar

# Clonar el repositorio
git clone https://github.com/mesaos-hq/mesaos.git
cd mesaos

# Instalar dependencias (workspace monorepo)
pnpm install

# Configurar variables de entorno
cp .env.example .env
# Edita .env con tus valores (ver sección Configuración)

# Aplicar migraciones de base de datos
pnpm db:migrate

# Arrancar en modo desarrollo
pnpm dev
✅ Verificación Visita http://localhost:3000 — deberías ver el panel de login.
Backend health: curl http://localhost:4000/health{"status":"ok","version":"0.4.2"}

🏗️ Arquitectura

MesaOS sigue una arquitectura monorepo multi-paquete con frontend desacoplado del backend. El frontend (Next.js) se despliega en Vercel; el backend (Fastify) y la base de datos (PostgreSQL + Redis) viven en Railway. La autenticación la gestiona Clerk y las notificaciones en tiempo real usan Supabase Realtime para sincronizar el panel de cocina sin polling.

📐 Diagrama — Arquitectura del sistema
flowchart TB accTitle: MesaOS System Architecture accDescr: High-level architecture showing frontend on Vercel, backend API on Railway, PostgreSQL database, Redis cache, Clerk auth, Stripe payments, and Supabase Realtime for kitchen panel sync. client(["👤 Comensal
(web / QR)"]) staff(["👨‍🍳 Staff
(TPV / tablet)"]) subgraph vercel ["☁️ Vercel"] next["⚛️ Next.js 14
Frontend"] end subgraph railway ["🚂 Railway"] api["⚡ Fastify API
Node.js 20"] db[("🐘 PostgreSQL 15
Base de datos")] cache[("⚡ Redis 7
Caché + sesiones")] end subgraph external ["🔌 Servicios externos"] clerk["🔐 Clerk
Auth"] stripe["💳 Stripe
Pagos"] supa["🟢 Supabase
Realtime"] end kitchen["🍳 Panel Cocina
(tablet)"] client --> next staff --> next next --> api next --> clerk api --> db api --> cache api --> stripe api --> supa supa -.->|"WebSocket"| kitchen classDef fe fill:#1e3a5f,stroke:#38bdf8,stroke-width:2px,color:#e2e8f0 classDef be fill:#14532d,stroke:#4ade80,stroke-width:2px,color:#e2e8f0 classDef ext fill:#3b1f5f,stroke:#818cf8,stroke-width:2px,color:#e2e8f0 classDef user fill:#292524,stroke:#78716c,stroke-width:2px,color:#e2e8f0 class next fe class api,db,cache be class clerk,stripe,supa ext class client,staff,kitchen user

Componentes clave

ComponenteFunciónTecnologíaDespliegue
FrontendUI del comensal, TPV, panel de gestiónNext.js 14 + TypeScriptVercel
API CoreLógica de negocio, endpoints RESTFastify + ZodRailway
Base de datosPedidos, menús, clientes, stockPostgreSQL 15 + Drizzle ORMRailway
CachéSesiones, menús en caliente, rate limitRedis 7 (Upstash)Railway / Upstash
Panel cocinaTickets en tiempo real, estado pedidosNext.js + Supabase RealtimeVercel
AuthLogin, roles (admin, camarero, cocina)ClerkSaaS externo
PagosCobro en mesa, facturación, reembolsosStripeSaaS externo

🔄 Flujo de un pedido

Desde que un comensal escanea el QR hasta que el ticket aparece en pantalla de cocina, el sistema ejecuta 7 pasos sincronizados en menos de 400 ms. El panel de cocina recibe el ticket vía WebSocket (Supabase Realtime) sin necesidad de refresco manual.

🔄 Diagrama — Secuencia de pedido (comensal → cocina)
sequenceDiagram accTitle: MesaOS Order Flow Comensal to Kitchen accDescr: Sequence showing a customer scanning QR code, selecting items, the API validating stock in Redis, saving the order to PostgreSQL, and pushing the ticket to the kitchen panel via Supabase Realtime WebSocket. participant C as 👤 Comensal participant FE as ⚛️ Next.js participant API as ⚡ API Fastify participant R as ⚡ Redis participant DB as 🐘 PostgreSQL participant RT as 🟢 Supabase RT participant K as 🍳 Cocina C->>FE: Escanea QR mesa #12 FE->>API: GET /menu?restaurantId=r01 API->>R: GET menu:r01 (caché 5min) R-->>API: HIT — menú JSON API-->>FE: 200 Menú actual FE-->>C: Muestra carta digital C->>FE: Selecciona 2 platos + confirma FE->>API: POST /orders {mesa:12, items:[...]} API->>R: DECR stock:item_id (atomic) R-->>API: Stock OK API->>DB: INSERT orders + order_items DB-->>API: order_id = ord_8472 API->>RT: PUBLISH channel:kitchen:r01 RT-->>K: 🔔 WebSocket push ticket API-->>FE: 201 {orderId: ord_8472} FE-->>C: ✅ Pedido confirmado — ETA 18 min

⚙️ Configuración

Variables de entorno

Variable Requerida Ejemplo Descripción
DATABASE_URL postgresql://... Cadena de conexión PostgreSQL (Railway la provee automáticamente)
REDIS_URL redis://localhost:6379 URL de Redis para caché y sesiones
CLERK_SECRET_KEY sk_live_... Clave secreta de Clerk para verificar tokens JWT
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY pk_live_... Clave pública de Clerk (expuesta en frontend)
STRIPE_SECRET_KEY sk_live_... Clave secreta Stripe para procesar pagos
STRIPE_WEBHOOK_SECRET whsec_... Secreto para verificar webhooks de Stripe
SUPABASE_URL https://xyz.supabase.co URL del proyecto Supabase (Realtime)
SUPABASE_ANON_KEY eyJ... Clave pública Supabase para suscripciones Realtime
LOG_LEVEL no info Verbosidad de logs: debug, info, warn, error
PORT no 4000 Puerto del servidor Fastify (Railway lo asigna automáticamente)
SENTRY_DSN no https://...@sentry.io/... DSN de Sentry para error tracking (solo producción)
⚠️ Seguridad Nunca comitas el archivo .env al repositorio. Usa .env.example (sin valores reales) para documentar las variables. Las claves de producción viven únicamente en el dashboard de Railway y Vercel.

📅 Roadmap Q3 2026

El Q3 cubre la salida de beta cerrada a lanzamiento público con 3 hitos principales: estabilización de la plataforma, nuevas funciones para proveedores y el sistema de analítica avanzada.

📅 Diagrama — Gantt Roadmap Q3 2026
gantt accTitle: MesaOS Q3 2026 Roadmap accDescr: Project timeline showing three phases: platform stabilization in July, supplier features in August, and analytics plus public launch in September 2026. dateFormat YYYY-MM-DD axisFormat %d %b section 🔧 Estabilización Refactor capa de auth (Clerk v5) :done, auth, 2026-07-01, 10d Migraciones DB + índices optimizados :done, db, 2026-07-05, 7d Suite de tests E2E (Playwright) :active, e2e, 2026-07-10, 14d Load testing (Artillery) — 500 rps : load, 2026-07-20, 5d section 🏪 Módulo Proveedores Diseño UX flujo de pedido a proveedor :done, ux_p, 2026-07-15, 7d API proveedores + webhooks :active, api_p, 2026-07-22, 12d Frontend módulo compras : fe_p, 2026-08-01, 10d Integración factura electrónica (FACeB2B): fac, 2026-08-10, 8d section 📊 Analítica avanzada Pipeline ETL PostgreSQL → ClickHouse : etl, 2026-08-05, 12d Dashboard analítica (Recharts) : dash, 2026-08-15, 14d Exportación PDF informes mensuales : pdf, 2026-08-28, 7d section 🚀 Lanzamiento público Beta pública (50 restaurantes) : beta, 2026-09-01, 14d Ajustes post-feedback : feed, 2026-09-10, 7d GA release v1.0.0 :milestone, ga, 2026-09-22, 1d

Estado actual de milestones

MilestoneFecha objetivoEstadoPropietario
Refactor auth Clerk v511 jul 2026✅ Completado@sara
Suite E2E Playwright24 jul 2026🔄 En curso@miguel
API proveedores3 ago 2026🔄 En curso@carlos
Pipeline ETL ClickHouse17 ago 2026⏳ Pendiente@carlos
Beta pública 50 restaurantes1 sep 2026⏳ Pendiente@all
GA v1.0.022 sep 2026⏳ Pendiente@all

📁 Estructura del repositorio

mesaos/
├── apps/
│   ├── web/              # Next.js 14 — frontend principal
│   │   ├── app/          # App Router (layouts, pages, api routes)
│   │   ├── components/   # Componentes React reutilizables
│   │   └── lib/          # Hooks, utils, cliente API
│   └── kitchen/          # Next.js — panel cocina (Supabase RT)
├── packages/
│   ├── api/              # Fastify — servidor API REST
│   │   ├── src/routes/   # Handlers de endpoints
│   │   ├── src/services/ # Lógica de negocio
│   │   └── src/db/       # Drizzle schema + migrations
│   ├── db/               # Drizzle ORM shared schema
│   └── types/            # Tipos TypeScript compartidos
├── tests/
│   ├── e2e/              # Playwright — tests end-to-end
│   └── load/             # Artillery — tests de carga
├── .env.example
├── pnpm-workspace.yaml
└── turbo.json            # Turborepo pipeline

🔧 Troubleshooting

"Cannot connect to database" al arrancar

Causa: PostgreSQL no está corriendo o la variable DATABASE_URL es incorrecta.

Solución 1. Verifica que PostgreSQL corre: pg_isready -h localhost
2. Revisa DATABASE_URL en tu .env
3. Comprueba que la base de datos existe: psql $DATABASE_URL -c "\l"

El panel de cocina no recibe actualizaciones en tiempo real

Causa: Variables de Supabase mal configuradas o la URL del proyecto es incorrecta.

Solución Verifica SUPABASE_URL y SUPABASE_ANON_KEY. Asegúrate de que Realtime está activado en el dashboard de Supabase para la tabla orders.

Error 401 en todas las peticiones a la API

Causa: CLERK_SECRET_KEY no configurada o expirada.

Solución Regenera la clave en dashboard.clerk.com y actualiza la variable en Railway.

🤝 Contribuir

# Fork y clone
git clone https://github.com/TU-FORK/mesaos.git

# Instalar con dependencias de dev
pnpm install

# Crear rama desde main
git checkout -b feature/tu-feature

# Tests antes de push (obligatorio)
pnpm test && pnpm lint

Abre un PR con descripción clara. Cada PR requiere: tests que pasen, lint sin errores y descripción del cambio. Ver CONTRIBUTING.md para el proceso completo.

Referencias

  1. Next.js 14 App Router — Documentación oficial del App Router y Server Components.
  2. Fastify — Framework web para Node.js con bajo overhead y alta velocidad.
  3. Drizzle ORM — ORM TypeScript-first para PostgreSQL con migraciones tipadas.
  4. Supabase Realtime — Guía de suscripciones a cambios en tablas PostgreSQL vía WebSocket.
  5. Clerk — Documentación de autenticación y gestión de usuarios.

Generado con la skill escritura-markdown-mermaid · CULTIVA IA Productividad · 18 jun 2026