Descargas
Documento del caso «Diagnóstico gratuito con calificación».
Documento del caso (PDF)
Problema, solución, distribución, recorte, construcción, medición y próximos pasos.
DescargarDocumento del caso (Markdown)
El mismo contenido en texto plano.
Descargar
Prompts utilizados
Copiá cada prompt con un clic.
Prompt 001 — Preparación y documentación del proyecto
Vamos a desarrollar el desafío técnico de Fudo en este proyecto Astro existente. El proyecto ya está inicializado con pnpm, TypeScript y Git. El servidor de desarrollo está funcionando en http://localhost:4322/. Respetá la estructura y las dependencias existentes. No reinicialices el proyecto ni instales otro framework. La arquitectura deberá ser modular, con componentes de responsabilidad única y separación entre páginas, layouts, estilos, datos y lógica de negocio. Priorizá el uso eficiente de la cuota gratuita de inteligencia artificial. No ejecutes pruebas repetitivas ni instales dependencias sin necesidad. Documentá en `docs/PROMPTS.md` los prompts relevantes utilizados durante el desarrollo, sin inventar ni reescribir las instrucciones originales. Registrá las decisiones técnicas y comerciales importantes en `docs/DECISIONES.md`. No incluyas credenciales ni información sensible. Este archivo `docs/PROMPTS.md` ya fue creado manualmente y contiene el primer prompt. No lo reemplaces ni lo regeneres. ## Control de versiones — Git El control de versiones es responsabilidad exclusiva del desarrollador humano. - Permitido: `git status`, `git diff`, `git log` y consultas de solo lectura. - Prohibido: `git add`, `git commit`, `git push`, `git pull`, `git merge`, `git rebase`, `git reset` y cualquier operación que altere el repositorio. - No crear, cambiar ni eliminar ramas. - No modificar `.gitignore` sin autorización. - No configurar repositorios remotos. - Al finalizar cada tarea, informar los archivos creados, modificados o eliminados. - El desarrollador humano revisará los cambios y realizará los commits manualmente. Estas restricciones se mantienen durante todo el proyecto, salvo autorización explícita del desarrollador. Antes de comenzar cualquier tarea, leé este archivo y respetá su contenido. Leé también AGENTS.md y respetá todas sus instrucciones permanentes, especialmente las restricciones sobre Git. Ante una contradicción entre ambos archivos, detenete y solicitá una aclaración antes de actuar. Para cada nuevo prompt, registrá su texto original, fecha y hora real de ejecución, modelo utilizado, objetivo, archivos modificados y resultado. Si no podés recuperar el texto exacto de una instrucción, indicá que no está disponible en lugar de reconstruirlo. No inventes fechas, resultados, pruebas ni modificaciones. No marques como ejecutada una tarea que solamente fue planificada. Por ahora, inspeccioná brevemente la estructura del proyecto y confirmá que comprendiste las restricciones. No modifiques código, no instales dependencias ni ejecutes pruebas. ### Restricciones de generación visual y consumo de recursos Para optimizar la cuota gratuita de Antigravity, se establecen las siguientes restricciones obligatorias: 1. **No generar imágenes** mediante modelos de IA, herramientas gráficas ni servicios externos. 2. **No generar archivos SVG**, ilustraciones, logotipos, fotografías, banners, fondos decorativos ni recursos visuales personalizados. 3. **No utilizar herramientas de generación de imágenes** ni invocar modelos multimodales para producir recursos gráficos. 4. No instalar bibliotecas de iconos, frameworks visuales ni paquetes de animaciones. 5. No generar diseños elaborados, propuestas visuales alternativas ni múltiples versiones de una misma interfaz. 6. Utilizar HTML semántico, CSS nativo y los componentes propios de Astro. 7. Priorizar una interfaz minimalista, accesible y funcional, utilizando tipografía del sistema, colores CSS y elementos HTML estándar. 8. Si se necesitan gráficos de métricas, utilizar HTML y CSS con datos estructurados, sin generar imágenes. 9. Evitar exploraciones estéticas, pruebas visuales automatizadas y capturas de pantalla innecesarias. 10. No ejecutar pruebas, compilaciones ni procesos repetitivos sin una razón técnica concreta. 11. No modificar componentes que ya funcionan salvo que exista un defecto identificable o un requisito pendiente. 12. Antes de incorporar cualquier dependencia o herramienta adicional, justificar su necesidad y solicitar autorización. **Prioridad absoluta:** funcionalidad, arquitectura, experiencia de conversión, accesibilidad y medición del negocio. El diseño visual no es un criterio puntuable del desafío técnico de Fudo. No dedicar recursos de IA a generar elementos decorativos.
Prompt 002 — Propuesta de estructura de archivos (descartado)
Leé docs/ESTRATEGIA.md, docs/PROMPTS.md y AGENTS.md. ESTRATEGIA.md es la fuente de verdad del proyecto. Proponé la lista exacta de archivos a crear en src/ según la sección 7 (Construcción), con una línea de responsabilidad por archivo. No escribas código todavía. Si encontrás algo ambiguo o contradictorio en la estrategia, listalo como pregunta. Registrá este prompt en docs/PROMPTS.md como Prompt 002 según las reglas del archivo.
Prompt 003 — Contratos de tipos y datos de negocio
Seguí AGENTS.md. Completá solo estos archivos, que ya existen vacíos: src/types/diagnostico.ts — exportar exactamente: type Estado = 'bien' | 'mejorable' | 'critico' type Segmento = 'alto' | 'medio' | 'fuera' type PreguntaId = 'sistema' | 'locales' | 'delivery' | 'rol' interface ItemDef { id: string; nombre: string; peso: number; fuenteReal: string; recomendaciones: Record<Estado, string[]> } interface ResultadoItem { id: string; nombre: string; nota: number; estado: Estado; recomendaciones: string[] } interface Diagnostico { local: string; ciudad: string; notaTotal: number; items: ResultadoItem[] } interface Opcion { valor: string; etiqueta: string } interface Pregunta { id: PreguntaId; texto: string; opciones: Opcion[] } type Respuestas = Record<PreguntaId, string> type FlagId = 'alto_requiere_delivery' type Flags = Record<FlagId, boolean> interface FlagDef { id: FlagId; titulo: string; descripcion: string; activo: string; inactivo: string; porDefecto: boolean } interface ReglaCalificacion { segmento: Segmento; motivo: string; cumple: (r: Respuestas, f: Flags) => boolean } interface ResultadoCalificacion { segmento: Segmento; motivo: string } src/data/items.ts — export const ITEMS: ItemDef[] con los 5 ítems y pesos de docs/ESTRATEGIA.md sección 4 (ids: google, resenas, instagram, web, delivery). 2 recomendaciones breves por estado, en español rioplatense, accionables, sin prometer funciones de Fudo. src/data/preguntas.ts — export const PREGUNTAS: Pregunta[] con las 4 preguntas de la sección 3. Valores: sistema: papel | basico | otro_software | no_se locales: 1 | 2_5 | 6_mas delivery: mucho | algunos | no rol: dueno | encargado | otro src/data/reglas-calificacion.ts — export const REGLAS: ReglaCalificacion[] en este orden (gana la primera que cumple): 1. locales = 6_mas → fuera, "Cadena: atención comercial" 2. sistema = otro_software → medio, "Ya usa software de gestión" 3. rol ≠ dueno → medio, "No es quien decide" 4. sistema ∈ {papel, basico} y (delivery ≠ no o f.alto_requiere_delivery es false) → alto, "Sin sistema y con encaje operativo" 5. siempre → medio, "Encaje a confirmar" src/data/flags.ts — export const FLAGS: FlagDef[] con un solo elemento: id: 'alto_requiere_delivery' titulo: "Alto encaje exige delivery o WhatsApp" descripcion: "Define si un local sin sistema y solo con salón cuenta como alto encaje." activo: "Sí: solo con pedidos por delivery o WhatsApp (variante A)" inactivo: "No: también locales solo de salón (variante B)" porDefecto: true Y export const FLAGS_POR_DEFECTO: Flags construido desde FLAGS con Object.fromEntries. Ejecutá una sola vez pnpm exec astro check. Completá el registro en docs/prompts/003-contratos-tipos-y-datos.md: hora real de ejecución (comando date), estado, resultado en 3 líneas como máximo y archivos modificados. No modifiques la sección "Prompt original".Prompt 004 — Lógica de diagnóstico y calificación
Seguí AGENTS.md. Completá solo estos archivos, que ya existen vacíos. No modifiques src/types ni src/data. Sin dependencias nuevas. src/lib/hash.ts: - export function normalizar(texto: string): string → minúsculas, sin tildes (NFD + quitar diacríticos), espacios colapsados, trim. - export function fnv1a(texto: string): number → FNV-1a de 32 bits, devuelve entero sin signo. src/lib/diagnostico.ts — export function diagnosticar(local: string, ciudad: string): Diagnostico - semilla = normalizar(local) + '|' + normalizar(ciudad) - nota de cada ítem de ITEMS = (fnv1a(semilla + ':' + item.id) % 81) + 10 → rango 10 a 90 - estado: nota ≥ 70 → 'bien'; 40 a 69 → 'mejorable'; < 40 → 'critico' - recomendaciones = item.recomendaciones[estado] - notaTotal = promedio de las notas ponderado por item.peso, redondeado a entero - local y ciudad se devuelven tal como los ingresó el usuario, con trim src/lib/calificacion.ts — export function calificar(r: Respuestas, f: Flags = FLAGS_POR_DEFECTO): ResultadoCalificacion - recorrer REGLAS en orden y devolver { segmento, motivo } de la primera cuya función cumple(r, f) sea verdadera. hash.ts, diagnostico.ts y calificacion.ts deben ser puros: sin acceso al DOM, a window, a localStorage ni a fechas. src/lib/flags.ts — único módulo que accede a localStorage, con clave 'fudo_flags': - export function leerFlags(): Flags → FLAGS_POR_DEFECTO combinado con lo guardado. Ignorar claves que no existan en FLAGS y valores no booleanos. - export function guardarFlag(id: FlagId, valor: boolean): void - export function restablecerFlags(): void → borra la clave. - Todo acceso a localStorage dentro de try/catch; si falla, leerFlags devuelve FLAGS_POR_DEFECTO y las escrituras no hacen nada. Ejecutá una sola vez pnpm exec astro check. Completá el registro en docs/prompts/004-logica-diagnostico-y-calificacion.md: hora real de ejecución (comando date), estado, resultado en 3 líneas como máximo y archivos modificados. No modifiques la sección "Prompt original".Prompt 005 — Interfaz y flujo del diagnóstico
Seguí AGENTS.md. Completá solo los archivos indicados. No modifiques src/lib, src/data ni src/types. HTML semántico, CSS nativo mínimo, sin imágenes, SVG ni librerías. Componentes (solo marcado estático, sin lógica): - src/components/FormularioLocal.astro: <form id="form-local"> con inputs name="local" y name="ciudad", ambos required y con <label>. Botón "Ver mi diagnóstico". - src/components/PreguntasCalificacion.astro: <form id="form-calificacion" hidden>. Importar PREGUNTAS desde src/data/preguntas.ts y generar un <fieldset> con <legend> por pregunta, con radios name={pregunta.id} y required. Botón "Ver resultado". - src/components/ResumenNota.astro: <section id="resultado" hidden aria-live="polite"> con un <h2 tabindex="-1" id="resultado-titulo">, un elemento data-campo="nota-total" y una <ul id="lista-items">. - src/components/TarjetaItem.astro: <template id="tpl-item"> con un <li> que contenga elementos con data-campo="nombre", "nota", "estado" y una <ul data-campo="recomendaciones">. El estado se muestra como texto ("Bien", "Mejorable", "Crítico"), no solo con color. - src/components/CtaSegmento.astro: <div id="cta"> con tres enlaces, todos hidden, con href="https://fu.do" y data-segmento: alto → "Creá tu cuenta gratis en Fudo" medio → "Compará Fudo con tu sistema actual" fuera → "Hablá con el equipo comercial" - src/components/AvisoDatosSimulados.astro: <p> visible: "Prototipo: los datos de presencia online son simulados." src/pages/index.astro: - Usar src/layouts/Layout.astro. En Layout.astro solo se autoriza cambiar lang a "es" y el <title> a "Diagnóstico gratuito para restaurantes"; nada más. - Contenido en <main>: <h1>¿Cómo está tu restaurante en internet?</h1>, una línea de propuesta de valor ("Revisamos tu presencia en Google, reseñas, redes, web y apps de delivery en menos de un minuto."), y los componentes en este orden: FormularioLocal, PreguntasCalificacion, ResumenNota, TarjetaItem, CtaSegmento, AvisoDatosSimulados. TarjetaItem solo aporta el <template>; no se ve hasta que app.ts lo clona. - Importar src/styles/global.css en el frontmatter. - Cargar el controlador con <script>import '../scripts/app.ts';</script>. src/scripts/app.ts: 1. Al enviar form-local: prevenir envío, ocultar form-local, mostrar form-calificacion y mover el foco a su primer radio. 2. Al enviar form-calificacion: prevenir envío, armar Respuestas desde los radios, llamar diagnosticar(local, ciudad) y calificar(respuestas, leerFlags()). 3. Completar resultado: nota total, título "Diagnóstico de <local>", clonar tpl-item por cada ítem y completar sus data-campo. 4. Mostrar #resultado y #cta; mostrar solo el enlace cuyo data-segmento coincida; ocultar form-calificacion; mover el foco a #resultado-titulo. 5. Actualizar la URL con ?local=&ciudad= usando history.replaceState. 6. Al cargar la página, si la URL trae local y ciudad: completar form-local con esos valores y mostrar directamente form-calificacion. Si falta un elemento del DOM, no lanzar error: salir de la función. src/styles/global.css: tipografía del sistema, ancho máximo de contenido 40rem centrado, foco visible en elementos interactivos, [hidden] { display: none !important; }. Nada más. Ejecutá una sola vez pnpm exec astro check. Completá el registro en docs/prompts/005-interfaz-y-flujo.md: hora real de ejecución (comando date), estado, resultado en 3 líneas como máximo y archivos modificados. No modifiques la sección "Prompt original".Prompt 006 — Medición de eventos y CTA a Fudo
Seguí AGENTS.md. Completá src/lib/analytics.ts y src/lib/cta.ts, y conectalos en src/scripts/app.ts. En src/components/CtaSegmento.astro solo se autoriza agregar el enlace de compartir indicado abajo. No modifiques otros archivos. src/lib/analytics.ts: - Declarar en global: interface Window { dataLayer: Record<string, unknown>[] }. - export function track(evento: string, props: Record<string, string | number> = {}): void → window.dataLayer = window.dataLayer || []; push de { event: evento, ...props }. → console.info('[track]', evento, props) solo si import.meta.env.DEV. - No enviar nunca el nombre del local ni la ciudad. src/lib/cta.ts — export function urlFudo(segmento: Segmento, flags: Flags): string - Base https://fu.do con URLSearchParams: utm_source=diagnostico, utm_medium=herramienta, utm_campaign=ar_lanzamiento, utm_content=<segmento>, utm_term=regla_a si flags.alto_requiere_delivery es true, regla_b si es false. - Función pura: recibe los flags, no los lee. src/components/CtaSegmento.astro: agregar dentro de #cta un enlace <a id="compartir-whatsapp" hidden target="_blank" rel="noopener">Compartir por WhatsApp</a>. src/scripts/app.ts — conectar sin cambiar el flujo existente: - Al enviar form-local: track('diagnostico_iniciado'). - Al enviar form-calificacion: track('calificacion_completada', { segmento, sistema, locales, delivery, rol, ...flags }), donde flags = leerFlags() con cada valor convertido a 'si' o 'no'. Así cada evento queda asociado a la variante de regla vigente. - Al mostrar el resultado: track('resultado_visto', { segmento, nota_total }). - Al mostrar el CTA: asignar urlFudo(segmento, leerFlags()) al href del enlace visible y registrar click con track('cta_click', { segmento }). - Enlace de compartir: mostrarlo junto con el resultado. href = 'https://wa.me/?text=' + encodeURIComponent('Mi restaurante sacó ' + notaTotal + '/100 en el diagnóstico de presencia online. Hacé el tuyo: ' + urlCompartir), donde urlCompartir = location.origin + location.pathname + '?utm_source=whatsapp&utm_medium=compartir&utm_campaign=ar_lanzamiento'. No incluir local ni ciudad en urlCompartir. Al hacer click: track('compartir_click', { segmento }). Ejecutá una sola vez pnpm exec astro check. Completá el registro en docs/prompts/006-medicion-y-cta.md: hora real de ejecución (comando date), estado, resultado en 3 líneas como máximo y archivos modificados. No modifiques la sección "Prompt original".Prompt 007 — Panel de control de switches
Seguí AGENTS.md. Completá solo estos archivos, que ya existen vacíos: src/pages/control.astro y src/scripts/control.ts. No modifiques ningún otro archivo de src/. src/pages/control.astro: - Usar src/layouts/Layout.astro e importar src/styles/global.css. - En el <head>, vía el layout o un slot si existe: <meta name="robots" content="noindex, nofollow">. Si Layout.astro no admite agregar meta, informalo y no lo modifiques. - <main> con <h1>Panel de control</h1> y el párrafo: "Los cambios se guardan solo en este navegador y no afectan a otros visitantes." - Importar FLAGS desde src/data/flags.ts y generar, por cada flag, un <fieldset> con <legend>{titulo}</legend>, un <p>{descripcion}</p> y dos radios name={id} con value="true" (etiqueta = activo) y value="false" (etiqueta = inactivo). - Un botón id="restablecer" con el texto "Restablecer valores por defecto". - Un <p id="estado" aria-live="polite"></p> para confirmar cambios. - Un enlace "Volver al diagnóstico" a "/". - Cargar el controlador con <script>import '../scripts/control.ts';</script>. src/scripts/control.ts: 1. Al cargar: marcar en cada grupo de radios el valor de leerFlags(). 2. Al cambiar un radio: guardarFlag(id, value === 'true') y escribir en #estado "Guardado: <titulo> → <etiqueta elegida>". 3. Al hacer clic en #restablecer: restablecerFlags(), volver a marcar los valores por defecto y escribir en #estado "Valores por defecto restablecidos". Usar solo leerFlags, guardarFlag y restablecerFlags de src/lib/flags.ts; no acceder a localStorage directamente. La página no debe enlazarse desde index.astro. Ejecutá una sola vez pnpm exec astro check. Completá el registro en docs/prompts/007-panel-de-control.md: hora real de ejecución (comando date), estado, resultado en 3 líneas como máximo y archivos modificados. No modifiques la sección "Prompt original".Prompt 008 — Verificación y compilación final
Seguí AGENTS.md. 1. Ejecutá una vez pnpm exec astro check y una vez pnpm exec astro build. 2. Si alguno falla, corregí solo las líneas que causan el error, sin refactorizar ni cambiar comportamiento, y volvé a ejecutar solo el comando que falló. Máximo dos intentos; si sigue fallando, detenete e informá el error completo. 3. Revisá sin modificar y respondé sí o no a cada punto: a. ¿El aviso "Prototipo: los datos de presencia online son simulados." se muestra en la página? b. ¿Ningún texto presenta los datos simulados como reales? c. ¿Ninguna llamada a track() envía local ni ciudad? d. ¿La URL de compartir por WhatsApp no incluye local ni ciudad? e. ¿Los tres enlaces del CTA usan urlFudo() con utm_content igual al segmento y utm_term igual a la variante de regla? f. ¿Quedan textos de relleno, TODO o lorem ipsum en src/? g. ¿src/lib/flags.ts es el único archivo de src/ que accede a localStorage? h. ¿calificar() recibe los flags como parámetro y no los lee por su cuenta? i. ¿La página /control tiene noindex y no está enlazada desde index.astro? Si alguna respuesta indica un problema, informalo sin corregirlo. No inicies el servidor de desarrollo, no despliegues ni modifiques archivos fuera de src/. Completá el registro en docs/prompts/008-verificacion-y-build.md: hora real de ejecución (comando date), estado, resultado del check y del build, respuestas a los puntos a–i y archivos modificados. No modifiques la sección "Prompt original".