{
  "documento": {
    "tipo": "hoja-de-datos",
    "parte": "M25",
    "revision": "2026.08",
    "medido": "2026-08-17",
    "idioma": "es",
    "canonica": "https://www.m25.com.ar/",
    "metodo": "Método: contado por par nombre y correo, agrupando 5 identidades de autor. No por correo solo: una de las cuentas es compartida con otras personas y un bot.",
    "alternativas": {
      "es": "https://www.m25.com.ar/index.json",
      "en": "https://www.m25.com.ar/en/index.json"
    }
  },
  "enlaces": {
    "html": "https://www.m25.com.ar/",
    "llms": "https://www.m25.com.ar/llms.txt",
    "json": "https://www.m25.com.ar/index.json",
    "rss": "https://www.m25.com.ar/rss.xml",
    "cv": "https://www.m25.com.ar/cv-mauro-venticinque-2026.08.pdf",
    "alternativo": "https://www.m25.com.ar/en"
  },
  "persona": {
    "nombre": "Mauro Venticinque",
    "titulo": "Frontend Developer",
    "ubicacion": "San Miguel de Tucumán, Tucumán, AR",
    "tz": "UTC−3",
    "email": "mauro25qe@gmail.com",
    "telefono": "+543816160976",
    "github": "https://github.com/VenticinqueMauro",
    "linkedin": "https://www.linkedin.com/in/mauro-venticinque",
    "cv": "https://www.m25.com.ar/cv-mauro-venticinque-2026.08.pdf",
    "idiomas": [
      "es",
      "en"
    ]
  },
  "stack": [
    "React",
    "TypeScript",
    "Next.js",
    "Astro",
    "VTEX IO",
    "Node",
    "Cloudflare Workers",
    "PostgreSQL",
    "GraphQL",
    "MCP"
  ],
  "escala": {
    "repos": 44,
    "commits": 4559,
    "commitsSinMerges": 3498,
    "archivosClaudeMd": 28,
    "metodo": "git rev-list sobre 44 repos · 5 identidades de autor agrupadas"
  },
  "estadoActual": [
    {
      "ref": "T-01",
      "desde": "2023-04",
      "hasta": null,
      "organizacion": "Red Clover",
      "lugar": "AR",
      "rol": "Frontend Developer VTEX",
      "alcance": "26 repos · 1.365 commits",
      "verificado": "26 repos con git: 6 apps de producto, 2 de tooling, 18 de cliente"
    },
    {
      "ref": "T-02",
      "desde": "2024-12",
      "hasta": null,
      "organizacion": "BCome",
      "lugar": "Barcelona, remoto",
      "rol": "Lead Frontend Web Developer",
      "alcance": "4 repos · 2.474 commits",
      "verificado": "último commit propio 2026-08-13"
    },
    {
      "ref": "T-03",
      "desde": "2024-03",
      "hasta": "2026-02",
      "organizacion": "Tendencia de Noticias",
      "lugar": "Tucumán",
      "rol": "Full-Stack, freelance",
      "alcance": "cerrado · Next.js 14 · MongoDB",
      "verificado": "sin repo local: dato declarado, no medido"
    }
  ],
  "caracteristicas": [
    {
      "ref": "3.1",
      "texto": "1.702 de los 5.246 commits del frontend de BCome son míos. Soy el autor número uno de 26, en un repositorio que empezó en marzo de 2021 y al que entré en diciembre de 2024.",
      "verificado": "2026-08-17 · primer commit 2021-03-15 · 422 .tsx · 163 .ts"
    },
    {
      "ref": "3.2",
      "texto": "Dirijo la migración de ese frontend a React 18.3.1, Vite 7.1.6 y Tailwind 4.1.17, con Bootstrap 4.6.2 todavía adentro. Para que convivan, Tailwind entra con Preflight desactivado y sólo se importan sus capas de tema y utilidades, no el paquete completo. La clase border pelada no sirve: Bootstrap la pisa con !important.",
      "verificado": "Deuda medida antes de empezar: 1.342 estilos inline, 367 colores hex únicos, app.scss de 499 líneas"
    },
    {
      "ref": "3.3",
      "texto": "Publiqué shopify-insights-mcp en npm con licencia MIT: un servidor MCP de 10 herramientas que no devuelve datos de Shopify sino lecturas. En vez de «tenés 45.000 en ventas», responde «tenés 45.000, un 12% menos que el mes pasado».",
      "verificado": "v1.1.0 en npm · @modelcontextprotocol/sdk · Admin GraphQL · stdio"
    },
    {
      "ref": "3.4",
      "texto": "bcome.biz: 95 de 95 commits. Saqué el sitio de WordPress a Astro 6.1.10 con 58 redirects escritos a mano, porque @astrojs/sitemap sólo empareja rutas idénticas y nuestros slugs están traducidos.",
      "verificado": "58 entradas en vercel.json · 0 rewrites"
    }
  ],
  "modos": [
    {
      "ref": "2.1",
      "empleo": "Full-time remoto, en relación de dependencia o contrato.",
      "freelance": "Un proyecto a la vez. Alcance cerrado o retainer mensual."
    },
    {
      "ref": "2.2",
      "empleo": "UTC−3. Solapo la jornada completa con Barcelona y con la costa este de Estados Unidos.",
      "freelance": "UTC−3, Tucumán. Facturo en Argentina."
    },
    {
      "ref": "2.3",
      "empleo": "Me hago cargo del frontend entero y respondo por él: arquitectura, permisos por rol y por plan, performance, deploy.",
      "freelance": "El producto entero: frontend, backend, base de datos e infraestructura."
    },
    {
      "ref": "2.4",
      "empleo": "En BCome son 422 componentes React sobre un repositorio de 2021, con Bootstrap 4 y Tailwind 4 conviviendo mientras dura la migración que dirijo.",
      "freelance": "Sostuve dos años solo un portal de noticias en Next.js 14 y MongoDB, con el tráfico creciendo. Publiqué un servidor MCP en npm con licencia MIT."
    },
    {
      "ref": "2.5",
      "empleo": "Español nativo. Inglés técnico escrito y de reuniones.",
      "freelance": "Escribo el alcance y las decisiones antes que el código. Si el alcance no se puede escribir, no tomo el proyecto."
    }
  ],
  "disponibilidad": {
    "medido": "2026-08-17",
    "texto": "Tomo un proyecto freelance a la vez. Para empleo, escucho propuestas remotas."
  },
  "limites": {
    "noHago": [
      "Identidad de marca",
      "Apps nativas",
      "WordPress",
      "SEO desligado del código"
    ],
    "fueraDeRango": [
      "Rediseños sin acceso al dato real",
      "Plazos fijados antes de definir el alcance",
      "«Hacelo como el de la competencia» sin una decisión de producto detrás"
    ]
  },
  "practica": {
    "plugins": 3,
    "skills": 13,
    "skillsPorPlugin": {
      "vtex-io-standards": 9,
      "korusuite-integrations": 3,
      "faststore-standards": 1
    },
    "hooks": 5,
    "comandos": 2,
    "lineas": 5732,
    "commits": 57,
    "skillsOficialesVtex": 40,
    "repo": "Red-Clover-Consultoria/vtex-io-claude-marketplace",
    "verificado": "medido con pnpm medir · .md + hooks .js del plugin = 5.732"
  },
  "proyectos": [
    {
      "ref": "A-01",
      "slug": "shopify-insights-mcp",
      "ficha": "https://www.m25.com.ar/proyectos/shopify-insights-mcp",
      "titulo": "shopify-insights-mcp",
      "resumen": "Servidor MCP que no devuelve datos de Shopify sino lecturas. Publicado en npm con licencia MIT.",
      "tipo": "producto",
      "plataforma": "MCP · npm",
      "anio": 2026,
      "rol": "Autor",
      "cliente": null,
      "stack": [
        "TypeScript",
        "@modelcontextprotocol/sdk",
        "Shopify Admin GraphQL",
        "Zod",
        "Vitest"
      ],
      "metricas": [
        {
          "label": "Herramientas",
          "valor": "10 tools",
          "metodo": "contadas en src/tools"
        },
        {
          "label": "Licencia",
          "valor": "MIT"
        },
        {
          "label": "Versión",
          "valor": "1.1.0",
          "metodo": "npm view shopify-insights-mcp version"
        }
      ],
      "url": null,
      "repo": null,
      "npm": "https://www.npmjs.com/package/shopify-insights-mcp",
      "estado": "vigente",
      "ia": "Los diez esquemas de entrada y sus tests los escribí con Claude Code. La decisión de qué comparación hace útil a cada herramienta, no.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-02",
      "slug": "bcome-frontend",
      "ficha": "https://www.m25.com.ar/proyectos/bcome-frontend",
      "titulo": "BCome — plataforma",
      "resumen": "Lead frontend de una plataforma de circularidad: la app principal, el panel de administración y el widget que se embebe en tiendas de clientes.",
      "tipo": "empleo",
      "plataforma": "React 18",
      "anio": "2024→",
      "rol": "Lead Frontend Web Developer",
      "cliente": "BCome · Barcelona, remoto",
      "stack": [
        "React 18.3.1",
        "TypeScript",
        "Vite 7.1.6",
        "Tailwind 4.1.17",
        "Bootstrap 4.6.2",
        "i18next",
        "Node 22"
      ],
      "metricas": [
        {
          "label": "Commits propios",
          "valor": "1.702 de 5.246",
          "metodo": "git log agrupando 2 identidades de autor"
        },
        {
          "label": "Componentes",
          "valor": "422 .tsx",
          "metodo": "git ls-files"
        },
        {
          "label": "Autor",
          "valor": "1.º de 26"
        },
        {
          "label": "Admin",
          "valor": "563 commits",
          "metodo": "repo aparte, React 17"
        },
        {
          "label": "Widget embebido",
          "valor": "114 commits",
          "metodo": "repo client-extension"
        }
      ],
      "url": null,
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "Las cinco reglas de convivencia entre Bootstrap y Tailwind las escribí después de romperlas, y quedaron en el CLAUDE.md del repositorio para que el agente no las rompa de nuevo.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-09",
      "slug": "bcome-biz",
      "ficha": "https://www.m25.com.ar/proyectos/bcome-biz",
      "titulo": "bcome.biz",
      "resumen": "El sitio público de BCome, sacado de WordPress a Astro. Bilingüe con slugs traducidos, 25 páginas y 71 componentes. Autor único.",
      "tipo": "empleo",
      "plataforma": "Astro 6",
      "anio": 2026,
      "rol": "Autor único",
      "cliente": "BCome · Barcelona, remoto",
      "stack": [
        "Astro 6.1.10",
        "Tailwind 4 (@tailwindcss/vite)",
        "TypeScript",
        "vanilla-cookieconsent",
        "Vercel"
      ],
      "metricas": [
        {
          "label": "Commits propios",
          "valor": "95 de 95",
          "metodo": "git log, único autor"
        },
        {
          "label": "Páginas",
          "valor": "25 páginas",
          "metodo": "git ls-files sobre src/pages"
        },
        {
          "label": "Componentes",
          "valor": "71 componentes"
        },
        {
          "label": "Redirects",
          "valor": "58 redirects",
          "metodo": "entradas en vercel.json, 0 rewrites"
        }
      ],
      "url": "https://bcome.biz",
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "Las 25 páginas y sus dos idiomas los armé con Claude Code contra el Figma. Lo que no delegué fue el mapa de redirects: 58 URLs viejas que si se rompen cuestan tráfico real, y eso se revisa a mano una por una.",
      "impacto": null,
      "captura": {
        "ref": "A-09",
        "url": "https://bcome.biz",
        "ancho": 1440,
        "alto": 900,
        "escala": 2,
        "fecha": "2026-08-18",
        "bytes": 163450
      },
      "traducida": true
    },
    {
      "ref": "A-03",
      "slug": "koru-shipday",
      "ficha": "https://www.m25.com.ar/proyectos/koru-shipday",
      "titulo": "Koru Shipday",
      "resumen": "Integración logística entre VTEX y Shipday: carga masiva de tarifas, envío de órdenes y actualización de tracking. App nativa del Admin de VTEX.",
      "tipo": "producto",
      "plataforma": "VTEX IO",
      "anio": 2026,
      "rol": "Autor",
      "cliente": "Koru Suite · producto propio de la agencia",
      "stack": [
        "TypeScript",
        "React",
        "VTEX IO node 7.x",
        "VTEX IO react 3.x",
        "VBase",
        "Vitest"
      ],
      "metricas": [
        {
          "label": "Casos de test",
          "valor": "391 tests",
          "metodo": "bloques it/test en 37 archivos"
        },
        {
          "label": "Commits propios",
          "valor": "111 de 111"
        },
        {
          "label": "Código",
          "valor": "17.562 líneas",
          "metodo": "git ls-files ts/tsx/js, sin node_modules ni dist"
        }
      ],
      "url": null,
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "Los 391 tests los escribí con Claude Code contra los contratos reales de la API, no contra mocks inventados. Los contratos los leí yo primero.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-14",
      "slug": "catalogo-boost",
      "ficha": "https://www.m25.com.ar/proyectos/catalogo-boost",
      "titulo": "Catálogo Boost",
      "resumen": "ABM masivo del catálogo VTEX desde Excel: categorías con árbol y drag & drop, marcas, imágenes por SKU y visibilidad programada por cron.",
      "tipo": "producto",
      "plataforma": "VTEX IO",
      "anio": 2026,
      "rol": "Autor",
      "cliente": "Koru Suite · producto propio de la agencia",
      "stack": [
        "TypeScript",
        "React",
        "VTEX IO node 7.x",
        "VTEX IO react 3.x",
        "vtex.styleguide",
        "VBase"
      ],
      "metricas": [
        {
          "label": "Código",
          "valor": "6.855 líneas",
          "metodo": "git ls-files ts/tsx, sin node_modules ni dist"
        },
        {
          "label": "Commits propios",
          "valor": "28 de 28"
        },
        {
          "label": "Casos de test",
          "valor": "39 tests"
        }
      ],
      "url": null,
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "El parser de Excel y sus casos borde los escribí con Claude Code contra planillas reales de cliente, que es donde aparecen las filas que ningún ejemplo de documentación tiene.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-04",
      "slug": "koru-power-seller",
      "ficha": "https://www.m25.com.ar/proyectos/koru-power-seller",
      "titulo": "Koru Power Seller",
      "resumen": "Social selling para vendedores de tiendas VTEX. Marca blanca y multitenant: un solo deploy sirve a todos los retailers, cada uno con su marca y sus credenciales.",
      "tipo": "producto",
      "plataforma": "Cloudflare Workers",
      "anio": 2026,
      "rol": "Autor",
      "cliente": "Koru Suite · producto propio de la agencia",
      "stack": [
        "TypeScript",
        "React",
        "Cloudflare Pages",
        "D1",
        "KV",
        "VTEX Catalog",
        "VTEX OMS",
        "Master Data"
      ],
      "metricas": [
        {
          "label": "Código",
          "valor": "10.382 líneas",
          "metodo": "git ls-files ts/tsx, sin node_modules ni dist"
        },
        {
          "label": "Commits propios",
          "valor": "105 de 105"
        },
        {
          "label": "Casos de test",
          "valor": "90"
        }
      ],
      "url": null,
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "El login de dos pasos lo diseñé yo. Los 90 tests de resolución de tenant los escribí con Claude Code, porque son combinatoria y ahí la máquina no se aburre.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-15",
      "slug": "pickup-cleaner",
      "ficha": "https://www.m25.com.ar/proyectos/pickup-cleaner",
      "titulo": "Pickup Cleaner",
      "resumen": "Gestión masiva de puntos de retiro VTEX: limpieza por radio geográfico con Haversine, borrado programado idempotente e importación desde planilla.",
      "tipo": "producto",
      "plataforma": "VTEX IO",
      "anio": 2026,
      "rol": "Autor",
      "cliente": "Koru Suite · producto propio de la agencia",
      "stack": [
        "TypeScript",
        "React",
        "VTEX IO node 7.x",
        "Logistics API",
        "VBase",
        "Vitest"
      ],
      "metricas": [
        {
          "label": "Código",
          "valor": "5.085 líneas",
          "metodo": "git ls-files ts/tsx, sin node_modules ni dist"
        },
        {
          "label": "Commits propios",
          "valor": "21 de 21"
        },
        {
          "label": "Casos de test",
          "valor": "77 tests"
        }
      ],
      "url": null,
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "Los 77 tests de la lógica geográfica los escribí con Claude Code. La decisión de hacer backup antes de cada borrado no salió de un test: salió de imaginar la llamada del cliente.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-05",
      "slug": "madernoa",
      "ficha": "https://www.m25.com.ar/proyectos/madernoa",
      "titulo": "Madernoa",
      "resumen": "Materiales para arquitectura y construcción del NOA. Landing en Astro, bot de WhatsApp y un servidor MCP que le da el catálogo al bot.",
      "tipo": "freelance",
      "plataforma": "Astro · Cloudflare",
      "anio": 2026,
      "rol": "Full-stack, end to end",
      "cliente": "Madernoa · Tucumán",
      "stack": [
        "Astro 5",
        "CSS nativo (oklch)",
        "Cloudflare Workers",
        "Supabase Postgres",
        "Hyperdrive",
        "pg_trgm",
        "Zod"
      ],
      "metricas": [
        {
          "label": "Commits landing",
          "valor": "32 commits"
        },
        {
          "label": "Commits MCP",
          "valor": "46 commits"
        }
      ],
      "url": "https://madernoa.com",
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "La ingesta de Excel a Postgres y la búsqueda con tolerancia a tildes las escribí con Claude Code contra el catálogo real del cliente, no contra datos de prueba.",
      "impacto": null,
      "captura": {
        "ref": "A-05",
        "url": "https://madernoa.com",
        "ancho": 1440,
        "alto": 900,
        "escala": 2,
        "fecha": "2026-08-18",
        "bytes": 182372
      },
      "traducida": true
    },
    {
      "ref": "A-10",
      "slug": "freijoarquitectos",
      "ficha": "https://www.m25.com.ar/proyectos/freijoarquitectos",
      "titulo": "Freijo Arquitectos",
      "resumen": "Sitio de un estudio de arquitectura contemporánea minimalista. La obra manda: el sitio es un contenedor que no compite con ella.",
      "tipo": "freelance",
      "plataforma": "Astro 5",
      "anio": 2026,
      "rol": "Full-stack, end to end",
      "cliente": "Estudio de arquitectura · Argentina",
      "stack": [
        "Astro 5.15.7",
        "Swiper 12",
        "TypeScript",
        "CSS nativo"
      ],
      "metricas": [
        {
          "label": "Commits propios",
          "valor": "42 de 42",
          "metodo": "git log, único autor"
        },
        {
          "label": "Código",
          "valor": "4.847 líneas",
          "metodo": "git ls-files astro/ts"
        },
        {
          "label": "Componentes",
          "valor": "10 componentes"
        }
      ],
      "url": "https://www.freijoarquitectos.com",
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": null,
      "impacto": null,
      "captura": {
        "ref": "A-10",
        "url": "https://www.freijoarquitectos.com",
        "ancho": 1440,
        "alto": 900,
        "escala": 2,
        "fecha": "2026-08-18",
        "bytes": 869834
      },
      "traducida": true
    },
    {
      "ref": "A-06",
      "slug": "pabloranea",
      "ficha": "https://www.m25.com.ar/proyectos/pabloranea",
      "titulo": "Pablo Ranea",
      "resumen": "Sitio de un chef y sommelier que trabaja en varios países. Catálogo de experiencias gastronómicas, agenda y contacto.",
      "tipo": "freelance",
      "plataforma": "Next.js",
      "anio": 2025,
      "rol": "Full-stack, end to end",
      "cliente": "Chef y sommelier · internacional",
      "stack": [
        "Next.js",
        "React",
        "NextUI",
        "Framer Motion",
        "Embla Carousel",
        "Vercel"
      ],
      "metricas": [
        {
          "label": "Commits propios",
          "valor": "256 de 256",
          "metodo": "git log, único autor"
        },
        {
          "label": "Autoría",
          "valor": "100%",
          "metodo": "sin otros autores en el historial"
        }
      ],
      "url": "https://pabloranea.com",
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": null,
      "impacto": null,
      "captura": {
        "ref": "A-06",
        "url": "https://pabloranea.com/es",
        "ancho": 1440,
        "alto": 900,
        "escala": 2,
        "fecha": "2026-08-18",
        "bytes": 475694
      },
      "traducida": true
    },
    {
      "ref": "A-11",
      "slug": "waldhaus",
      "ficha": "https://www.m25.com.ar/proyectos/waldhaus",
      "titulo": "Waldhaus Residences",
      "resumen": "Sitio de un desarrollo inmobiliario en San Pablo, Tucumán. Una sola página: el recorrido de venta es lineal y la navegación no debía competir con él.",
      "tipo": "freelance",
      "plataforma": "Next.js",
      "anio": 2025,
      "rol": "Full-stack, end to end",
      "cliente": "Coletti Construcciones · Tucumán",
      "stack": [
        "Next.js",
        "React",
        "Headless UI",
        "Framer Motion",
        "react-scroll",
        "react-countup",
        "Vercel"
      ],
      "metricas": [
        {
          "label": "Commits propios",
          "valor": "42 de 42",
          "metodo": "git log, único autor"
        },
        {
          "label": "Código",
          "valor": "1.682 líneas",
          "metodo": "git ls-files tsx/ts"
        },
        {
          "label": "Componentes",
          "valor": "8 componentes"
        }
      ],
      "url": "https://waldhaus.ar",
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": null,
      "impacto": null,
      "captura": {
        "ref": "A-11",
        "url": "https://waldhaus.ar",
        "ancho": 1440,
        "alto": 900,
        "escala": 2,
        "fecha": "2026-08-18",
        "bytes": 432830
      },
      "traducida": true
    },
    {
      "ref": "A-07",
      "slug": "marketplace-claude",
      "ficha": "https://www.m25.com.ar/proyectos/marketplace-claude",
      "titulo": "Marketplace de Claude Code del equipo",
      "resumen": "Marketplace privado de Claude Code para el equipo de VTEX de la agencia. Tres plugins que llevan metodología y guardarraíles, no conocimiento de plataforma.",
      "tipo": "tooling",
      "plataforma": "Claude Code",
      "anio": 2026,
      "rol": "Autor y mantenedor",
      "cliente": "Red Clover · equipo de VTEX",
      "stack": [
        "Markdown",
        "Node (hooks)",
        "node --test",
        "JSON Schema"
      ],
      "metricas": [
        {
          "label": "Plugins",
          "valor": "3 plugins"
        },
        {
          "label": "Skills propias",
          "valor": "13 skills"
        },
        {
          "label": "Hooks",
          "valor": "5"
        },
        {
          "label": "Líneas",
          "valor": "5.732",
          "metodo": "5.220 de .md + 480 de hooks .js"
        },
        {
          "label": "Commits propios",
          "valor": "57 de 57"
        }
      ],
      "url": null,
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "Es un proyecto sobre cómo uso Claude Code, escrito con Claude Code. La contradicción de eso es real y por eso existe el comando que verifica que las skills no afirmen cosas que el código ya desmintió.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-08",
      "slug": "prospea",
      "ficha": "https://www.m25.com.ar/proyectos/prospea",
      "titulo": "Prospea",
      "resumen": "Generación de leads B2B por geolocalización y categoría de negocio, sobre la API de Google Places.",
      "tipo": "freelance",
      "plataforma": "Next.js",
      "anio": 2026,
      "rol": "Full-stack",
      "cliente": null,
      "stack": [
        "Next.js",
        "TypeScript",
        "Prisma",
        "Auth.js",
        "Radix UI",
        "Anthropic SDK",
        "Google Places API",
        "Jest"
      ],
      "metricas": [
        {
          "label": "Commits propios",
          "valor": "144 de 274",
          "metodo": "git log agrupando 2 identidades de autor"
        },
        {
          "label": "Cobertura",
          "valor": "umbrales por ruta",
          "metodo": "jest.config.js, de 3% a 78% según módulo"
        }
      ],
      "url": null,
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": "Usa el SDK de Anthropic en producción para clasificar y redactar. Los umbrales de cobertura son desparejos a propósito y están declarados por ruta.",
      "impacto": null,
      "captura": null,
      "traducida": true
    },
    {
      "ref": "A-12",
      "slug": "tendencia-de-noticias",
      "ficha": "https://www.m25.com.ar/proyectos/tendencia-de-noticias",
      "titulo": "Tendencia de Noticias",
      "resumen": "Portal de noticias de San Miguel de Tucumán. Dos años de desarrollo y mantenimiento, solo, con el tráfico creciendo.",
      "tipo": "freelance",
      "plataforma": "Next.js 14",
      "anio": 2024,
      "rol": "Full-stack, end to end",
      "cliente": "Portal de noticias · Tucumán",
      "stack": [
        "Next.js 14",
        "React",
        "MongoDB",
        "Tailwind CSS",
        "Vercel"
      ],
      "metricas": [
        {
          "label": "Duración",
          "valor": "2024-03 → 2026-02"
        },
        {
          "label": "Métricas de repo",
          "valor": "sin medir",
          "metodo": "no tengo el repositorio en esta máquina"
        }
      ],
      "url": "https://tendenciadenoticias.com.ar",
      "repo": null,
      "npm": null,
      "estado": "vigente",
      "ia": null,
      "impacto": null,
      "captura": {
        "ref": "A-12",
        "url": "https://tendenciadenoticias.com.ar",
        "ancho": 1440,
        "alto": 900,
        "escala": 2,
        "fecha": "2026-08-18",
        "bytes": 208308
      },
      "traducida": true
    },
    {
      "ref": "A-13",
      "slug": "pentimento",
      "ficha": "https://www.m25.com.ar/proyectos/pentimento",
      "titulo": "Pentimento Color Grading",
      "resumen": "Sitio de un estudio de corrección de color para cine, televisión y publicidad. El portafolio es video, así que el sitio se mide en cuánto tarda en mostrarlo.",
      "tipo": "freelance",
      "plataforma": "Next.js",
      "anio": 2025,
      "rol": "Full-stack, end to end",
      "cliente": "Estudio de color grading",
      "stack": [
        "Next.js",
        "React",
        "Vercel"
      ],
      "metricas": [
        {
          "label": "Commits propios",
          "valor": "132 de 132",
          "metodo": "API de GitHub, VenticinqueMauro/pentimiento-app"
        },
        {
          "label": "Lenguaje",
          "valor": "TypeScript"
        }
      ],
      "url": "https://www.pentimento.cc",
      "repo": "https://github.com/VenticinqueMauro/pentimiento-app",
      "npm": null,
      "estado": "vigente",
      "ia": null,
      "impacto": null,
      "captura": {
        "ref": "A-13",
        "url": "https://www.pentimento.cc",
        "ancho": 1440,
        "alto": 900,
        "escala": 2,
        "fecha": "2026-08-18",
        "bytes": 235930
      },
      "traducida": true
    }
  ],
  "notas": [
    {
      "ref": "N-001",
      "titulo": "La marginalia con anchor positioning no se puede hacer accesible",
      "fecha": "2026-08-17",
      "plataforma": "CSS",
      "metodo": "Leído en la especificación y verificado armando las dos versiones"
    },
    {
      "ref": "N-002",
      "titulo": "En YAML, «5.700» es el número 5,7",
      "fecha": "2026-08-17",
      "plataforma": "YAML · Zod",
      "metodo": "Encontrado en producción por un revisor externo, reproducido en el schema"
    }
  ],
  "errata": [
    {
      "ref": "E-02",
      "fecha": "2026-08-17",
      "situacion": "corregido",
      "repo": "m25",
      "causa": "Publiqué este sitio con un conmutador de idioma en el header de todas las páginas apuntando a rutas que no existían. Cada /en/* devolvía 404, y el público al que ese botón le servía era justamente el que buscaba.",
      "guardarrail": "El inglés existe: mismo cuerpo de documento, mismas cifras, prosa escrita aparte. Y el cuerpo pasó a ser un componente compartido por los dos idiomas, así que no puede haber una versión con secciones que la otra no tenga."
    },
    {
      "ref": "E-01",
      "fecha": "2026-07-28",
      "situacion": "corregido",
      "repo": "vtex-io-claude-marketplace",
      "causa": "Mi propia skill de licenciamiento documentó durante meses un fail-open que el boilerplate ya había reemplazado por un stale allow. Cualquiera que siguiera la skill iba a escribir el gate de licencia mal.",
      "guardarrail": "La corrección no fue editar el archivo. Instalé un hook de SessionStart que compara sin red la versión del boilerplate del repo contra la versión fijada en el plugin, y un comando que consulta las tags reales y contrasta el CHANGELOG contra lo que afirman las skills, reportando archivo y línea de los dos lados."
    }
  ],
  "revisiones": [
    {
      "ref": "R-02",
      "revision": "2026.08",
      "fecha": "2026-08-17",
      "cambio": "Reescrito como hoja de datos. Astro 7.2.2, salida estática, dos tipografías, sin librerías de animación."
    },
    {
      "ref": "R-01",
      "revision": "2025.11",
      "fecha": "archivada",
      "cambio": "React 19 en una sola página, Tailwind por CDN y detección por cámara delante del contenido. Dos paletas peleadas y el scroll bloqueado, en el sitio de alguien que dice optimizar performance."
    }
  ]
}