ai-startup-skills
AI 제품을 만드는 스타트업을 위한 7단계 에이전트 스킬: 검증 → 비즈플랜 → 정책 → 로드쇼 → 고객 확보 → 가격 책정 → 등록
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Iniciativa 1 de Mindlin Developers. Las facturas llegan por Telegram (al bot de facturas; su usuario aparece en la web, pestaña "Subir") o se suben en la web. La IA las lee, las clasifica en una de las tres carpetas del equipo (compras, honorarios de administración, que son las facturas que los socios le hacen a la sociedad, o ventas) y propone los datos como los carga el equipo. Quedan en una cola "Para revisar" en la web; una persona revisa y aprueba. Recién ahí la app agrega la fila en la planilla Administración Contable (compras y honorarios en "Facturación de Egresos (Compras)", ventas en "Facturación de Ingresos (Ventas)") y mueve el PDF a la carpeta de Drive de su categoría, en la subcarpeta del mes. No calcula retenciones (eso es la iniciativa 11).
Qué hay en Drive, qué pestañas de la planilla toca la app y qué falta: docs/mapa.md.
Para ponerla en marcha después de este cambio: docs/puesta-en-marcha.md. La configuración que falta, lista para pegarle a un agente con computer use: docs/configurar-con-computer-use.md.
| Paso | Estado |
|---|---|
| Esqueleto Next.js + TypeScript | Hecho. |
Extractor con IA (lib/invoice/extract.ts) | Hecho. Probado en producción con la API real de Claude y comprobantes sintéticos en imagen y PDF. Falta medir con facturas reales del cliente. |
Controles de CUIT, suma y QR (lib/validation/) | Hecho. Falta leer el QR de la imagen o del PDF. |
Script de evaluación (scripts/eval/) | Hecho y adaptado a la planilla real. Falta correrlo con octubre de 2026 (ver pendientes). |
| Tres categorías y columnas de la planilla real | Hecho (29/10/2026). Auditado contra octubre: ver docs/auditoria-octubre.md. |
| Cola de pendientes, web (revisar, subir, historial) y bot de Telegram | Hecho (29/10/2026). Falta la puesta en marcha: carpetas, script v3, planilla de la cola y variables. |
| Panel de inicio, accesos a la planilla y a Drive, QR de Telegram y cero duplicados | Hecho (29/10/2026). Probado con tests y con capturas en compu y celular, con datos simulados. Falta verlo con datos reales después de la puesta en marcha. |
| Login con Google y lista de mails | Hecho y desplegado en https://mindlin-developers.vercel.app |
| Pantalla de carga, revisión y aprobación | Hecho. Probado de punta a punta con la API real, Drive y la planilla de prueba. |
| Escritura en la planilla y control de duplicados | Hecho. Probado contra la planilla de prueba. |
| Subida de los PDF a Drive | Script publicado, autorizado y conectado a Vercel. Guardado de imagen y PDF verificado en la carpeta de prueba. |
Configuración actual de cada servicio: docs/configuracion.md. Lo que falta: docs/pendientes.md.
Se continúa trabajando en la planilla y carpeta de prueba de [email protected], por decisión del responsable del proyecto el 28/10/2026. La planilla real del cliente todavía no está disponible. Los resultados de las pruebas están en docs/verificacion.md.
npm install
cp .env.example .env.local # completar
npm run dev # app en http://localhost:3000
npm test # tests (sin llamadas a la API)
npm run typecheck
npm run eval -- --dir muestras/2026-10 --mes 2026-10 --decimal punto # ver scripts/eval/README.md
Requiere Node 22 o más nuevo.
Nada de esto va al repo. En local, en .env.local. En Vercel, en Settings > Environment Variables.
| Variable | Para qué | Cuándo hace falta |
|---|---|---|
ANTHROPIC_API_KEY | Llamar a Claude | Ya (extractor y evaluación) |
AUTH_SECRET | Firmar las sesiones de Auth.js (npx auth secret) | Login |
AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET | Cliente OAuth de Google para el login | Login |
ALLOWED_EMAILS | Mails que pueden entrar, separados por coma | Login |
GOOGLE_SERVICE_ACCOUNT_EMAIL, GOOGLE_PRIVATE_KEY | Cuenta de servicio para la planilla. La clave va como en el JSON, con los \n escritos | Planilla |
SHEET_ID | Planilla Administración Contable. Mientras se desarrolla, una copia. | Planilla |
SHEET_TAB_EGRESOS | Pestaña de compras y honorarios. Si no está, se usa SHEET_TAB (el nombre anterior) | Planilla |
SHEET_TAB_INGRESOS | Pestaña de ventas. Sin esto, la app no carga ventas | Ventas |
APPS_SCRIPT_URL, APPS_SCRIPT_SECRET | Script que guarda y ordena los PDF en Drive (apps-script/, versión 2) | Siempre: la cola guarda cada archivo al llegar |
COLA_SHEET_ID | Planilla aparte para la cola y las cuentas de Telegram conectadas. No la de Administración Contable. La app crea sus pestañas ("Cola", "Telegram" y "Candados") | Siempre |
COLA_TAB, COLA_TAB_TELEGRAM, COLA_TAB_CANDADOS | Nombres de esas pestañas. Por defecto, "Cola", "Telegram" y "Candados" | Opcional |
TELEGRAM_API_KEY | Token del bot de Telegram (de BotFather). También se acepta TELEGRAM_BOT_TOKEN | Telegram |
Tomado de mindlindevelopers.com. Los colores y estilos están como variables en app/globals.css:
#D2DA4D (el color del logo) y negro #1A1A1A. Botones principales en lima con texto negro.next/font.--dudoso), un tono distinto del lima para que no se confundan.La auditoría de experiencia y los cambios del recorrido están documentados en docs/auditoria-ux-2026-10-28.md. La bandeja permite buscar y filtrar, revisar un comprobante por vez sin perder ediciones y consultar un historial con búsquedas y estados. Las subidas continúan al cambiar de sección dentro de la app.
public/brand/ y el ícono de la pestaña en app/icon.png, copiados del sitio.Auth.js (next-auth v5) con Google. Solo entran los mails de ALLOWED_EMAILS, y tienen que estar verificados por Google.
auth.ts: configuración. La sesión dura 12 horas. Cada persona puede entrar desde todos los dispositivos y navegadores que quiera, a la vez: cada uno tiene su sesión.proxy.ts: todo pedido sin sesión válida va a /login. La lista se vuelve a mirar en cada pedido, así que sacar un mail de ALLOWED_EMAILS (y volver a desplegar) le corta el acceso a esa persona en el momento, aunque tenga la sesión abierta.requireUser() (lib/auth/session.ts): segunda barrera. Llamarlo al principio de cada página y ruta de API que toque datos.http://localhost:3000/api/auth/callback/googlehttps://<dominio de Vercel>/api/auth/callback/googleAUTH_GOOGLE_ID y AUTH_GOOGLE_SECRET.mindlindevelopersia/factura. Vercel detecta Next.js solo.AUTH_SECRET (generado con npx auth secret), AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET y ALLOWED_EMAILS. ANTHROPIC_API_KEY todavía no hace falta en Vercel.Es lo primero que se ve al entrar (components/Panel.tsx, GET /api/panel, cálculo en lib/panel.ts). Un link de Telegram (/?revisar=<id>) abre directo "Para revisar".
REGISTROS_VIGENCIA_MS), aunque haya varias personas con la web abierta. La aprobación siempre la lee de nuevo.Los botones del panel, los links "fila 230" de la ficha y del historial apuntan a /ir/<destino> (app/ir/[destino]/route.ts, lib/enlaces.ts). Esa ruta pide sesión y recién ahí redirige a Google, así que los links de Google no aparecen en ninguna página. Los links de las carpetas los da el script de Drive desde la versión 3; con la 2, esos botones aparecen grisados con lo que falta.
Lo que la app no puede hacer: una vez que alguien tiene el link de Google (por ejemplo, lo copia de la barra del navegador), Google decide quién lo abre, no la app. Para que solo entre el equipo, la planilla y las carpetas tienen que estar compartidas con acceso general "Restringido" y solo con las cuentas de Google de cada persona (y la cuenta de servicio, en la planilla). Así, aunque el link circule, nadie más lo puede abrir.
Todo comprobante, llegue por donde llegue, pasa por la misma cola (lib/cola/):
POST /api/cola, pestaña "Subir") o por Telegram (POST /api/telegram-webhook). Se guarda enseguida en la carpeta de pendientes de Drive, así no se pierde aunque falle algo después, y entra en la cola con estado "leyendo".components/FichaRevision.tsx): el archivo al lado de los datos editables.
POST /api/cola/<id>/aprobar): se vuelve a controlar duplicados, el PDF se mueve a la carpeta de su categoría y a la subcarpeta del mes ("Facturas Compras Octubre 2026") con el nombre estándar, y se agrega la fila en la planilla. Si algo falla a mitad de camino, el comprobante sigue pendiente y se puede volver a aprobar sin duplicar nada. O se descarta: el archivo va a la papelera de Drive.La cola vive en una pestaña de la planilla COLA_SHEET_ID, una fila por comprobante, con la lectura completa en JSON y columnas legibles (contraparte, comprobante, total, estado). La web la vuelve a consultar cada 20 segundos, así aparece lo que llega por Telegram.
/api/telegram-webhook de la dirección desde la que se toca (tiene que ser la de producción).AUTH_SECRET que vence a la hora; al tocar "Iniciar", esa cuenta de Telegram queda conectada al mail con el que entró a la web (pestaña "Telegram" de la planilla de la cola).ALLOWED_EMAILS. A las demás les contesta cómo conectarse y no guarda nada de lo que mandaron.secretoWebhook en lib/telegram/api.ts): el webhook rechaza las que no lo traen. Es la única ruta fuera del login (proxy.ts).Nada se carga dos veces aunque dos pedidos lleguen al mismo tiempo (dos personas que aprueban a la vez, la misma foto mandada dos veces seguidas, Telegram que reintenta un mensaje). Para eso hay candados (lib/cola/candados.ts) en la pestaña "Candados" de la planilla de la cola: cada intento agrega una fila y gana la primera vigente. Sheets aplica los agregados de a uno, así que de dos intentos simultáneos gana exactamente uno.
Aprobar toma un candado por comprobante y otro por factura (proveedor, tipo y número), y con el candado vuelve a leer la cola y la planilla. El que llega segundo recibe "Otra persona está aprobando esta factura".
Aprobación cortada: antes de escribir la fila, el comprobante queda "aprobando". Si Sheets falla o la función se corta, la ficha lo muestra con "Completar la aprobación": al tocarlo, si la fila ya está en la planilla se completa con esa fila, y si no, se agrega. No se puede descartar a mitad de camino, porque el archivo ya puede estar en su carpeta.
Google con mucho tráfico: si Sheets responde que se agotó la cuota, la app espera y reintenta. Las lecturas también se reintentan ante un corte; un agregado de fila no, porque podría haberse hecho (lib/google/reintentos.ts).
El mismo archivo (misma huella SHA-256) no entra dos veces en la cola, venga por donde venga: no se guarda ni se lee de nuevo, y se le dice a quien lo mandó dónde está ("llegó el 29/10, 14:32 y está para revisar", "ya está cargado en la fila 230"). Si el anterior se descartó, sí se puede volver a mandar.
El mismo comprobante en otro archivo (una foto y después el PDF): se lee, pero la ficha avisa que ya lo habían mandado y el bot también. Se reconoce por proveedor, tipo, punto de venta, número y total.
Ya cargado en la planilla (a mano o desde la app): la ficha lo dice con la fila y no se deja aprobar.
Si falta configurar algo, la web muestra qué (lib/estado.ts, GET /api/estado): la clave de Anthropic (la prueba contra la API), las planillas y sus pestañas (con los nombres que tiene la planilla, para copiarlos), la planilla de la cola, el script de Drive (versión y carpetas) y el bot. También se ve desde "Subir > Revisar la configuración".
lib/invoice/completar.ts. La categoría sale del CUIT del emisor: si es el de Mindlin (config/empresa.json), es una venta; si es el de un socio (la lista socios del mismo archivo), son honorarios; si no, una compra. Los socios, confirmados por el cliente el 29/10/2026, son Matías Mindlin, Michelle Mindlin y Micaela Druck.
El equipo le compra casi siempre a los mismos proveedores, y la planilla ya dice cómo se anota cada uno. Por eso, si el CUIT ya tiene cargas:
config/proveedores.json).La ficha avisa de qué fila tomó los datos. Medido sobre las 218 filas de egresos de la planilla real, con lo cargado antes de cada una: rubro 97%, "corresponde a" 98%, razón social 96% y concepto 95% de aciertos (auditoría).
lib/sheets/. Las columnas son las de la planilla Administración Contable, en el mismo orden (columnas.ts): A a Y en egresos y A a O en ingresos. La app no agrega columnas.
=T-U).=M*0,21, y eso puede diferir en centavos de lo facturado.lib/sheets/registros.ts).COLUMNAS_OPCIONALES en columnas.ts).=, +, - o @ se fuerza a texto, para que una factura no pueda meter una fórmula.Planilla: si el cliente usa Excel, se cambia la implementación.lib/storage/archivos.ts. Los PDF se guardan en Drive a través de un script de Apps Script publicado en la cuenta dueña de las carpetas (ver apps-script/README.md), porque la cuenta de servicio no tiene espacio en un Drive de Gmail.
AAAA-MM-DD Razón social - Tipo N°.pdf; en las ventas, con el cliente en lugar de la razón social. El script crea la subcarpeta si no existe.extractInvoice(file) manda el PDF (como bloque document) o la foto (como bloque image) a claude-opus-5-5 y devuelve los datos del comprobante según el esquema zod de lib/invoice/schema.ts. Lee el emisor y el receptor por separado, así que sirve para compras y para ventas.
output_config.format: la respuesta siempre es un JSON con ese esquema. El esquema se convierte con lib/invoice/json-schema.ts y no con el zodOutputFormat del SDK, porque ese helper pasa los enum a la descripción en vez de dejarlos como restricción.output_config.effort: "low").fallbacks: "default", beta server-side-fallback-2026-07-01): si el modelo rechaza la factura, la API la reintenta con otro modelo. ExtractionResult.fallback indica si pasó.campos_dudosos lo que no pudo leer bien. validateInvoice suma a esa lista los campos que fallan algún control: eso es lo que la pantalla de revisión va a marcar en amarillo.Convenciones de los importes (en lib/invoice/prompt.ts). Las de facturas C y notas de crédito coinciden con la planilla real; las demás, a confirmar con el cliente:
no_gravado.no_gravado.iva_otras, que no es una columna de la planilla.otros_tributos, que tampoco es una columna de la planilla.Concepto, rubro y "corresponde a" siguen cómo carga el equipo (el prompt tiene ejemplos de la planilla):
config/rubros.json: Materiales, Servicios de Terceros, Honorarios Profesionales o Monotributista. Es lo que usa la columna "Rubro / Descripción" y lo que dijo Tadeo en sus notas. La clasificación más fina que armó con GPT (62 proveedores) no está en la planilla, así que no se usa.config/empresa.json).lib/validation/cuit.ts): prefijo válido y dígito verificador (módulo 11), para el emisor y el receptor.lib/validation/sum.ts): neto + no gravado + IVA + percepciones + otros tributos = total, con una tolerancia de $0,05.lib/validation/qr.ts): decodifica la URL https://www.afip.gob.ar/fe/qr/?p=... y compara CUIT, punto de venta, tipo, número, fecha, importe, moneda y CAE. Por ahora recibe el texto del QR: falta leerlo de la imagen o del PDF.