Sistemas Kitchco · kit instalable

Tus operadores reportan errores con captura, en un click.

Argos es un botón flotante y un panel de admin que se enchufan a cualquier proyecto Next.js. Adiós al “no anda nada” sin contexto.

4archivos que se copian
1comando para instalarlo
0dependencias de tu UI
olivos.kitchcocenter.com/pedidos/4821

Pedidos de hoy

mié 29 · 14:07
Pedidos hoy
37
En camino
8
Demorados
2
Facturado
$412k
PedidoClienteTotalEstado
#4818M. Duarte$18.400entregado
#4819L. Ferrari$9.250en camino
#4820J. Bravo$26.900en camino
#4821S. Ríos$0trabado
#4822P. Castro$12.100preparando
Confirmando pedido #4821…
🐛

así queda el botón, en todas las pantallas de tu app

El problema

Un error reportado sin contexto es un error que no existe.

El operador ve algo raro, te escribe, y arranca el interrogatorio. Para cuando llegás a entender qué pasó, la pantalla ya cambió y nadie se acuerda de nada.

antes4 idas y vueltas · 20 min
che no anda nada 😤
¿qué pantalla?
la de siempre
¿qué dice el error?
nada, no carga
¿me mandás una foto?
🤳 (foto del monitor, borrosa)

Y todavía no sabés en qué pantalla estaba.

con argos1 click · 8 segundos
No me deja confirmar el pedido, el botón queda girando.
captura adjunta
Fotos
2 adjuntas desde la galería
Pantalla
/pedidos/4821
Proyecto
logistica
Reportó
operador · id 3f9a…
Navegador
Chrome 131 · macOS
Cuándo
hoy, 14:07

Todo eso lo junta Argos solo. El operador solo escribe qué pasó.

Demo en vivo

Apretá el botón. Es el mismo código que corre en producción.

El 🐛 de acá abajo captura de verdad la pantalla falsa de la izquierda, con la misma librería y las mismas opciones que el kit instalado. El reporte aparece en el panel de la derecha.

todo queda en tu navegadorsin backendsin subir nada
tu app
olivos.kitchcocenter.com/pedidos/4821

Pedidos de hoy

mié 29 · 14:07
Pedidos hoy
37
En camino
8
Demorados
2
Facturado
$412k
PedidoClienteTotalEstado
#4818M. Duarte$18.400entregado
#4819L. Ferrari$9.250en camino
#4820J. Bravo$26.900en camino
#4821S. Ríos$0trabado
#4822P. Castro$12.100preparando
Confirmando pedido #4821…
/errores

👁️ Errores reportados

2 sin resolver
sin captura

El total del pedido queda en $0 cuando saco un ítem del carrito.

📦 logistica📄 /pedidos/4821🕐 hace 12 min
sin captura

No me carga la lista de conversaciones, queda el spinner girando.

📦 whatsapp-dashboard📄 /chats🕐 hace 1 h
Cómo funciona

Tres pasos, y ninguno requiere entrenar a nadie.

El flujo entero está pensado para que un operador sin conocimientos técnicos lo use bien la primera vez que lo ve.

  1. 01

    El operador aprieta 🐛

    Un botón flotante siempre visible, en todas las pantallas. No hay que explicarle nada a nadie: si algo está raro, se aprieta.

  2. 02

    Argos captura y pregunta

    Toma la pantalla tal cual se ve (sombras, gradientes, Tailwind v4 incluido), muestra el preview y pide una nota de una línea. Si hace falta, el operador adjunta hasta 5 fotos de su galería.

  3. 03

    Aparece en /errores

    El reporte llega al panel de admin con la captura, la nota y todo el contexto técnico. Lo mirás, lo arreglás, lo marcás resuelto.

Características

Chico por fuera, terco por dentro.

Cada decisión del kit está tomada para que entre en cualquier proyecto sin pelearse con nada de lo que ya tenés.

Captura fiel, sin popup

Usa modern-screenshot (serialización SVG foreignObject). Respeta sombras, oklch y CSS moderno. Nada de pedirle permiso de pantalla al navegador.

Hasta 5 fotos adjuntas

A veces el problema no está en la pantalla: está en la impresora, en el paquete o en la moto. El operador adjunta fotos de su galería y se redimensionan en el navegador antes de subirse.

Autocontenido

