From 5df91bc281c51fc1107b4e88bbeebbc5ff78c7c5 Mon Sep 17 00:00:00 2001 From: Rodrigo Opalo <206490241+devrodri-com@users.noreply.github.com> Date: Sat, 15 Aug 2026 14:27:51 -0400 Subject: [PATCH 1/2] docs(portfolio): refresh the Magenta case to its verified pre-cutover state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El caso de Imprenta Magenta describía un estado que ya no corresponde al proyecto. Esta actualización alinea la tarjeta y el caso expandido (ES/EN) con lo verificado contra el repositorio y el despliegue vigentes. Correcciones de fondo: - Enlace actualizado a https://magenta-paysandu.vercel.app. El deploy previo (`m5in`) era una versión vieja del sitio. Consolida el cambio de #88. - La imprenta está activa en Paysandú desde 2010; "15 años de trayectoria" era un dato sin respaldo. - Los mockups se generaron con GPT Image 2, no con Sora, y se presentan como recursos del MVP, no como una automatización de runtime. - El contacto es un enlace directo a WhatsApp, no una "WhatsApp API". - Se describe la integración con Resend y la protección con Cloudflare Turnstile en el formulario de presupuesto. - "SEO completo" pasa a ser un contrato SEO pre-cutover: metadata, Open Graph, sitemap y robots controlados por configuración, con la indexación deshabilitada hasta el cutover. El despliegue responde hoy con `X-Robots-Tag: noindex, follow`. - Los bullets de impacto pasan de afirmaciones no medidas ("web rápida y confiable", "menos fricción", "eleva el branding") a resultados demostrables, y ya no presentan e-commerce ni panel administrativo como funciones implementadas. `PortfolioSafety` pinea un sha256 sobre el payload público de cada caso (`key`, `cover`, `actions`, `content`), así que reescribir el contenido mueve ese digest. Se actualiza únicamente el hash de magenta; ningún otro caso se toca. `ServiceCopyRevision` y `Routing` no requirieron cambios: sus assertions cubren la copy de servicios y el título, que quedan igual. Co-Authored-By: Claude Opus 5 --- src/data/portfolio/cases/magenta.ts | 74 ++++++++++++++--------------- src/i18n/en.ts | 2 +- src/i18n/es.ts | 2 +- src/test/PortfolioSafety.test.ts | 2 +- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/data/portfolio/cases/magenta.ts b/src/data/portfolio/cases/magenta.ts index 3cfa305..f4af765 100644 --- a/src/data/portfolio/cases/magenta.ts +++ b/src/data/portfolio/cases/magenta.ts @@ -2,36 +2,36 @@ import { en, es } from "../../../i18n"; import { definePortfolioCase } from "../types"; const stackEs = [ - "Frontend: Next.js 16 (App Router) + TypeScript + TailwindCSS", - "Infraestructura: Vercel (deploy continuo)", - "Optimización SEO: metadata personalizada, OG automáticas, sitemap.xml y robots.txt", - "Automatización: generación de imágenes con IA (Sora/OpenAI)", - "Diseño: mockups personalizados + UI modular", - "Gestión de datos: estructuras centralizadas en /src/data" + "Frontend: Next.js 16 (App Router) + TypeScript + Tailwind CSS", + "Infraestructura: Vercel con despliegue continuo", + "SEO técnico: metadata, Open Graph, sitemap y robots controlados por un gate de indexación hasta el cutover", + "Recursos visuales del MVP: mockups generados con GPT Image 2", + "Gestión de datos: productos y servicios centralizados en src/data" ] as const; const stackEn = [ - "Frontend: Next.js 16 (App Router) + TypeScript + TailwindCSS", - "Infrastructure: Vercel (continuous deploy)", - "SEO optimization: custom metadata, automatic OG, sitemap.xml and robots.txt", - "Automation: AI image generation with Sora/OpenAI", - "Design: custom mockups + modular UI", - "Data management: centralized structures in /src/data" + "Frontend: Next.js 16 (App Router) + TypeScript + Tailwind CSS", + "Infrastructure: Vercel with continuous deployment", + "Technical SEO: metadata, Open Graph, sitemap, and robots controlled by an indexing gate until cutover", + "MVP visual assets: mockups generated with GPT Image 2", + "Data management: products and services centralized in src/data" ] as const; const integrationsEs = [ - "Mockups personalizados generados por IA (Sora)", - "Formularios dinámicos por servicio", - "WhatsApp API para contacto inmediato", + "Formulario dinámico de presupuesto por servicio", + "Cloudflare Turnstile para protección antiabuso", + "Integración con Resend para entrega transaccional por email", + "Enlace directo a WhatsApp", "Mapa de ubicación embebido", - "Carrusel automático de marcas/clientes", - "Favicon y OG card personalizada para redes sociales" + "Carrusel de marcas y clientes", + "Favicon y Open Graph card para redes sociales" ] as const; const integrationsEn = [ - "Custom AI-generated mockups (Sora)", - "Service-based dynamic forms", - "WhatsApp API for instant contact", + "Service-based dynamic quote form", + "Cloudflare Turnstile for abuse protection", + "Resend integration for transactional email delivery", + "Direct WhatsApp link", "Embedded location map", - "Automatic brand/client carousel", - "Custom favicon and OG card for social media" + "Brand and client carousel", + "Favicon and Open Graph card for social sharing" ] as const; export const magentaCase = definePortfolioCase({ @@ -41,7 +41,7 @@ export const magentaCase = definePortfolioCase({ cover: "/img/magenta-cover.png", actions: [ { - href: "https://magenta-paysandu-m5in.vercel.app", + href: "https://magenta-paysandu.vercel.app", label: { es: es.portfolio.magenta.link, en: en.portfolio.magenta.link, @@ -57,7 +57,7 @@ export const magentaCase = definePortfolioCase({ "Next.js" ], details: { - summary: "MVP funcional para una imprenta con 15 años de trayectoria. Incluye catálogo optimizado con mockups generados por IA, formulario dinámico de presupuestos y arquitectura moderna con Next.js 16.", + summary: "MVP público en etapa pre-cutover para una imprenta de Paysandú activa desde 2010. Centraliza productos, servicios y solicitudes de presupuesto en una arquitectura modular construida con Next.js 16.", stack: stackEs, integrations: integrationsEs, challenges: [ @@ -71,15 +71,15 @@ export const magentaCase = definePortfolioCase({ "Catálogo de productos y servicios centralizado en estructuras de datos (src/data).", "Formularios dinámicos basados en reglas por servicio (libretas, tarjetas, afiches, etc.).", "Diseño limpio estilo Apple minimal con foco en claridad y velocidad de acceso.", - "Optimización SEO completa (metadata, OG card, sitemap, robots).", + "Contrato SEO pre-cutover con metadata, Open Graph, sitemap y robots controlados por configuración; la indexación permanece deshabilitada hasta el cutover.", "Deploy automatizado en Vercel con imágenes optimizadas." ], impact: [ - "Web rápida y confiable para un negocio local con mucha competencia.", - "Mejor experiencia de usuario para pedidos de presupuesto (menos fricción).", - "Imagen profesional consistente con la marca Magenta.", - "Catálogo visual con mockups de alta calidad que elevan el branding.", - "Preparado para futuras expansiones: e-commerce, panel administrativo, etc." + "MVP público disponible en Vercel para revisión previa al cutover.", + "Productos, servicios y solicitud de presupuesto reunidos en una experiencia responsive.", + "Flujo de presupuesto con protección Turnstile e integración de entrega por email mediante Resend.", + "Sistema visual coherente con la identidad de Magenta y mockups creados con GPT Image 2.", + "Arquitectura modular preparada para nuevas iteraciones, sin presentar e-commerce ni panel administrativo como funciones implementadas." ], }, }, @@ -91,7 +91,7 @@ export const magentaCase = definePortfolioCase({ "Next.js" ], details: { - summary: "Functional MVP for a print shop with 15 years of experience. Includes an optimized catalog with AI-generated mockups, a dynamic quote form and a modern architecture with Next.js 16.", + summary: "Public pre-cutover MVP for a Paysandú print shop operating since 2010. It centralizes products, services, and quote requests in a modular architecture built with Next.js 16.", stack: stackEn, integrations: integrationsEn, challenges: [ @@ -105,15 +105,15 @@ export const magentaCase = definePortfolioCase({ "Centralized product and service catalog in reusable data structures (src/data).", "Dynamic forms driven by per-service rules (notebooks, cards, posters, etc.).", "Clean Apple-like minimal design focused on clarity and fast access.", - "Full SEO optimization (metadata, OG card, sitemap, robots).", + "Pre-cutover SEO contract with metadata, Open Graph, sitemap, and robots controlled through configuration; indexing remains disabled until cutover.", "Automated deployment on Vercel with optimized images." ], impact: [ - "Fast and reliable website for a local business in a competitive market.", - "Better user experience for quote requests (less friction).", - "Professional image consistent with the Magenta brand.", - "Visual catalog with high-quality mockups that elevate the branding.", - "Ready for future expansions: e-commerce, admin panel, etc." + "Public MVP available on Vercel for pre-cutover review.", + "Products, services, and quote requests brought together in a responsive experience.", + "Quote flow with Turnstile protection and email delivery integrated through Resend.", + "Visual system consistent with the Magenta identity, with mockups created using GPT Image 2.", + "Modular architecture ready for further iterations, without presenting e-commerce or an admin panel as implemented features." ], }, }, diff --git a/src/i18n/en.ts b/src/i18n/en.ts index cfcca3e..801321d 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -434,7 +434,7 @@ export const en = { }, magenta: { title: "Imprenta Magenta · Paysandú, Uruguay", - desc: "Modern print shop specializing in digital printing, offset and food packaging. Optimized catalog, dynamic quote form and full SEO. Functional MVP currently live.", + desc: "Public pre-cutover MVP for Imprenta Magenta, operating in Paysandú since 2010, with a product and service catalog and a Turnstile-protected quote form.", link: "Visit site", }, campings_demo: { diff --git a/src/i18n/es.ts b/src/i18n/es.ts index 6eb4199..fcad7b8 100644 --- a/src/i18n/es.ts +++ b/src/i18n/es.ts @@ -430,7 +430,7 @@ export const es = { }, magenta: { title: "Imprenta Magenta · Paysandú, Uruguay", - desc: "Imprenta moderna especializada en impresión digital, offset y packaging gastronómico. Catálogo optimizado, formulario dinámico y SEO completo. MVP funcional ya activo.", + desc: "MVP público pre-cutover para Imprenta Magenta, activa en Paysandú desde 2010, con catálogo de productos y servicios y formulario de presupuesto protegido con Turnstile.", link: "Ver sitio", }, campings_demo: { diff --git a/src/test/PortfolioSafety.test.ts b/src/test/PortfolioSafety.test.ts index f072e80..f51a67a 100644 --- a/src/test/PortfolioSafety.test.ts +++ b/src/test/PortfolioSafety.test.ts @@ -87,7 +87,7 @@ const expectedPreservedCaseHashes = { zentra: "50082406905123ed80a6eac63745d3a4a27448825990fdc82b7057d41b4d411a", esteban: "643b388f7f34ce4b90e2ba1890b007fef0f2c485694647bf56cc0c04a4c421e4", mutter: "aa118ae6042f19d18ec824d988519e28a8a36aef2b94be6a80ec3634dac1ec25", - magenta: "e705f225be4bb4ea1f0158d65198f206657f7ead2d892e4169902c9df5935c89", + magenta: "215dbbc81c898955ad25cb5c23094c70ee1677d599ea248fd03ae98d618bd082", federico: "bb8a9ebb7529473d3e6952ba0870c16b309559e09b76524abc7e678a92f8145d", boating: "7754ed5cab71d070f83f13d70fcd761440018bb2927881ebecb30e6104b2e418", campings_demo: From 6eecb71c90d304d0425162bb62397d8c6f5474b4 Mon Sep 17 00:00:00 2001 From: Rodrigo Opalo <206490241+devrodri-com@users.noreply.github.com> Date: Sat, 15 Aug 2026 15:36:18 -0400 Subject: [PATCH 2/2] =?UTF-8?q?docs(portfolio):=20usar=20lenguaje=20llano?= =?UTF-8?q?=20en=20el=20estado=20del=20caso=20Magenta=20en=20espa=C3=B1ol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La revisión señaló que la copy pública en español introducía "pre-cutover" sin explicarlo, y lo repetía en el caso expandido junto con "cutover" y "gate de indexación". Para un visitante hispanohablante del portfolio eso oscurece el estado real del proyecto en vez de comunicarlo. Se reemplaza esa terminología por lenguaje llano —"disponible para revisión antes de la publicación definitiva"— de forma consistente en la tarjeta, el resumen, el stack, la solución y el impacto. El significado técnico no cambia: la indexación sigue descrita como deshabilitada hasta completar la transición. La versión en inglés conserva "pre-cutover": el término es corriente para esa audiencia y la observación apuntaba específicamente a la claridad en español. Actualiza únicamente la línea sha256 de `magenta` en PortfolioSafety, que vuelve a moverse porque el payload público del caso cambió. Co-Authored-By: Claude Opus 5 --- src/data/portfolio/cases/magenta.ts | 8 ++++---- src/i18n/es.ts | 2 +- src/test/PortfolioSafety.test.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/data/portfolio/cases/magenta.ts b/src/data/portfolio/cases/magenta.ts index f4af765..3074049 100644 --- a/src/data/portfolio/cases/magenta.ts +++ b/src/data/portfolio/cases/magenta.ts @@ -4,7 +4,7 @@ import { definePortfolioCase } from "../types"; const stackEs = [ "Frontend: Next.js 16 (App Router) + TypeScript + Tailwind CSS", "Infraestructura: Vercel con despliegue continuo", - "SEO técnico: metadata, Open Graph, sitemap y robots controlados por un gate de indexación hasta el cutover", + "SEO técnico: metadata y Open Graph; sitemap y robots controlados por una configuración que mantiene deshabilitada la indexación hasta la publicación definitiva", "Recursos visuales del MVP: mockups generados con GPT Image 2", "Gestión de datos: productos y servicios centralizados en src/data" ] as const; @@ -57,7 +57,7 @@ export const magentaCase = definePortfolioCase({ "Next.js" ], details: { - summary: "MVP público en etapa pre-cutover para una imprenta de Paysandú activa desde 2010. Centraliza productos, servicios y solicitudes de presupuesto en una arquitectura modular construida con Next.js 16.", + summary: "MVP público para una imprenta de Paysandú activa desde 2010, disponible para revisión antes de la publicación definitiva. Centraliza productos, servicios y solicitudes de presupuesto en una arquitectura modular con Next.js 16.", stack: stackEs, integrations: integrationsEs, challenges: [ @@ -71,11 +71,11 @@ export const magentaCase = definePortfolioCase({ "Catálogo de productos y servicios centralizado en estructuras de datos (src/data).", "Formularios dinámicos basados en reglas por servicio (libretas, tarjetas, afiches, etc.).", "Diseño limpio estilo Apple minimal con foco en claridad y velocidad de acceso.", - "Contrato SEO pre-cutover con metadata, Open Graph, sitemap y robots controlados por configuración; la indexación permanece deshabilitada hasta el cutover.", + "Configuración SEO para la etapa previa a la publicación definitiva, con metadata, Open Graph, sitemap y robots; la indexación permanece deshabilitada hasta completar esa transición.", "Deploy automatizado en Vercel con imágenes optimizadas." ], impact: [ - "MVP público disponible en Vercel para revisión previa al cutover.", + "MVP público disponible en Vercel para revisión antes de la publicación definitiva.", "Productos, servicios y solicitud de presupuesto reunidos en una experiencia responsive.", "Flujo de presupuesto con protección Turnstile e integración de entrega por email mediante Resend.", "Sistema visual coherente con la identidad de Magenta y mockups creados con GPT Image 2.", diff --git a/src/i18n/es.ts b/src/i18n/es.ts index fcad7b8..c57224d 100644 --- a/src/i18n/es.ts +++ b/src/i18n/es.ts @@ -430,7 +430,7 @@ export const es = { }, magenta: { title: "Imprenta Magenta · Paysandú, Uruguay", - desc: "MVP público pre-cutover para Imprenta Magenta, activa en Paysandú desde 2010, con catálogo de productos y servicios y formulario de presupuesto protegido con Turnstile.", + desc: "MVP público de Imprenta Magenta, activa en Paysandú desde 2010. Disponible para revisión antes de la publicación definitiva, con catálogo y formulario de presupuesto protegido con Turnstile.", link: "Ver sitio", }, campings_demo: { diff --git a/src/test/PortfolioSafety.test.ts b/src/test/PortfolioSafety.test.ts index f51a67a..e1208d8 100644 --- a/src/test/PortfolioSafety.test.ts +++ b/src/test/PortfolioSafety.test.ts @@ -87,7 +87,7 @@ const expectedPreservedCaseHashes = { zentra: "50082406905123ed80a6eac63745d3a4a27448825990fdc82b7057d41b4d411a", esteban: "643b388f7f34ce4b90e2ba1890b007fef0f2c485694647bf56cc0c04a4c421e4", mutter: "aa118ae6042f19d18ec824d988519e28a8a36aef2b94be6a80ec3634dac1ec25", - magenta: "215dbbc81c898955ad25cb5c23094c70ee1677d599ea248fd03ae98d618bd082", + magenta: "d2c9c76edfd53b982ce9567d102d79189cffa01e74ee59e6aef6cd34b5dae5cf", federico: "bb8a9ebb7529473d3e6952ba0870c16b309559e09b76524abc7e678a92f8145d", boating: "7754ed5cab71d070f83f13d70fcd761440018bb2927881ebecb30e6104b2e418", campings_demo: