Guía de desarrollo.
El estándar técnico, visual y cultural que define cómo se construye software en cerouno. Para los que entran, los que se quedan y los que se preguntan por qué importan los detalles.
Cultura.
No buscamos decirte lo que quieres escuchar. Priorizamos el feedback honesto, directo y realista. Nuestro software se usa en entornos de alta presión y debe funcionar de manera impecable.
El estándar cerouno.#
No envíes código que “hace lo que se pidió”. Envía código del que estés orgulloso, con interacciones refinadas, pensando en el camarero que lo usará un viernes por la noche con el restaurante lleno.
-
01Los detalles invisibles se acumulan
Si el usuario no nota un detalle, lo hicimos bien. La suma de estados hover correctos, animaciones fluidas y tipografía perfecta crea una interfaz que se siente premium sin que el usuario sepa explicar por qué.
-
02El buen gusto se entrena
No hagas que “simplemente funcione”. Estudia por qué las mejores interfaces se sienten bien. Haz ingeniería inversa de las interacciones. La curiosidad es parte del oficio.
-
03Feedback realista
Las revisiones de código y diseño usan tablas Antes / Después / Por qué. Si algo se ve como plantilla SaaS genérica o hecho por IA, se rechaza y se rehace. Sin diplomacia innecesaria.
-
04El usuario manda, no el desarrollador
Diseñamos para el cajero a las 9pm, no para nosotros en un escritorio limpio. Touch targets enormes, contrastes altos, latencia cero en lo que se repite.
Las dos verticales.#
Nuestros productos viven en dos mundos con requisitos opuestos. Tratarlos igual es la receta para que ambos fallen.
Plataformas escalables
Arquitectura multi-tenant, gestión de roles y permisos, facturación recurrente impecable. Dashboards densos en datos con jerarquía clara, onboarding intuitivo, cero complejidad innecesaria.
Entornos caóticos
Los restaurantes son ruido, prisa y pantallas con grasa. El software debe reducir el estrés, no aumentarlo. POS ridículamente rápido, menús QR mobile-first, integración WhatsApp directa.
Productos activos.#
- POSPunto de venta
Cero animaciones en acciones repetitivas. Atajos de teclado en todo. Offline-first. La latencia es el enemigo.
- LumoraInventario
Mermas, recetas y costos reales. Sabes cuánto te cuesta cada plato antes de cobrarlo.
- QartaMenú QR
Mobile-first, carga en 3G, sin login. El cliente escanea, ordena, paga. Pedidos por WhatsApp a la cocina.
- FudiApp de delivery
GPS en tiempo real, múltiples pedidos por viaje, rutas optimizadas. Sin pánico en hora pico.
- TasquesSistema escolar
Calificaciones, asistencia y boletines MINERD. Roles para profesores, gestión y dirección.
Caldera.
Nuestro sistema visual. Alto contraste, formas sólidas, legibilidad extrema. El 90% de la interfaz es neutro. El color es estratégico, nunca decorativo.
Paleta.#
Siete tokens. Ni uno más sin justificación escrita. El naranja digital es sagrado: solo para llamados a la acción y superficies que deben gritar.
| Token | HEX | Rol |
|---|---|---|
| Basalt Canvas | #e2e2df | Fondo base. Apaga el estrés visual. |
| Ash White | #f7f6f2 | Superficies de tarjetas y contenedores. |
| Abyssal Ink | #070607 | Texto principal y bordes fuertes. Nunca #000. |
| Pure White | #ffffff | Solo texto sobre fondos oscuros e inputs. |
| Digital Orange | #fc5000 | CTA. Único color que exige atención. |
| Cyber Violet | #524ae9 | Acento decorativo. Nunca texto ni UI principal. |
| Pixel Glare | #f5f28e | Resaltados y patrones sutiles. |
Tipografía.#
Display · PP Neue Corp Compact Ultrabold
Sustituto vía Google Fonts: Bebas Neue. Voz autoritaria, letras apretadas (letter-spacing: 0.02em), peso ultra. Para encabezados y números de impacto.
Body · DM Sans
Sustituto: Inter. Limpia, geométrica, legible incluso en pantallas con grasa. Para cuerpo, inputs, navegación.
Morfología.#
Solidez amigable. Bordes generosos. Padding amplio. Todo pensado para pantallas táctiles de POS y móviles.
40px
border-radius en tarjetas y contenedores.
100px
forma de píldora en formularios.
800px
píldora perfecta. CTA en naranja.
Espaciado.
Padding amplio de 40px en cards. 16–24px en componentes interiores. Nunca menos de 10px entre elementos interactivos. La densidad cómoda es parte del estándar Caldera.
Motion.#
Antes de animar algo, pregúntate con qué frecuencia lo verá el usuario. La respuesta dicta la decisión.
| Frecuencia | Decisión |
|---|---|
| 100+ veces/día (cobrar en POS, atajos) | Cero animación. Jamás. |
| Decenas/día (hovers, navegación de listas) | Eliminar o reducir drásticamente. |
| Ocasional (modales, dropdowns, toasts) | Animación estándar rápida. |
| Rara vez (onboarding, confirmaciones) | Permitido celebrar (delight). |
Reglas técnicas.
- ≤300Duración máxima en ms
Un dropdown de 180ms se siente más responsivo que uno de 400ms. Bajo techo, no piso.
- OutEasing por defecto
Nunca
ease-inen UI. Rápido al inicio, suave al final. Curvas personalizadas, no las débiles del navegador. - .95Escala inicial mínima
Nunca animes desde
scale(0). Nada en el mundo real aparece de la nada. Inicia enscale(0.95) opacity:0. - .97Estado :active de botones
Todos los botones llevan
transform: scale(0.97)en:active. Si tu PR no lo trae, será rechazado. - CSSTransitions sobre keyframes
Para elementos dinámicos que el usuario interrumpe. Las transitions retargetean suave; los keyframes reinician desde cero.
Curvas oficiales.
/* Caldera easings */ --ease-out: cubic-bezier(0.23, 1, 0.32, 1); --ease-out-q: cubic-bezier(0.25, 1, 0.5, 1); --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
Prohibiciones absolutas.#
Sí
- Fondos tintados o iconos claros para destacar.
- Énfasis con peso tipográfico, no con color.
- Alternativas inline antes que modales.
- Naranja digital reservado para CTAs.
- Touch targets ≥ 44px en POS y móvil.
- Estados
:active,:focus-visible,:disabled.
No
- Bordes laterales de color (side-stripe).
- Texto con degradados.
- Modales como primera opción.
- Plantilla métrica genérica de SaaS.
- El azul por defecto del navegador en enlaces.
- Sombras decorativas o glassmorphism por reflejo.
Código.
El código se lee diez veces más de lo que se escribe. Optimiza para el desarrollador que va a abrir este archivo en seis meses con el restaurante caído y treinta minutos para arreglarlo.
Stack oficial.#
Decidimos una vez, no en cada proyecto. La consistencia entre proyectos hace que cambiar de contexto sea barato.
- FEReact + Vite
Componentes funcionales con Hooks. Sin clases. Vite por velocidad de dev server.
- UITailwind CSS
Configurado con tokens Caldera en
tailwind.config.js.darkMode: 'class'donde aplique. - DBSupabase
Default. Postgres + Auth + Realtime + Edge Functions. Firebase solo si hay razón concreta.
- RLSRow Level Security siempre
Multi-tenant sin RLS es un incidente de seguridad esperando. Política por tabla, sin excepciones.
- JSTypeScript en sistemas nuevos
JS vanilla solo para landings o prototipos rápidos. Backend siempre tipado.
- PKGpnpm
Lockfile commiteado. Versiones exactas en dependencias críticas.
Convenciones.#
Nombres.
| Tipo | Convención | Ejemplo |
|---|---|---|
| Componentes | PascalCase | AddressAutocomplete.jsx |
| Hooks | useCamelCase | useRealtimeOrders.js |
| Utilidades | camelCase | formatPhoneRD.js |
| Tablas Supabase | snake_case plural | orders, order_items |
| Variables CSS | --kebab-case | --color-digital-orange |
Estructura de carpetas.
// Proyecto cerouno estándar src/ ├── components/ // reutilizables, sin lógica de negocio ├── features/ // agrupado por dominio (orders, inventory) ├── hooks/ // custom hooks compartidos ├── lib/ // supabase, fetch wrappers, utils ├── pages/ // rutas (o app/ en Next) └── styles/ // tokens, globals
Antes / Después.
El formato de revisión es siempre tabla. No vale “esto está mal”, vale qué cambia y por qué.
| Antes | Después | Por qué |
|---|---|---|
transition: all 300ms |
transition: transform 200ms var(--ease-out) |
Especificar la propiedad. all dispara animaciones que no controlas. |
transform: scale(0) |
scale(0.95); opacity: 0 |
Nada en el mundo real aparece de la nada. |
| Modal para confirmar borrado | Botón con hold-to-delete 2s | El modal interrumpe el flujo. La acción deliberada lo reemplaza. |
Botón sin :active |
:active { transform: scale(0.97) } |
Los botones deben sentirse responsivos a la presión. |
| Query Supabase en cada render | React Query + cache de 30s | El POS no puede depender de queries en cada clic. |
color: #000 |
color: var(--color-abyssal-ink) |
Sin tokens no hay sistema. Sin sistema no hay consistencia. |
Git y Pull Requests.#
Branches.
- mainProducción
Protegida. Solo merge desde PR aprobado.
- devIntegración
Donde se mergea trabajo en curso. Despliega al entorno de staging.
- feat/Features
Una rama por feature. Vida corta.
feat/multi-order-driver. - fix/Bugs
fix/cierre-totals-overflow. Descriptivo, nofix/bug.
Commits.
Conventional Commits. El historial es documentación.
feat(pos): atajo de teclado F2 para cobrar fix(kome): RLS faltante en panel_pedidos refactor(maps): extraer AddressAutocomplete a componente style(lumora): aplicar tokens Caldera al sidebar docs(readme): instrucciones de setup local
PR checklist.
Si tu PR no cumple esto, no se revisa.
Obligatorio
- Descripción con el “por qué”, no solo el “qué”.
- Screenshots o video del cambio si toca UI.
- Antes / Después en cambios visuales.
- Botones con
:active scale(0.97). - Migración SQL si toca esquema.
- Sin
console.logen producción.
Rechazo automático
- Side-stripe borders en tarjetas.
- Texto con
background-clip: text. - Animaciones > 300ms en UI repetitiva.
ease-inen cualquier elemento de UI.- Hex hardcodeado en lugar de tokens.
- Componentes sin estados
:disabledo:focus-visible.
Rendimiento real.#
No optimices a ciegas. Mide. Pero hay no negociables.
- 3GMenús QR cargan en 3G
Lighthouse mobile ≥ 90. Sin esto, el cliente final cierra la pestaña.
- OffPOS offline-first
Cobrar no puede depender de la red. Cola local, sync cuando vuelva.
- 100Acción del POS ≤ 100ms
De clic a feedback visual. Si tarda más, el cajero pierde confianza.
- LzyLazy loading por defecto
Rutas, imágenes, componentes pesados.
React.lazy+Suspense.
Accesibilidad.#
En el mundo real de los restaurantes hay ruido, prisa y pantallas con grasa. No es accesibilidad por diversidad, es accesibilidad por realidad operativa.
- 4.5Contraste mínimo WCAG AA
Texto sobre fondo. Más alto en POS por las pantallas sucias.
- 44Touch target ≥ 44×44 px
En POS y QR. Dedos grandes con prisa no apuntan fino.
- ⌨Navegable por teclado
Especialmente el POS. Atajos para todo lo repetitivo.
- A11yLectores de pantalla en SaaS
aria-labelen iconos sueltos,rolecorrecto en regiones.
Deploy.
Desplegar es la mitad del trabajo. Un feature que funciona en local pero rompe en producción no existe. Procesos boring, ejecución impecable.
Entornos.#
- DevLocal
Cada dev con su
.env.local. Supabase project propio o branch. Datos seed. - StgStaging
Auto-deploy desde
dev. Datos de prueba realistas. Aquí prueba el cliente. - PrdProducción
Auto-deploy desde
main. Manual approval en cambios de schema. Backups diarios.
Hosting.#
Hostinger + SPA
npm run build, sube el dist/ con .htaccess para fallback de rutas. Económico, confiable para clientes pequeños.
Vercel o Netlify
Previews por PR, CDN global, edge functions. Cuando el cliente paga por escala, pagamos por velocidad.
Release checklist.#
No se mergea a main sin pasar esto. Sin excepciones, ni para hotfixes.
- 01Build pasa sin warnings
Warning de hoy es bug de producción mañana.
- 02Probado en staging por el cliente
O por un dev distinto al que escribió el código.
- 03Migraciones aplicadas en orden
SQL versionado. Nada manual en la consola de Supabase.
- 04Variables de entorno verificadas
Keys de Stripe, Supabase, WhatsApp. Las equivocadas son incidentes silenciosos.
- 05Rollback plan documentado
Si esto falla a las 2am, ¿cómo volvemos atrás? Tiene que estar escrito antes del deploy.
- 06Smoke test post-deploy
Cinco minutos verificando los flujos críticos. No te vayas a dormir sin esto.
Observabilidad.#
Si no lo mides, no existe. Lo que rompe en producción nadie te lo va a reportar a tiempo.
- ErrSentry o equivalente
En todos los productos en producción. Alertas a Slack/WhatsApp para errores recurrentes.
- LatMétricas de latencia
P95 de endpoints críticos. POS endpoint > 200ms es una alerta.
- DBSupabase logs y slow queries
Revisión semanal. Una query lenta a las 12pm el viernes tumba el restaurante.
- UXFeedback directo del cliente
Canal de WhatsApp con cada cliente. Lo que se quejan vale más que cualquier dashboard.
Seguridad mínima.#
Siempre
- RLS habilitado en toda tabla de Supabase.
- Service role key solo en backend / Edge Functions.
- Validación de inputs en cliente y servidor.
- HTTPS obligatorio. Sin excepciones.
- Secrets en variables de entorno, nunca en repo.
- Backups automáticos verificados mensualmente.
Jamás
- Service role key en el bundle frontend.
- Credenciales commiteadas, ni “temporalmente”.
- SQL raw con concatenación de strings.
- Confiar en validación solo del lado cliente.
- Compartir credenciales por WhatsApp o email.
- Asumir que un cliente “no va a hackear su propio sistema”.
No envíes código.
Envía obra.
Esta guía existe porque creemos que el oficio importa. Si tienes una mejor manera de hacer algo, proponla. Esto se mejora con uso.