El botón lleva sus estilos inline. No depende de tu Tailwind, tu design system ni tu librería de toasts. Entra en cualquier Next.js sin fricción.

Capturas privadas

Van a un bucket privado y se sirven solo a admin con URLs firmadas de 1 hora. Una captura puede tener datos de clientes: se trata como tal.

Aislado por proyecto

Cada proyecto tiene su propia tabla y su propio bucket, en su propia Supabase. Nada se comparte, nada se cruza.

Un comando, y actualizable

node install.mjs ../ruta/al/proyecto copia los cuatro archivos y te imprime los pasos finales. El template es la fuente de verdad: mejorás una vez, re-corrés el instalador y tu argos.config.ts nunca se pisa.

Doble candado

Cualquier usuario logueado puede crear un reporte. Solo admin puede listar, ver capturas y resolver. Se define en tu config, con tu esquema de auth.

Local, Docker y Vercel

Los archivos se copian adentro del proyecto, no se linkean. Lo que corre en tu máquina es exactamente lo que se buildea en producción.

Instalación

Un minuto, cuatro pasos, cero sorpresas.

El instalador copia los archivos adentro del proyecto (no los linkea), así lo que corre en tu máquina es exactamente lo que se buildea en Docker o en Vercel.

Copia los 4 archivos adentro del proyecto y te imprime los pasos finales.

bash · 1 · instalar
cd "Sistemas/Argos"
node install.mjs "../WhatsApp Infra/whatsapp-dashboard"

npm install modern-screenshot

Para actualizar: editás template/ en Sistemas/Argos/ y re-corrés el instalador en cada proyecto. Se re-copian el botón, la API y la página — argos.config.ts nunca se pisa.

Arquitectura

El cliente nunca toca la base.

Todo pasa por la API del servidor, que valida quién sos antes de escribir o leer. La tabla tiene RLS habilitado sin policies: para el navegador, sencillamente no existe.

Navegador del operador

  • error-report-button.tsx
  • modern-screenshot
  • captura + nota
POST

API /api/errors

  • requireUser()
  • requireAdminUser()
  • service role
insert + upload

Supabase del proyecto

  • tabla error_reports
  • bucket privado
  • RLS on · 0 policies

Navegador del admin

  • /errores
  • filtros + lightbox
  • resolver / reabrir
GET · PATCH

Chequeo de admin

  • 401 si no está logueado
  • 403 si no es admin
  • URLs firmadas 1 h
signed url

error-screenshots

  • public: false
  • límite 10 MB
  • path por proyecto

Cada proyecto corre su propia copia de este diagrama, contra su propia Supabase. Nada se comparte entre proyectos — aunque cada reporte guarda el campo project por si algún día querés consolidarlos en un panel único.

Anatomía del kit

Cinco archivos. Ni uno de más.

Clickeá cada uno para ver qué hace y un pedazo del código real que se copia a tu proyecto.

tu-proyecto/
se conserva al actualizar
src/components/error-report-button.tsxse actualiza

Botón fijo abajo a la derecha, visible en todas las pantallas. Al apretarlo captura el body con modern-screenshot, abre un modal con el preview, un campo de nota y un adjuntar fotos (hasta 5, comprimidas en el navegador), y postea a /api/errors. Se auto-excluye de su propia captura con data-error-report-ignore.

error-report-button.tsx
const { domToJpeg } = await import("modern-screenshot");

const dataUrl = await domToJpeg(document.body, {
  quality: 0.7,
  scale: Math.min(window.devicePixelRatio || 1, 1.5),
  backgroundColor: getComputedStyle(document.body).backgroundColor,
  filter: (node) =>
    !(node instanceof HTMLElement &&
      node.hasAttribute("data-error-report-ignore")),
});

// Las fotos de la galería se achican antes de viajar:
// 5 fotos de celular sin tocar son ~40 MB de base64.
const scale = Math.min(1, 1400 / Math.max(sw, sh));
ctx.drawImage(bitmap, 0, 0, w, h);
let out = canvas.toDataURL("image/jpeg", quality);
Seguridad y privacidad

Una captura de pantalla es un dato sensible.

