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.
🚀 Quick start
Requisitos previos
| Requisito | Versión mínima | Verificar |
|---|---|---|
| Node.js | ≥ 20.0 | node --version |
| PostgreSQL | ≥ 15 | psql --version |
| Redis | ≥ 7.0 | redis-cli --version |
| pnpm | ≥ 8.0 | pnpm --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
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.
(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
| Componente | Función | Tecnología | Despliegue |
|---|---|---|---|
| Frontend | UI del comensal, TPV, panel de gestión | Next.js 14 + TypeScript | Vercel |
| API Core | Lógica de negocio, endpoints REST | Fastify + Zod | Railway |
| Base de datos | Pedidos, menús, clientes, stock | PostgreSQL 15 + Drizzle ORM | Railway |
| Caché | Sesiones, menús en caliente, rate limit | Redis 7 (Upstash) | Railway / Upstash |
| Panel cocina | Tickets en tiempo real, estado pedidos | Next.js + Supabase Realtime | Vercel |
| Auth | Login, roles (admin, camarero, cocina) | Clerk | SaaS externo |
| Pagos | Cobro en mesa, facturación, reembolsos | Stripe | SaaS 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.
⚙️ Configuración
Variables de entorno
| Variable | Requerida | Ejemplo | Descripción |
|---|---|---|---|
DATABASE_URL |
SÍ | postgresql://... |
Cadena de conexión PostgreSQL (Railway la provee automáticamente) |
REDIS_URL |
SÍ | redis://localhost:6379 |
URL de Redis para caché y sesiones |
CLERK_SECRET_KEY |
SÍ | sk_live_... |
Clave secreta de Clerk para verificar tokens JWT |
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY |
SÍ | pk_live_... |
Clave pública de Clerk (expuesta en frontend) |
STRIPE_SECRET_KEY |
SÍ | sk_live_... |
Clave secreta Stripe para procesar pagos |
STRIPE_WEBHOOK_SECRET |
SÍ | whsec_... |
Secreto para verificar webhooks de Stripe |
SUPABASE_URL |
SÍ | https://xyz.supabase.co |
URL del proyecto Supabase (Realtime) |
SUPABASE_ANON_KEY |
SÍ | 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) |
.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.
Estado actual de milestones
| Milestone | Fecha objetivo | Estado | Propietario |
|---|---|---|---|
| Refactor auth Clerk v5 | 11 jul 2026 | ✅ Completado | @sara |
| Suite E2E Playwright | 24 jul 2026 | 🔄 En curso | @miguel |
| API proveedores | 3 ago 2026 | 🔄 En curso | @carlos |
| Pipeline ETL ClickHouse | 17 ago 2026 | ⏳ Pendiente | @carlos |
| Beta pública 50 restaurantes | 1 sep 2026 | ⏳ Pendiente | @all |
| GA v1.0.0 | 22 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.
pg_isready -h localhost2. Revisa
DATABASE_URL en tu .env3. 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.
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.
🤝 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
- Next.js 14 App Router — Documentación oficial del App Router y Server Components.
- Fastify — Framework web para Node.js con bajo overhead y alta velocidad.
- Drizzle ORM — ORM TypeScript-first para PostgreSQL con migraciones tipadas.
- Supabase Realtime — Guía de suscripciones a cambios en tablas PostgreSQL vía WebSocket.
- Clerk — Documentación de autenticación y gestión de usuarios.
Generado con la skill escritura-markdown-mermaid · CULTIVA IA Productividad · 18 jun 2026