Puede tener el chat de un cliente, un teléfono o un total facturado. Argos la trata como tal desde el primer día.

  • Bucket privado

    Ni las capturas ni las fotos adjuntas se sirven públicas. El bucket se crea con public: false y límite de 10 MB por archivo.

  • URLs firmadas de 1 hora

    Cada vez que un admin abre el panel, la API genera links temporales. Se vencen solos.

  • RLS sin policies

    La tabla tiene Row Level Security habilitado y cero policies: el cliente no puede leerla ni escribirla directo.

  • Todo por service role

    El único camino a los datos es la API del servidor, que valida quién sos antes de tocar nada.

  • Dos niveles de permiso

    Crear un reporte: cualquier usuario logueado. Ver, listar y resolver: solo admin.

  • El botón no se auto-espía

    El botón y el modal llevan data-error-report-ignore, así que jamás aparecen dentro de su propia captura.

route.ts · storage
// El bucket se crea privado la primera vez, solo.
await service.storage.createBucket(BUCKET, {
  public: false,
  fileSizeLimit: 10 * 1024 * 1024,
});

// Y se sirven con un link que se vence solo.
const { data: signed } = await service.storage
  .from(BUCKET)
  .createSignedUrl(report.screenshot_path, 3600);

Si el reporte llega sin captura (porque falló la serialización o pesaba más de 9 MB), se guarda igual con la nota y el contexto. Nunca se pierde un reporte por culpa de la imagen.

En el ecosistema

Dónde está mirando Argos hoy.

Relevado sobre el workspace real: 4 sistemas con Argos vivo y el resto listos para el instalador.

ProyectoEstado
whatsapp-dashboard

La implementación original: acá nació Argos y de acá se extrajo el template. Usa requireOperator / requireAdminOrLocal propios, y la UI va con Tailwind y sonner en vez de estilos inline.

vivo
control-turnos

Fichaje GPS+WiFi con la PWA del operario. El botón lleva props propias (variant, position, hideOn) para convivir con la barra inferior del celu.

vivo
engine-app

Port a JavaScript puro (sin TS, sin src/), con i18n propio y Supabase por REST. Tabla engine_reports y endpoint /api/reports en vez de /api/errors.

port a mano
meta-ads-scheduler

Port a TypeScript vanilla (sin React). Reportes en logs/error-reports.json y las imágenes en disco, servidas por índice. El panel ya está detrás del basic-auth de Traefik, así que no lleva candado propio.

port a mano
logistica

Next.js + Supabase con operadores en la calle: el candidato número uno para el próximo install.

pendiente
kitchco-hq

Dashboard RPG + switchboard. Encaja directo con el instalador.

pendiente
meta-dashboard

Next.js 16. Instalación estándar.

pendiente
sistemas-dashboard · social-hub · kitchcocenter-new

Mismo stack, mismo instalador. Van cuando estén en manos de operadores.

pendiente
Preguntas

Lo que siempre se pregunta.

El instalador asume Next.js con App Router, Supabase y login. Para lo que no encaja se hace un port a mano: el scheduler de Meta Ads tiene uno en TypeScript vanilla, sin React, que guarda los reportes en JSON local en vez de Supabase. Si mejorás el template, ese cambio hay que llevarlo a mano.

Porque html2canvas se rompe con oklch (o sea, con Tailwind v4) y no dibuja bien las sombras. modern-screenshot serializa el DOM a SVG con foreignObject: sale fiel al CSS moderno y no pide permiso de captura de pantalla al navegador.

Hoy no: cada proyecto tiene su tabla y su bucket, a propósito. Pero cada reporte guarda el campo project, así que la consolidación está preparada para el día que la quieras.

Porque muchas veces el problema no está en la pantalla: la impresora no imprime, el paquete llegó roto, el cartel del local está mal. El operador adjunta hasta 5 fotos de su galería y viajan con el mismo reporte, al mismo bucket privado. Se redimensionan a 1400 px y se comprimen en el navegador, así 5 fotos de celular no se convierten en 40 MB de POST.

El modal se abre igual con un aviso, y el reporte se envía solo con la nota y el contexto. Nunca se pierde el reporte por culpa de la captura.

Editás los archivos de template/ y re-corrés node install.mjs en cada proyecto. Se re-copian el botón, la API y la página; tu argos.config.ts queda intacto.

Cuatro archivos y una dependencia. modern-screenshot se carga con import dinámico: recién baja cuando alguien aprieta el botón, no en el bundle inicial.