<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">
  <channel>
    <title>Blog - Xúlio Zé</title>
    <link>https://xulioze.com/</link>
    <atom:link href="https://xulioze.com/blog/feed.xml" rel="self" type="application/rss+xml"/>
    <description>Un cuaderno donde hablo de mis proyectos y lo que aprendo.</description>
    <lastBuildDate>Thu, 22 Oct 2026 08:30:46 GMT</lastBuildDate>
    <language>es</language>
    <generator>Lume v3.2.5</generator>
    <author>
      <name>Xúlio Zé</name>
      <uri>https://xulioze.com/</uri>
    </author>
    <item>
      <title>atproto-comments</title>
      <link>https://xulioze.com/blog/atproto-comments.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/atproto-comments.html</guid>
      <description>
        atproto-comments es un web component que lleva los comentarios del AT Protocol (Bluesky, Mu, Deer…) a cualquier web, sin base de datos ni autenticación.
      </description>
      <content:encoded>
        <![CDATA[        <figure class="c-post__body-img c-post__body-img--figure">
          <img src="https://xulioze.com/img/leiras.jpg" alt="Nubes, molinos y campos fotografiados desde el cielo" width="1200" loading="lazy">
          <figcaption>Atmósfera, molinos y campos (Thomas Richter)</figcaption>
        </figure>

        <p>Acabo de publicar atproto-comments (en <a href="https://www.npmjs.com/package/atproto-comments" target="_blank" rel="noopener" title="atproto-comments en npm">npm</a> y en <a href="https://jsr.io/@arinspunk/atproto-comments" target="_blank" rel="noopener" title="atproto-comments en JSR">JSR</a>), un web component que lleva los comentarios del AT Protocol a cualquier web, de forma sencilla y sin necesidad de autenticación.</p>

        <ol>
          <li>Publicas un artículo en tu web.</li>
          <li>Publicas un post en una app del AT Protocol (Bluesky, Mu, Deer, etc.) con el enlace a ese artículo.</li>
          <li>Insertas el componente en tu HTML, apuntando al post mediante su AT URI:</li>
        </ol>

        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">&lt;atproto-comments thread-uri="at://did:plc:xxxx/app.bsky.feed.post/yyyy"&gt;&lt;/atproto-comments&gt;</code></pre>

        <p>Y listo: las respuestas a ese post aparecen como comentarios en tu artículo. Además, si un visitante con cuenta en el AT Protocol quiere comentar, elige su app y se le redirige al post.</p>

        <p>El objetivo es doble. Por un lado, ofrecer un sistema de comentarios fácil de integrar, sin base de datos propia y sin depender de plataformas como Disqus. Por otro, traer a tu web las conversaciones que hoy se quedan encerradas dentro de las redes sociales.</p>

        <p>Si no conoces el AT Protocol, sigue leyendo. Te voy a contar el camino que seguí hasta conocerlo y entenderlo, porque tengo la intuición de que te será más útil que una definición de manual.</p>

        <p>Hace año y medio, harto del estercolero en el que se ha convertido X, busqué alternativas. Di con Bluesky, que prometía ser una red abierta y tenía una interfaz con vibes del viejo Twitter. Me gustó: casi sin ruido, nazis ni bots. Pero no entendí el porqué de lo de "abierta".</p>

        <p>En marzo vi un post de Eurosky, iniciativa europea independiente que trabaja para construir una web social abierta, donde <a href="https://eurosky.tech/accounts/migrate/" target="_blank" rel="noopener" title="How to move your account to Eurosky">invitaban a mover nuestras cuentas de Bluesky, alojadas en servidores en EE. UU., a sus servidores en Europa</a>, y a seguir conversando en Bluesky. ¿Cómo? Esto ya era un poco más raro. Pero era verdad: cambié mi cuenta a Eurosky y seguí conversando en Bluesky.</p>

        <p>En junio, <a href="https://bsky.app/profile/eurosky.social/post/3mnyoeuenq225" target="_blank" rel="noopener" title="Muve to the beat">otro post de Eurosky</a>. Esta vez anunciaban <a href="http://mu.social/" target="_blank" rel="noopener" title="mu.social">mu.social</a>, una nueva app de microblogging. Probé a entrar con mis credenciales de Bluesky y me quedé de piedra. Ahí estaba mi perfil, con mis posts, la gente a la que sigo y mis seguidores. Todo. Después encontré y probé Deer y pasó lo mismo.</p>

        <p>Para que entiendas mi sorpresa, aquí está el mismo post de Eurosky visto a través de tres apps:</p>

        <ul>
          <li>
            <a href="https://bsky.app/profile/eurosky.social/post/3mnyoeuenq225" target="_blank" rel="noopener" title="Post de Eurosky en Bluesky">
              Post de Eurosky en Bluesky
            </a>
          </li>
          <li>
            <a href="https://mu.social/profile/eurosky.social/post/3mnyoeuenq225" target="_blank" rel="noopener" title="Post de Eurosky en mu.social">
              Post de Eurosky en mu.social
            </a>
          </li>
          <li>
            <a href="https://deer.social/profile/eurosky.social/post/3mnyoeuenq225" target="_blank" rel="noopener" title="Post de Eurosky en Deer">
              Post de Eurosky en Deer
            </a>
          </li>
        </ul>

        <p>Espera, esto me recordaba a algo que ya había vivido. ¡Claro, qué morriña! Los blogs, el RSS, Google Reader y Feedly. Cuando internet era descentralizada, lo que publicábamos era nuestro y lo que leíamos no estaba deformado por los algoritmos de empresas privadas.</p>

        <p>Investigué y recapitulé. Esto era posible porque Bluesky está construido sobre el AT Protocol, un protocolo abierto para redes sociales descentralizadas. En él, tus datos viven en un servidor de datos personal (PDS) y están firmados criptográficamente (DID). Por eso podemos cambiar de proveedor sin perder la cuenta ni los seguidores (¡los datos son nuestros!), e incluso montar <a href="https://sliplane.io/blog/self-hosting-bluesky-pds-from-scratch" target="_blank" rel="noopener" title="Self-hosting Bluesky PDS from Scratch">nuestro propio servidor</a>. Podemos consumir nuestros datos y los de las personas a las que seguimos desde distintas apps. Y podemos desarrollar herramientas como atproto-comments, que acabo de publicar, sin depender de lo que una empresa decida en cada momento.</p>

        <h2>Cómo funciona por dentro</h2>

        <p>Si quieres ver las piezas del puzle, estas son las que entran en juego cuando atproto-comments carga los comentarios:</p>

        <ul>
          <li>Identidad (DID y handle): cada cuenta tiene un identificador permanente (<code>did:plc:...</code>) y un nombre legible (<code>@xulioze.eurosky.social</code>). El DID es lo que permite cambiar de servidor sin perder nada.</li>
          <li>PDS (Personal Data Server): el servidor donde viven tus datos, en un repositorio firmado. Puede ser el de Bluesky, el de Eurosky o el tuyo propio.</li>
          <li>Lexicons y registros: cada tipo de dato tiene un esquema público. Un post es un registro de la colección <code>app.bsky.feed.post</code>; por eso la AT URI apunta a <code>at://&lt;did&gt;/app.bsky.feed.post/&lt;id&gt;</code>.</li>
          <li>Relay: como los datos están repartidos en muchos PDS, el Relay los reúne y reemite sus cambios en un único flujo en tiempo real (el <em>firehose</em>).</li>
          <li>AppView: consume ese flujo, lo indexa y sirve vistas ya montadas, como el hilo de respuestas de un post. atproto-comments pide ese hilo a la API pública del AppView de Bluesky (<code>app.bsky.feed.getPostThread</code>), pero puedes apuntarlo a otro AppView con el atributo <code>appview</code>.</li>
          <li>Apps cliente: Bluesky, Mu, Deer… son solo interfaces distintas sobre los mismos datos, y cada una puede decidir cómo los muestra: qué algoritmo usa, cómo ordena el feed, qué moderación aplica. Si un día no me gusta cómo me sirve Bluesky el feed, me cambio a otra app que lo haga más a mi gusto, sin perder nada.</li>
        </ul>

        <p>En el fondo, la idea es muy parecida a la del RSS y los blogs: los datos son de quien los publica, que puede llevárselos adonde quiera. Cada cual decide cómo y dónde consumirlos. Y cualquiera puede desarrollar herramientas para el ecosistema sin pedir permiso a nadie, como atproto-comments, que estrenamos hoy aquí. Si ya tienes cuenta en el AT Protocol, deja un comentario aquí abajo desde tu app favorita (Bluesky, Mu, Deer…) y lo verás aparecer. Si no tienes, <a href="https://portal.eurosky.tech/create-account" target="_blank" rel="noopener" title="Create your Eurosky account">crea una cuenta en Eurosky</a> y úsala en la app que quieras. ¡Bienvenida a las redes sociales abiertas!</p>

        <h2 class="c-post__body-title">Comentarios</h2>

        <atproto-comments
          thread-uri="at://did:plc:ooensn4mr5mhznzypvxelfa3/app.bsky.feed.post/3mnyoeuenq225"
          strings='{"comment":"Comentar","reply":"Responder","replyTo":"Responder a {name}","otherApp":"Otra app","invalidDomain":"Dominio no válido","error":"No se han podido cargar los comentarios.","viewMore":"Ver más en Bluesky","now":"ahora","months":"mes"}'
          style="color-scheme: dark; --atproto-font-family: inherit; --atproto-font-size: 1rem; --atproto-color-muted: oklch(70% 0 0); --atproto-color-border: oklch(40% 0 0); --atproto-color-surface: #1c1c3d;"
        ></atproto-comments>
]]>
      </content:encoded>
      <pubDate>Mon, 19 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Contexto Extendido 2.0: Los agentes necesitan arquitectura, no solo tomar notas</title>
      <link>https://xulioze.com/blog/contexto-extendido-v2.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/contexto-extendido-v2.html</guid>
      <description>
        Guía mejorada para estructurar desarrollo asistido por IA: separar conocimiento reutilizable (rules) de memoria temporal (memory) elimina el vibe-coding.
      </description>
      <content:encoded>
        <![CDATA[        <figure class="c-post__body-img c-post__body-img--figure">
          <img src="https://xulioze.com/img/blade-runner-2049-k-in-rooftop.jpg" alt="Silueta de K en Blade Runner 2049 mirando la ciudad desde un tejado, simbolizando la arquitectura de conocimiento para agentes de IA" width="1200" loading="lazy">
          <figcaption>Observando la ciudad</figcaption>
        </figure>

        <p>Esta guía es una versión mejorada de la que propuse en "<a href="https://xulioze.com/blog/contexto-extendido.html" target="_blank" rel="noopener" title="Contexto extendido. Los agentes también necesitan tomar notas">Contexto extendido. Los agentes también necesitan tomar notas</a>" y <a href="https://xulioze.com/blog/guia-desarrollar-software-agentes.html" target="_blank" rel="noopener" title="Guía: desarrollar software de calidad asistido por agentes de IA">Guía: desarrollar software de calidad asistido por agentes de IA</a>.</p>

        <p>Cuando llegaron los editores con agentes de IA autónomos (Cursor, GitHub Copilot, Claude Code), muchos compramos la promesa: "<a href="https://xulioze.com/blog/oneshot-vs-dialogo.html" target="_blank" rel="noopener" title="One-shot vs diálogo: cómo elegir el modo correcto para tu agente de IA">escribe el prompt perfecto</a> y el agente te genera la feature completa de una tirada". La realidad fue otra: sin estructura ni constraints, acabábamos dedicando más tiempo a corregir bugs que a escribir código.</p>

        <p>El "vibe-coding", eso de confiar en que el agente "pille la vibe" de tu proyecto, funciona bien para prototipos rápidos, pero en proyectos reales y complejos genera más problemas que soluciones:</p>
        <ul>
          <li>Decisiones perdidas: ¿Por qué elegimos esta arquitectura hace dos semanas?</li>
          <li>Alucinaciones constantes: La IA inventa APIs, mezcla frameworks, ignora constraints</li>
          <li>Trabajo monolítico: Imposible dividir features en tareas rastreables</li>
          <li>Improvisación continua: Cada sesión comienza desde cero</li>
        </ul>

        <p>Hace unos meses documenté <a href="https://xulioze.com/blog/guia-desarrollar-software-agentes.html" target="_blank" rel="noopener" title="Guía: desarrollar software de calidad asistido por agentes de IA">una solución</a> (v1): un workflow estructurado (análisis → solución → backlog → ejecución → progreso guardado) con cuatro archivos de contexto que convertía el vibe-coding en ingeniería rastreable. Funcionó, pero había fricción: repetir manualmente los mismos prompts en cada sesión era un dolor.</p>

        <p>Esta guía presenta la evolución de ese sistema (v2). Aprovecha el sistema de rules de Cursor para automatizar prompts y convierte el workflow en protocolos reutilizables. Pero al diseñarla emergió un patrón universal: separar conocimiento reutilizable (rules) de memoria temporal (memory). Esto va más allá de ahorrarte escribir los mismos prompts: puedes reutilizar el conocimiento en diferentes proyectos y llevar un registro ordenado de todo lo que haces. Y el patrón funciona con cualquier herramienta de IA, no solo con Cursor.</p>

        <p>Vamos a ver cómo construir esa arquitectura.</p>

        <h2>Problema de v1</h2>

        <p>Sistema de cuatro archivos en <code>context/</code>:</p>
        <ul>
          <li><code>01-expert.md</code> - Perfil del experto</li>
          <li><code>02-analysis.md</code> - Análisis del código</li>
          <li><code>03-plan.md</code> - Plan de implementación</li>
          <li><code>04-backlog.md</code> - Tareas pendientes</li>
        </ul>

        <h3>Limitaciones en proyectos reales</h3>

        <p>Conocimiento mezclado: <code>01-expert.md</code> combina principios generales (KISS, DRY) con constraints específicos del proyecto (stack, versiones, dependencias críticas). Imposible reutilizar principios entre proyectos sin arrastrar configuración irrelevante.</p>

        <p>Duplicación entre proyectos: Cada proyecto replica conocimiento común. Si trabajas en 3 proyectos WordPress, tienes <code>security: sanitize_*, nonces</code> copiado tres veces. Actualizas una best practice, debes sincronizar manualmente.</p>

        <p>Sin gestión de histórico: v1 te da tres opciones, todas malas:</p>
        <ul>
          <li>Sobrescribir <code>02-analysis.md</code> → pierdes decisiones previas</li>
          <li>Acumular análisis en el mismo archivo → crece descontroladamente, imposible rastrear cuándo se tomó cada decisión</li>
          <li>Crear múltiples archivos (<code>02-analysis-feature-X.md</code>) → desorden, sin nomenclatura consistente</li>
        </ul>

        <p>En todos los casos: ¿Por qué rechazaste la arquitectura X hace dos semanas? No hay forma sistemática de recuperarlo.</p>

        <p>Sin modularidad: Cambiar de WordPress a React requiere reescribir <code>01-expert.md</code> completo. No puedes mantener módulos comunes (principios, patrones) y solo intercambiar el experto técnico.</p>

        <p>v1 tenía dos problemas fundamentales: (1) conocimiento mezclado en un solo archivo (<code>01-expert.md</code>), (2) ejecución manual - cada acción requería escribir el prompt completo ("analiza este archivo y guarda en <code>02-analysis.md</code>", "lee <code>04-backlog.md</code>, ejecuta tareas 1-3, actualiza estado"). v2 resuelve ambos: separa conocimiento en <code>rules/</code> modulares y automatiza ejecución mediante protocolos invocables en <code>rules/utils/</code> (<code>@analysis</code>, <code>@execute</code>).</p>

        <h2>Solución: Separación Rules/Memory</h2>

        <p>La solución replica cómo funciona nuestro cerebro: separamos conocimiento permanente (idioma, matemáticas, habilidades) de memoria episódica (lo que hicmos ayer, decisiones de la semana pasada). Pero además, nuestro conocimiento no es monolítico: tenemos módulos especializados (JavaScript, WordPress, principios KISS) que activamos según el contexto.</p>

        <p>v2 implementa esta arquitectura dual:</p>

        <ol>
          <li>Separación conocimiento/memoria: Rules reutilizables vs memory temporal</li>
          <li>Modularización del conocimiento: Expertos, guidelines y protocolos ejecutables</li>
        </ol>

        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">.cursor/
├── rules/          # Conocimiento reutilizable y modular
│   ├── experts/    # Roles técnicos (WordPress, React, Python...)
│   ├── guidelines/ # Principios y constraints (KISS, proyecto-específicos)
│   └── utils/      # Protocolos ejecutables (analysis, backlog, commit)
└── memory/         # Experiencias temporales
    └── YYYYMMDD-VV-descripcion.md</code></pre>

        <h3>Concepto Clave: alwaysApply</h3>

        <p>El sistema rules/memory necesita un mecanismo de activación: ¿qué conocimiento carga Cursor automáticamente vs. qué invocas bajo demanda? Sin esto, tendrías 100 reglas compitiendo por contexto limitado.</p>

        <p>El flag <code>alwaysApply</code> resuelve esto:</p>

        <ul>
          <li><code>alwaysApply: true</code> → Cursor las carga automáticamente en cada conversación
            <ul>
              <li>Usa para: Expertos base, guidelines críticas del proyecto</li>
              <li>Ejemplo: <code>wordpress-classic-themes.mdc</code>, <code>constraints-balneario.mdc</code></li>
            </ul>
          </li>
          <li><code>alwaysApply: false</code> → Usuario las invoca con <code>@</code> según necesidad
            <ul>
              <li>Usa para: Protocolos bajo demanda, herramientas específicas</li>
              <li>Ejemplo: <code>@analysis</code>, <code>@backlog</code></li>
            </ul>
          </li>
        </ul>

        <h3>Rules: Conocimiento Reutilizable</h3>

        <p>Experts - Perfiles de expertos técnicos/dominio:</p>

        <p><code>rules/experts/wordpress-classic-themes.mdc</code></p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: true
---
# WordPress Classic Expert
PHP + vanilla JS specialist. WordPress core APIs, theme dev.

## Stack
Backend: PHP 7.4+, WP Core APIs | Frontend: Vanilla JS, HTML5, CSS3

## Core Patterns
- Security: sanitize_*, esc_*, nonces
- Performance: transients (12h), conditional enqueue
- Translation: __(), _e() with text domain</code></pre>

        <p>Guidelines - Principios de código y restricciones de proyecto:</p>

        <p><code>rules/guidelines/constraints-balneario.mdc</code></p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: true
---
# Balneario Theme
Text domain: themefront v0.1.2
Stack: Node | SASS 1.67.0 | PHP 7.4+ | jQuery 3.x
Build: npm run watch:sass (never edit compiled CSS)

Critical: ACF PRO (18 groups), WooCommerce, WPML
Core Systems: PDF Generator (pdf-generator.php), WooCommerce integration</code></pre>

        <p><code>rules/guidelines/kiss.mdc</code></p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: true
---
# KISS Principle
- Direct solutions, avoid over-engineering
- Simple patterns, minimal dependencies
- Single responsibility per function

Rule: If you can't explain it in 2-3 sentences, it's too complex.</code></pre>

        <p>El principio KISS es especialmente importante en desarrollo asistido por IA: es más fácil pedir al agente que añada complejidad a una solución simple, que perder tiempo analizando qué sobra en su propuesta (<a href="https://arxiv.org/html/2411.09916v1" target="_blank" rel="noopener" title="Research paper: LLMs tend to generate more complex code than necessary">los LLMs tienden a generar código más complejo de lo necesario</a>).</p>

        <p>Utils - Protocolos invocables:</p>

        <p><code>rules/utils/analysis.mdc</code> → Analiza código/carpetas y guarda en memory</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: false
---
# Analysis Protocol
Trigger: @file/@folder or "analyze"
1. Acknowledge → 2. Analyze → 3. Save to .cursor/memory/YYYYMMDD-VV-*.md → 4. Confirm</code></pre>

        <p><code>rules/utils/solution.mdc</code> → Propone solución y guarda en memory</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: false
---
# Solution Protocol (KISS)
Trigger: User requests solution
1. Acknowledge → 2. Propose simplest solution → 3. Save to memory → 4. Confirm
Principles: Simplicity > complexity, proven patterns > novel</code></pre>

        <p><code>rules/utils/backlog.mdc</code> → Convierte solución en tareas atómicas rastreables</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: false
---
# Backlog Protocol
Solution → atomic tasks → persistent backlog (YYYYMMDD-VV-backlog-*.md)

Format: [Phase.Task#] ⏳/🔄/✅/⚠️ Title
> What to do | Date completed | Work done

Rules: 2-4h max, sequential, testable</code></pre>

        <p><code>rules/utils/execute.mdc</code> → Ejecuta tareas del backlog y actualiza estado</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: false
---
# Task Execution Protocol
Load backlog → parse scope → execute → update status → stop at boundary
Input: [1.1], [2.3,2.4], Phase 2, continue</code></pre>

        <p><code>rules/utils/commit.mdc</code> → Genera commits convencionales y actualiza backlog</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">---
alwaysApply: false
---
# Commit Protocol
Analyze staged → generate conventional commit → approve → execute → update backlog
Format: [JIRA-XXX] type(scope): subject (English, imperative, max 72 chars)</code></pre>

        <h3>Memory: Registro Histórico</h3>

        <p>Los protocolos utils generan automáticamente archivos en <code>memory/</code> siguiendo la nomenclatura <code>YYYYMMDD-VV-descripcion.md</code> (VV = secuencia diaria: 01, 02, 03...):</p>

        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">memory/
├── 20250919-01-analisis-pdf-generator.md
├── 20250919-02-sistema-pdfs-emails-finalizado.md
├── 20251015-01-analisis-completo-balneario-theme.md
├── 20251015-02-solucion-facturacion-automatica-399.md
└── 20251015-03-backlog-facturacion-automatica-399.md</code></pre>

        <p>Ventajas: ordenación cronológica, múltiples entradas/día, trazabilidad, relaciones visibles.</p>

        <p>Esto resuelve el problema de las tres opciones malas de v1: la nomenclatura cronológica (YYYYMMDD-VV) acumula histórico sin descontrol, mantiene orden sin desorganización, y preserva decisiones sin sobrescritura.</p>

        <h2>Workflow en Cursor</h2>

        <blockquote>
          <p>Nota: Los comandos con <code>@</code> invocan reglas específicas. Por ejemplo, <code>@analysis</code> carga <code>rules/utils/analysis.mdc</code> sin necesidad de escribir la ruta completa. Esto es parte de la sintaxis nativa de Cursor.</p>
        </blockquote>

        <p>Esta sección describe el workflow general para desarrollo asistido por IA: separar conocimiento reutilizable de memoria temporal, siguiendo el ciclo análisis → solución → backlog → ejecución → commit → continuar. Usamos Cursor y su sistema de rules como ejemplo de implementación, pero el workflow es aplicable a cualquier herramienta de IA con capacidad de inyectar contexto.</p>

        <p>A continuación verás cómo funciona el workflow en la práctica. Si después quieres implementarlo en tus proyectos con Cursor, consulta la guía de Implementación y Configuración más abajo.</p>

        <h3>Desarrollo de feature: facturación automática</h3>

        <p>1. Análisis</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">@analysis checkout.php</code></pre>
        <p>→ Genera: <code>20251015-01-analisis-checkout.md</code></p>

        <p>2. Solución</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">@solution
Implementa facturación automática WooCommerce</code></pre>
        <p>→ Genera: <code>20251015-02-solucion-facturacion.md</code></p>

        <p>3. Backlog</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">@memory/20251015-02-solucion-facturacion
@backlog</code></pre>
        <p>→ Genera: <code>20251015-03-backlog-facturacion.md</code></p>

        <p>4. Ejecución</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">@memory/20251015-03-backlog-facturacion
@execute [1.1]</code></pre>
        <p>→ Actualiza: <code>[1.1] ⏳ → ✅</code></p>

        <p>5. Commit</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">@memory/20251015-03-backlog-facturacion
@commit</code></pre>
        <p>→ Crea commit + actualiza backlog</p>

        <p>6. Continuar trabajo (nueva sesión)</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">@memory/20251015-03-backlog-facturacion
Resume trabajo</code></pre>
        <p>→ Carga contexto + muestra próximas tareas</p>

        <h2>Implementación y Configuración</h2>

        <h3>1. Instalar el sistema (5 min)</h3>

        <p>Este sistema está disponible en <a href="https://github.com/arinspunk/extended-context" target="_blank" rel="noopener" title="Extended Context - Knowledge architecture for AI agents">github.com/arinspunk/extended-context</a>.</p>

        <p>Dos formas de configurar:</p>

        <p>Opción A - Contribuir al repo compartido (recomendado si quieres participar en el mantenimiento):</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">cd tu-proyecto
git clone https://github.com/arinspunk/extended-context.git .cursor</code></pre>
        <p>Mantiene conexión con el repo para recibir actualizaciones y contribuir mejoras. Actualiza cuando quieras: <code>cd .cursor && git pull</code></p>

        <p>Opción B - Snapshot para tu proyecto (recomendado para trabajo diario):</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">git clone https://github.com/arinspunk/extended-context.git temp
cp -r temp/rules temp/memory tu-proyecto/.cursor/
rm -rf temp</code></pre>
        <p>Copia independiente que personalizas libremente sin afectar el repo original, ideal para versionar junto con el código de tu proyecto.</p>

        <p>Migración desde v1: Usa Opción B para integrar con tu estructura existente.</p>

        <h3>2. Configuración inicial (15 min)</h3>

        <p>Pre-requisitos:</p>
        <ul>
          <li>Cursor instalado y proyecto abierto</li>
          <li>Sistema rules/memory clonado en <code>.cursor/</code> (paso anterior completado)</li>
        </ul>

        <p>Paso 1: Identifica tu stack (2 min)</p>
        <p>Revisa <code>rules/experts/</code> y activa el experto que coincida con tu proyecto:</p>
        <ul>
          <li>WordPress → <code>wordpress-classic-themes.mdc</code></li>
          <li>React → <code>react-typescript.mdc</code> (si existe)</li>
          <li>Backend Python → <code>python-fastapi.mdc</code> (si existe)</li>
        </ul>
        <p>Si tu stack no existe: copia el experto más cercano y adáptalo.</p>

        <p>Paso 2: Activa constraints del proyecto (3 min)</p>
        <ol>
          <li>Copia <code>rules/guidelines/constraints-template.mdc</code> a <code>constraints-{proyecto}.mdc</code></li>
          <li>Completa:
            <ul>
              <li>Stack técnico (versiones específicas)</li>
              <li>Dependencias críticas (librerías que NO se pueden cambiar)</li>
              <li>Sistemas legacy que debes respetar</li>
            </ul>
          </li>
          <li>Cambia <code>alwaysApply: false</code> → <code>true</code></li>
        </ol>

        <p>Paso 3: Activa principios base (1 min)</p>
        <p>Activa <code>kiss.mdc</code> cambiando <code>alwaysApply: false</code> → <code>true</code></p>

        <p>Paso 4: Verifica carga (1 min)</p>
        <p>Abre chat de Cursor (Cmd+L) y escribe:</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">¿Qué experto y guidelines tienes activas?</code></pre>
        <p>Cursor debe listar los archivos con <code>alwaysApply: true</code>.</p>

        <p>Paso 5: Primera ejecución (8 min)</p>
        <p>Prueba el workflow completo con un archivo real:</p>
        <pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">@analysis src/components/Header.tsx</code></pre>
        <p>Si genera correctamente <code>memory/YYYYMMDD-01-*.md</code>, el sistema está operativo.</p>

        <blockquote>
          <p>Nota para otras herramientas: Este sistema es agnóstico a Cursor. La separación conceptual rules/memory puede implementarse en cualquier herramienta capaz de inyectar contexto (GitHub Copilot, Claude Code, etc.).</p>
        </blockquote>

        <p>Una vez configurado el sistema, el verdadero trabajo comienza: alimentar rules con conocimiento específico del proyecto y prácticas habituales del equipo, mientras memory registra el trabajo realizado con la IA (análisis, propuestas de solución, tareas y progreso). En la práctica, esto transforma cómo la IA genera código: soluciones coherentes con la arquitectura del proyecto y escalables. Además, documenta decisiones que facilitan debug posteriores y transferencia de conocimiento entre desarrolladores.</p>

        <h2>Conclusión</h2>

        <p>El vibe-coding funciona para prototipos, pero genera más problemas que soluciones en proyectos reales: decisiones perdidas, alucinaciones constantes, trabajo imposible de rastrear. v1 resolvió esto con workflow estructurado, pero requería repetir prompts manualmente en cada sesión.</p>

        <p>v2 elimina esa fricción automatizando los protocolos y, al hacerlo, descubre un patrón universal: separar conocimiento reutilizable (rules) de memoria temporal (memory). Esta separación, la misma que hace tu cerebro entre habilidades y experiencias, convierte cualquier herramienta de IA en un sistema donde el conocimiento persiste, evoluciona y se reutiliza sistemáticamente.</p>

        <p>No elimina las limitaciones de ventana de contexto, pero las transforma en un framework estructurado para construir software de forma rastreable y escalable.</p>

        <h3>Próximos Pasos</h3>

        <ol>
          <li>Si usas Cursor: <a href="https://github.com/arinspunk/extended-context" target="_blank" rel="noopener" title="Extended Context - Knowledge architecture for AI agents">Clona el repo</a> y configura tu primer proyecto</li>
          <li>Si usas otra herramienta: Adapta la separación rules/memory a tu sistema</li>
          <li>Comparte tu implementación: ¿Creaste expertos para tu stack? Contribuye al repo</li>
          <li>Comparte resultados: ¿Mejoraste el workflow? Documenta tus hallazgos para refinar colectivamente el sistema</li>
        </ol>
]]>
      </content:encoded>
      <pubDate>Fri, 24 Oct 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>¿One-shot prompting? Prefiero conversar con mi IA</title>
      <link>https://xulioze.com/blog/oneshot-vs-dialogo.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/oneshot-vs-dialogo.html</guid>
      <description>
        El valor real de la IA no está en la generación inicial, sino en las iteraciones posteriores. La iteración no es desarrollo, es trabajo de diseño.
      </description>
      <content:encoded>
        <![CDATA[				<figure class="c-post__body-img c-post__body-img--figure">
					<img src="https://xulioze.com/img/bicentennial-man.jpg" alt="Escena de la película Bicentennial Man: un hombre trabaja en un portátil mientras dos robots humanoides dorados observan atentamente por encima de sus hombros" width="768" loading="lazy">
					<figcaption>Andrew, Galatea y Rupert Burns trabajando juntos</figcaption>
				</figure>

				<p>Hace unos días, en una conversación con compañeros, surgió el debate sobre la utilidad del one-shot prompting a la hora de generar código con IA. Yo defendía que no lo es, y el argumento que usé creo que merece ser compartido.</p>

				<h2>El problema del one-shot como objetivo</h2>

				<p>Cuando asumimos que el one-shot puede darnos los resultados esperados, estamos cargando toda la responsabilidad de la calidad del output en la parte humana: si el LLM no produce una buena respuesta, el problema es que no escribimos el prompt correcto.</p>

				<p>Pero esta idea choca frontalmente con la naturaleza de la IA generativa, que es no-determinista. Para un mismo prompt y modelo, obtenemos respuestas diferentes en cada ejecución. Por tanto, resulta imposible —sobre todo con tareas complejas— obtener la respuesta óptima en una sola interacción. La iteración se vuelve ineludible.</p>

				<p>En ese debate, con pequeños matices, todos coincidíamos en que el one-shot no es válido como fin en sí mismo, sino como ejercicio para mejorar nuestros prompts. Es imposible alcanzar el 100% de calidad, pero con esta práctica aprendemos a pasar, por decir algo, del 60% al 70%.</p>

				<h2>De Figma al código: otra perspectiva</h2>

				<p>Este fin de semana leí <a href="https://www.uxtools.co/blog/the-only-ai-workflow-i-use-in-production" title="The only AI workflow I use in production" target="_blank" rel="noopener">The only AI workflow I use in production</a>, de Tommy Geoco. El artículo describe el flujo que Tommy utiliza para desarrollar su trabajo de diseño asistido por IA (Figma → Claude Code), afirmando que supera en términos absolutos al uso de otras herramientas como Lovable, Replit o Bolt. Si eres diseñador UX/UI interesado en la integración de IA en tu trabajo, te recomiendo leerlo porque contiene ideas realmente interesantes.</p>

				<p>Entre esas ideas hay una que me ha hecho reflexionar de nuevo sobre la inconveniencia del one-shot. Según el autor, debemos desmitificarlo porque no captura el valor real. La verdadera potencia no está en la generación inicial, sino en las iteraciones posteriores.</p>

				<p>Su flujo de trabajo es el siguiente:</p>

				<ol>
					<li>Diseñar el "happy path" (flujo óptimo) en Figma</li>
					<li>Alimentar el diseño a Claude Code vía <a href="https://help.figma.com/hc/en-us/articles/32132100833559-Guide-to-the-Figma-MCP-server" title="Figma MCP server guide" target="_blank" rel="noopener">Figma MCP</a></li>
					<li>Obtener una base sólida en 15 minutos (vs. 50 horas de codificación manual)</li>
					<li>Iterar y refinar durante 50 horas</li>
				</ol>

				<p>El último punto es clave para él: la iteración no es desarrollo, es trabajo de diseño. No se trata de refinar el código para representar un diseño cerrado, sino con él tomar decisiones sobre jerarquía visual, patrones de interacción, casos extremos, estados de error, etc.</p>

				<h2>¿Y si el valor está en la iteración?</h2>

				<p>De aquí saco dos conclusiones igualmente importantes. La primera: el autor está trasladando gran parte del ejercicio de diseño de Figma al código, algo novedoso que desdibuja la frontera UX/UI-Desarrollo. No voy a desarrollarla aquí para no desviarme del tema, pero merece un post propio.</p>

				<p>La segunda, relacionada con el debate sobre one-shot: el autor no usa la IA para que diseñe por él en base a unas instrucciones iniciales, sino que se apoya en ella para iterar más rápido, reflexionar sobre el diseño de manera más profunda y conseguir un mejor resultado. Creo que no solo porque la IA le ahorra tiempo de trabajo repetitivo sin valor y lo gana para pensar, sino porque el diálogo generado puede llevarlo a lugares, pensamientos y decisiones a los que solo no habría llegado.</p>

				<p>Queda por ver si este esquema se traslada igual al desarrollo de software, pero si funciona de manera similar, entonces la inconveniencia del one-shot no se debe únicamente a las limitaciones que nos impone la naturaleza no-determinista de los LLMs. Hay algo más importante: la iteración —ese diálogo continuado entre humano e IA— nos proporciona valor real, obtenemos mejores resultados.</p>

				<p>Esta idea de la iteración como diálogo me ha hecho recordar los <a href="https://intralation-culture-theory-posthuman-pedagogy.ghost.io/attuning-orienting-and-navigating-the-co-emergence-of-meaning-in-ai-dialogue-13-propositions-for-a-critical-ai-pedagogy/" title="Attuning, Orienting, and Navigating the Co-Emergence of Meaning in AI Dialogue: 13 Propositions for a Critical AI Pedagogy" target="_blank" rel="noopener">planteamientos sobre cocreación humano–IA de Owen Matson</a>. Y tengo que reconocer que ha sido escribiendo este post —en diálogo con una IA— cuando creo que finalmente he entendido lo que Owen plantea. Queda pendiente profundizar en esta vía 🙂</p>
]]>
      </content:encoded>
      <pubDate>Mon, 13 Oct 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Usa las herramientas de formas inesperadas, también la IA</title>
      <link>https://xulioze.com/blog/usa-herramientas-formas-inesperadas-ia.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/usa-herramientas-formas-inesperadas-ia.html</guid>
      <description>No dejes de pedirle a la IA cosas que crees imposibles. Puede que te sorprenda con los resultados y aprendas algo nuevo.</description>
      <content:encoded>
        <![CDATA[				<p>Cuando trabajaba como diseñador gráfico me encantaba usar herramientas u objetos de formas para las que no habían sido creados. Como por ejemplo hacer dibujos coloreando celdas de una hoja excel o <a href="https://arinspunk.com/kraksh-disco/" title="Disco Kraksh diseñado por las Arinspunk" target="_blank" rel="noopener">escribir un texto con cinta aislante amarilla</a>.</p>

				<p>El otro día, mientras probaba <a href="https://xulioze.com/blog/claude-talk-to-figma-mcp.html" title="Cómo integrar Figma con Claude">el MCP que desarrollé para integrar Figma con Claude</a>, mi hija de 9 años me preguntó qué hacía. Yo le expliqué y ella escuchó atenta, cuando terminé me dijo:<br>
				—Dile que dibuje un monstruo enfadado.<br>
				Se lo pedí a Claude y lo dibujó.</p>

				<figure class="c-post__body-img c-post__body-img--figure">
					<img src="https://xulioze.com/img/monstruo.png" alt="Un monstruo enfadado dibujado por una IA en Figma" width="768" loading="lazy">
					<figcaption>Monstruo enfadado dibujado con Figma por Claude Sonnet 3.7</figcaption>
				</figure>


				<p>Desde hace un tiempo <a href="https://xulioze.com/blog/guia-desarrollar-software-agentes.html" title="desarrollar software de calidad asistido por agentes de IA">estoy usando la IA de forma intensiva en mi trabajo</a> y una de las cosas de las que me he dado cuenta es que no hay que dejar de pedirle algo porque creemos que no lo puede hacer. Tú pide sin más, verás cómo muchas veces te sorprenderá con la solución propuesta y aprenderás algo nuevo.</p>

				<p>Hoy trabajando con Figma + Cursor me acordé de mi hija y le pedí al agente que dibujase un dragón.</p>
				
				<figure class="c-post__body-img c-post__body-img--figure">
					<img src="https://xulioze.com/img/dragon-og.png" alt="Un dragón echando fuego dibujado por una IA en Figma" width="768" loading="lazy">
					<figcaption>Encantador dragón dibujado con Figma por Claude Sonnet 4</figcaption>
				</figure>

				
				<p>Creo que voy a volver a la afición que tenía  <a href="https://arinspunk.com/" title="Archivo de las difuntas Arinspunk" target="_blank" rel="noopener">cuando era diseñador</a> 😊</p>
]]>
      </content:encoded>
      <pubDate>Wed, 30 Jul 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Guía: integrar Figma en flujos de trabajo con IA</title>
      <link>https://xulioze.com/blog/guia-integrar-figma-con-ia.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/guia-integrar-figma-con-ia.html</guid>
      <description>
        Aprende a integrar Figma en tus flujos de trabajo de IA con la API de Figma, Dev Mode MCP Server y Claude Talk to Figma MCP. Guía para equipos de desarrollo y diseño.
      </description>
      <content:encoded>
        <![CDATA[                <img class="c-post__body-img" src="https://xulioze.com/img/ex-machina.jpg" alt="Ava shows her drawing" width="768" loading="lazy">

                <h2>Propósito</h2>
                <p>Permitir a los LLMs:</p>
                <ul>
                    <li>Analizar y modificar diseños en Figma.</li>
                    <li>Generar código a partir de ellos.</li>
                </ul>

                <h2>A quién va dirigido</h2>
                <p>Equipos de UX/UI que quieren automatizar auditorías de accesibilidad, realizar tests de usuario sintéticos y iterar diseños basándose en feedback automatizado.</p>
                <p>Equipos de Frontend que necesitan acelerar la traducción de diseños a código, especialmente cuando trabajan con sistemas de componentes y frameworks modernos.</p>
                <p>Equipos de Backend/DevOps que desarrollan workflows automatizados y agentes IA que requieren integrar análisis de diseños en Figma y generación de código a partir de ellos.</p>
                <p>Equipos multidisciplinarios que buscan reducir la fricción en el handoff entre diseño y desarrollo, manteniendo cada equipo en su herramientas habituales.</p>

                <h2>Herramientas</h2>
                
				<div class="c-post__table">
					<table>
						<thead>
							<tr>
								<th>Herramienta</th>
								<th>Funcionalidad</th>
								<th>Uso recomendado</th>
								<th>Equipo objetivo</th>
								<th>Entorno de uso</th>
							</tr>
						</thead>
						<tbody>
							<tr>
								<td>
									<a href="https://xulioze.com/blog/guia-integrar-figma-con-ia.html#api-figma" title="API de Figma">API de Figma</a>
								</td>
								<td>
									Análisis de diseños + generación de código
								</td>
								<td>
									Integración de Figma en flujos de trabajo de agentes IA
								</td>
								<td>
									Equipos de backend que desarrollan flujos de trabajo de agentes IA
								</td>
								<td>
									ADK, Crew AI, LangGraph, etc.
								</td>
							</tr>
							<tr>
								<td>
									<a href="https://xulioze.com/blog/guia-integrar-figma-con-ia.html#dev-mode-mcp-server" title="Dev Mode MCP Server">Dev Mode MCP Server</a>
								</td>
								<td>
									Análisis de diseños + generación de código
								</td>
								<td>
									Generación de código a partir de diseños en Figma
								</td>
								<td>
									Equipos de frontend
								</td>
								<td>
									Cursor, VS Code + Github Copilot, Windsurf, Claude Code, etc.
								</td>
							</tr>
							<tr>
								<td>
									<a href="https://xulioze.com/blog/guia-integrar-figma-con-ia.html#claude-talk-to-figma-mcp" title="Claude Talk to Figma MCP">Claude Talk to Figma MCP</a>
								</td>
								<td>
									Análisis y modificación de diseños
								</td>
								<td>
									Tests de usuarios (sintéticos), auditorías de accesibilidad y SEO, y modificación de diseños
								</td>
								<td>
									Equipos de UX/UI
								</td>
								<td>
									Claude
								</td>
							</tr>
						</tbody>
					</table>
				</div>
                
                <h3 id="api-figma">API de Figma</h3>
                <h4>Requisitos</h4>
                <ul>
                    <li>Cuenta de Figma</li>
                    <li>Generar un <a href="https://www.figma.com/developers/api#access-tokens" target="_blank" rel="noopener" title="'Access tokens' en la documentación de Figma">token de acceso</a> o usar <a href="https://www.figma.com/developers/api#oauth2" target="_blank" rel="noopener" title="'OAuth 2' en la documentación de Figma">OAuth 2</a></li>
                </ul>
                <h4>Descripción</h4>
                <p>Es la vía más simple para que un LLM analice un diseño.</p>
                <p>La API de Figma permite construir endpoints para solicitar archivos, imágenes, versiones de archivos, usuarios, comentarios, proyectos de equipo y archivos de proyecto. Devuelve un JSON que podemos pasar al LLM para que lo interprete.</p>
                <p>A diferencia de los MCPs, no necesitamos tener abierto Figma Desktop para que un agente analice un diseño. Esto la convierte en el método idóneo para integrar Figma en flujos de trabajo de agentes IA.</p>
                <h4>Instalación</h4>
                <p>Al tratarse de una API, no de un MCP, no existe una instalación como tal. Podemos ver cómo funciona con una prueba simple con Cursor o VS Code:</p>
                <ol>
                    <li><a href="https://www.figma.com/developers/api#access-tokens" target="_blank" rel="noopener" title="'Access tokens' en la documentación de Figma">Crea un token</a>.</li>
                    <li>Dile a tu agente que analice un diseño en Figma ejecutando <a href="https://www.figma.com/developers/api#get-file-nodes-endpoint" target="_blank" rel="noopener" title="'GET file nodes' en la documentación de Figma">una petición curl de un endpoint</a>.</li>
                </ol>
                <p>Por ejemplo, para la siguiente URL de un nodo de un diseño:</p>
<pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">https://www.figma.com/design/XG1EYHLnC7NdwGuYc7LmUf/MVC---WEB?node-id=6037-2235&t=AHpchSRAIyGCdoci-0</code></pre>
                <p>dile que use:</p>
<pre class="c-post__prompt c-post__prompt--scroll"><button class="c-post__copy-btn" aria-label="Copiar código"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#fff" viewBox="0 -960 960 960"><path d="M362.31-260q-27.01 0-45.66-18.65T298-324.31v-455.38q0-27.01 18.65-45.66T362.31-844h359.38q27.01 0 45.66 18.65T786-779.69v455.38q0 27.01-18.65 45.66T721.69-260zm0-52h359.38q4.62 0 8.46-3.85 3.85-3.84 3.85-8.46v-455.38q0-4.62-3.85-8.46-3.84-3.85-8.46-3.85H362.31q-4.62 0-8.46 3.85-3.85 3.84-3.85 8.46v455.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85m-124 176q-27.01 0-45.66-18.65T174-200.31v-507.38h52v507.38q0 4.62 3.85 8.46 3.84 3.85 8.46 3.85h411.38v52zM350-312v-480z"/></svg></button><code class="c-post__prompt-code">curl -H 'X-FIGMA-TOKEN: {your personal access token}'
'https://api.figma.com/v1/files/XG1EYHLnC7NdwGuYc7LmUf/nodes?ids=6037-2235'</code></pre>
                <p>Al recibir el prompt, el agente ejecutará la petición curl y obtendrá un JSON con los parámetros del diseño. Luego lo analizará y generará un texto con el contenido de su análisis.</p>
                
                <h3 id="dev-mode-mcp-server">Dev Mode MCP Server</h3>
                <h4>Requisitos</h4>
                <ul>
                    <li><a href="https://help.figma.com/hc/en-us/articles/27468498501527-Updates-to-Figma-s-pricing-seats-and-billing-experience#h_01JCPBM8X2MBEXTABDM92HWZG4" target="_blank" rel="noopener" title="descripciones de los 'seats' de Figma">Dev o Full seat</a> en los <a href="https://help.figma.com/hc/en-us/articles/360040328273-Figma-plans-and-features" target="_blank" rel="noopener" title="Figma plans and features">planes Professional, Organization o Enterprise</a>.</li>
                    <li>Un editor de código o aplicación que soporte MCP Servers (<a href="https://code.visualstudio.com/docs/copilot/overview" target="_blank" rel="noopener" title="GitHub Copilot en VS Code">VS Code</a>, <a href="https://www.cursor.com/" target="_blank" rel="noopener" title="Página oficial de Cursor">Cursor</a>, <a href="https://windsurf.dev/" target="_blank" rel="noopener" title="Página oficial de Windsurf">Windsurf</a>, <a href="https://docs.anthropic.com/en/docs/claude-code/overview" target="_blank" rel="noopener" title="Página oficial de Claude Code">Claude Code</a>).</li>
                    <li><a href="https://www.figma.com/downloads/" target="_blank" rel="noopener" title="Descargas de Figma">Figma Desktop App</a></li>
                </ul>
                <h4>Descripción</h4>
                <p>Se trata del servidor MCP oficial de Figma.</p>
                <p>Habilita varias herramientas de análisis (5 a la fecha de publicación de este post) que los agentes pueden usar para generar código a partir de un diseño.</p>
                <p>Las herramientas que permiten "ver" un diseño son <code>get_code</code> y <code>get_image</code>. A diferencia de la API de Figma, <code>get_code</code> no devuelve un JSON con los datos del diseño, sino una traducción del diseño a React que genera al vuelo Dev Mode.</p>
                <p>Esto facilita al LLM la generación de código aunque no sea React, ya que la distancia entre React y otro framework/lenguaje es menor que entre la información del JSON y nuestro framework/lenguaje.</p>
                <p><code>get_image</code> crea una captura de pantalla del diseño seleccionado y sirve de apoyo al agente a la hora de generar código.</p>
                <h4>Instalación</h4>
                <ol>
                    <li><a href="https://help.figma.com/hc/en-us/articles/32132100833559-Guide-to-the-Dev-Mode-MCP-Server#h_01K25F7RBP00A3VH1733692QN2" target="_blank" rel="noopener" title="Step 1: Enable the MCP Server">Activación en Figma Desktop App</a></li>
                    <li><a href="https://help.figma.com/hc/en-us/articles/32132100833559-Guide-to-the-Dev-Mode-MCP-Server#h_01K25F7RBRZKCATVJHNXCS6KXW" target="_blank" rel="noopener" title="Step 2: Set up your MCP client">Instalación en nuestro editor de código</a> (Cursor, VS Code, Windsurf, Claude Code, Others)</li>
                </ol>

                <h3 id="claude-talk-to-figma-mcp">Claude Talk to Figma MCP</h3>
                <h4>Requisitos</h4>
                <ul>
                    <li><a href="https://claude.ai/download" target="_blank" rel="noopener" title="Página de descarga de Claude Desktop">Claude Desktop</a></li>
                    <li><a href="https://www.figma.com/downloads/" target="_blank" rel="noopener" title="Descargas de Figma">Figma Desktop</a></li>
                    <li><a href="https://bun.sh/" target="_blank" rel="noopener" title="Página oficial de Bun">Bun</a> instalado</li>
                </ul>
                <h4>Descripción</h4>
                <p>MCP server de código abierto.</p>
                <p>Habilita un conjunto amplio de herramientas (43 a la fecha de publicación de este post) que permite a los agentes analizar y también modificar diseños en Figma.</p>
                <p>Las herramientas que permiten "ver" un diseño devuelven un JSON con sus datos. Esto permite a los LLMs analizarlo mediante "thinking aloud", evaluación crítica, test de usuario, auditoría de accesibilidad, auditoría de SEO, etc.</p>
                <p>Con las herramientas de modificación, el LLM puede después aplicar los cambios propuestos en el análisis.</p>
                <h4>Instalación</h4>
                <p>Sigue las instrucciones de la <a href="https://github.com/arinspunk/claude-talk-to-figma-mcp/tree/main?tab=readme-ov-file#-installation" target="_blank" rel="noopener" title="Instalación de Claude Talk to Figma MCP">documentación oficial</a>.</p>
                
                <h2>Comparte tu experiencia</h2>
                <p>Si ya estás integrando Figma en tu flujo de trabajo con IA, ya sea con estas u otras herramientas, me encantaría conocer tu experiencia:</p>
                <ul>
                    <li>Cómo ha ido su instalación.</li>
					<li>Experimentos y descubrimientos.</li>
                    <li>Casos de uso reales.</li>
                    <li>Resultados obtenidos.</li>
                </ul>
                <p>El ecosistema de IA + diseño/desarrollo está en constante evolución y las mejores prácticas emergen de la experiencia colectiva de quienes las implementan en proyectos reales ✊</p>
                <p>Si todavía no lo has hecho, atrévete con alguna de las herramientas de este post. Si algo se te atasca, puedes escribirme en mi <a href="https://www.linkedin.com/in/xulioze/" target="_blank" rel="noopener" title="Perfil de LinkedIn">perfil de LinkedIn</a> 😉</p>
]]>
      </content:encoded>
      <pubDate>Thu, 24 Jul 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Prompt, Contexto y memoria</title>
      <link>https://xulioze.com/blog/prompt-contexto-memoria.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/prompt-contexto-memoria.html</guid>
      <description>Los tres pilares fundamentales de cualquier interacción con modelos de lenguaje IA.</description>
      <content:encoded>
        <![CDATA[				<p>Empecé a usar IA en mi trabajo como desarrollador de software hace algo más de 2 años. <a href="https://xulioze.com/blog/construir-pwa-con-chatgpt.html" title="Mi experiencia inicial con ChatGPT para construir una PWA">Con ChatGPT y de manera tosca</a>, igual que la mayoría, imagino 😅</p>

				<p>A lo largo de este tiempo <a href="https://xulioze.com/blog/como-hablar-con-chatgpt.html" title="Guía sobre cómo comunicarse efectivamente con ChatGPT">refiné mi conversación con LLMs</a>, comencé a usar asistentes de código (GitHub Copilot) y después asistentes con agentes (Cursor) e incluso desarrollé sistemas de agentes con frameworks como CrewAI. Pero no ha sido hasta ahora que he entendido de forma clara que cualquier interacción con modelos de lenguaje, <a href="https://xulioze.com/blog/desarrollo-con-ia.html" title="Reflexiones sobre el desarrollo de software con inteligencia artificial">no importa que herramienta usemos</a>, se resume en tres puntos fundamentales: prompt, contexto y memoria.</p>

				<h2>Prompt</h2>

				<p>A través del prompt creamos el experto que necesitamos para una determinada tarea, le indicamos qué hay que hacer y también qué no hay que hacer. Es el medio del que disponemos para alcanzar el resultado deseado.</p>

				<p>Para escribir el prompt adecuado para cada tarea, tenemos la <a href="https://www.promptingguide.ai/es" title="Guía completa de ingeniería de prompts">ingeniería de prompts</a>. Conocer sus principales técnicas es importante, pero lo que de verdad hace que mejoremos, es la práctica continua con los LLMs, nuestra conversación con la IA.</p>

				<h2>Contexto</h2>

				<p>Los grandes modelos de lenguaje disponen de un vasto conocimiento, pero para determinadas tareas este no es suficiente. Proporcionarle contexto adicional se convierte en una necesidad ineludible.</p>

				<p>Para dar contexto disponemos de diferentes vías, desde la simple inclusión de información relevante en el prompt, pasando por añadir documentos de referencia hasta <a href="https://www.anthropic.com/news/model-context-protocol" title="MCP explicado por Anthropic">el uso de MCPs</a> que permiten a los LLMs acceder al contenido de múltiples plataformas (Jira, Drive, etc.) y herramientas (<a href="https://xulioze.com/blog/claude-talk-to-figma-mcp.html" title="Cómo hacer que Claude se comunique con Figma usando MCP">Figma</a>, Draw.io, etc.).</p>

				<h2>Memoria</h2>

				<p>Los LLMs tienen la capacidad de recordar nuestras conversaciones, pero esta memoria tiene un límite (<a href="https://www.ibm.com/es-es/think/topics/context-window" title="Explicación sobre el límite de la ventana de contexto en LLMs">límite de la ventana de contexto</a>). Cuanto más compleja es la tarea a desarrollar, con mayor probabilidad superamos este límite y más necesario se hace extender la memoria del LLM.</p>

				<p>Existen diferenetes técnicas para ampliar la memoria de los LLMs, algunas bastante sofisticadas como el uso de bases de datos clásicas y <a href="https://xulioze.com/blog/bases-datos-vectoriales-introduccion.html" title="Introducción a las bases de datos vectoriales">vectoriales</a>, pero la forma más sencilla de hacerlo es introduciendo en nuestras rutinas estrategias de <a href="https://xulioze.com/blog/contexto-extendido.html" title="Estrategias para extender el contexto y memoria de los LLMs">contexto/memoria extendida</a>.</p>

				<img class="c-post__body-img" src="https://xulioze.com/img/prompt-contexto-memoria.jpg" alt="Frank y el robot hablando" width="900" height="383" loading="lazy">

				<h2>En perspectiva</h2>

				<p>Prompt, contexto y memoria. Es decir, las instrucciones correctas para lograr el objetivo deseado, la información necesaria para entender el proyecto y su objetivo, y el registro del trabajo completado (cuándo, cómo, dónde y por qué).</p>

				<p>Si lo piensas por un momento, no es muy diferente de lo que los humanos necesitamos para desarrollar cualquier tarea compleja. Realmente cada vez que profundizamos en el uso de la IA nos encontramos con situaciones en las que vemos un paralelismo claro entre la forma en que los LLMs trabajan y la nuestra. No en vano estamos entrando en una era donde ya no "hablamos" con las máquinas a través de código, sino que hablamos con las máquinas de forma natural. <a href="https://www.youtube.com/watch?v=YBPOguI-AFI&ab_channel=ChandanDatta" target="_blank" rel="noopener" title="Conversación de Frank con su robot">Algo que Frank ya descubrió hace más de 10 años</a> 😎🤖.</p>
]]>
      </content:encoded>
      <pubDate>Wed, 25 Jun 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Guía: desarrollar software de calidad asistido por agentes de IA</title>
      <link>https://xulioze.com/blog/guia-desarrollar-software-agentes.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/guia-desarrollar-software-agentes.html</guid>
      <description>
        Una guía completa para implementar estrategias de contexto extendido que permiten desarrollar proyectos complejos con agentes IA manteniendo coherencia y calidad.
      </description>
      <content:encoded>
        <![CDATA[				<img class="c-post__body-img" src="https://xulioze.com/img/extended-context-guide.jpg" alt="pantalla con notas"  width="900" height="383" loading="lazy">

				<p>Esta guía es una versión mejorada de la que propuse inicialmente en "<a href="https://xulioze.com/blog/contexto-extendido.html" title="Contexto extendido. Los agentes también necesitan tomar notas">Contexto extendido. Los agentes también necesitan tomar notas</a>".</p>

				<p>Su propósito es implementar una estrategia que nos permite desarrollar proyectos complejos asistidos por agentes sin perder la coherencia y calidad del código generado.</p>

				<p>Su redacción está orientada para su uso con herramientas como Cursor o GitHub Copilot, pero se puede adaptar de forma simple a muchas otras.</p>

				<h2>Estructura del Sistema de Contexto</h2>

				<p>Para implementar esta estrategia, creamos una carpeta <code>context/</code> en la raíz del proyecto con la siguiente estructura:</p>

				<pre class="c-post__prompt"><code class="c-post__prompt-code">context/
├── 01-expert.md      # Definición de experto sintético
├── 02-analysis.md    # Análisis del código existente (vacío)
├── 03-plan.md        # Plan maestro de desarrollo (vacío)
└── 04-backlog.md     # Tareas desglosadas y su estado (vacío)</code></pre>

				<h2>Paso 1: Definición del Experto Sintético</h2>

				<p>El primer paso consiste en definir un "experto sintético": un rol específico con competencias y restricciones claras que guiará al agente de IA durante todo el desarrollo.</p>

				<h3>Prompt para el agente:</h3>

				<pre class="c-post__prompt"><code class="c-post__prompt-code">Lee el archivo `context/01-expert.md` para entender tu rol en el proyecto.

No generes código hasta recibir requisitos específicos.</code></pre>				

				<h3>Ejemplo de contenido para <code>context/01-expert.md</code>:</h3>

				<pre class="c-post__prompt"><code class="c-post__prompt-code"># SUDO: Actúa como un Experto Senior en Desarrollo Frontend especializado en HTML5, CSS3/SCSS y JavaScript ES6+.

## ROL
Desarrollador Frontend Senior (10+ años) experto en HTML5 semántico, CSS3/SCSS avanzado con metodologías BEM e ITCSS, y JavaScript ES6+ moderno, con enfoque en arquitectura de componentes, rendimiento y accesibilidad.

## COMPETENCIAS_TÉCNICAS

- HTML5 semántico y accesibilidad (ARIA, WCAG 2.1)
- CSS3 avanzado (Grid, Flexbox, animaciones, propiedades personalizadas)
- SCSS/Sass con arquitectura ITCSS (Triángulo Invertido CSS)
- Metodología BEM estricta (Bloque__Elemento--Modificador)
- JavaScript ES6+ (async/await, módulos, destructuring, clases)
- Gestión de estado y arquitectura de componentes
- Optimización de rendimiento web (Core Web Vitals)
- Testing unitario y de integración
- Herramientas de construcción modernas (Vite, Webpack)

## PRINCIPIOS_DE_TRABAJO

- Código limpio y mantenible siguiendo principios SOLID
- Documentación clara y concisa
- Enfoque mobile-first y responsive
- Mejora progresiva
- Semántica antes que presentación

## RESTRICCIONES

- Evitar jQuery y librerías legacy salvo requerimiento específico
- Mantener compatibilidad con navegadores modernos (últimas 2 versiones)
- Priorizar soluciones nativas sobre dependencias externas
- No generar código hasta recibir requisitos específicos</code></pre>

				<p>⚠️ Importante: La última restricción ("No generar código hasta recibir requisitos específicos") es fundamental, los modelos son muy proactivos 😅</p>

				<h2>Paso 2: Análisis del Código del Proyecto</h2>

				<p>Este paso solo es necesario para proyectos existentes. Si estás empezando un proyecto desde cero, puedes omitirlo.</p>

				<p>Ahora pedimos al agente que analice el código del proyecto y guarde su análisis en <code>context/02-analysis.md</code></p>

				<h3>Prompt para el agente:</h3>

				<pre class="c-post__prompt"><code class="c-post__prompt-code">Analiza en profundidad el código actual del proyecto. Excluye la carpeta `context/` del análisis.

Guarda el resultado del análisis en `context/02-analysis.md` con la siguiente estructura:
- Resumen ejecutivo
- Arquitectura actual
- Tecnologías utilizadas
- Patrones identificados
- Áreas de mejora potencial
- Dependencias críticas

Al terminar, espera instrucciones adicionales sin realizar ninguna acción.</code></pre>

				<p>⚠️ Importante: No dudes en iterar con el agente si no estás satisfecho con su primer análisis.</p>

				<h2>Paso 3: Creación del Plan Maestro</h2>

				<p>Una vez analizado el código, explicamos al agente qué queremos desarrollar y le pedimos que defina un plan maestro que debe guardarse en <code>context/03-plan.md</code></p>

				<p>El plan maestro es el documento fundamental que guiará todo el desarrollo. Tómate el tiempo necesario para definir claramente los requisitos y objetivos.</p>

				<h3>Prompt para el agente:</h3>

				<pre class="c-post__prompt"><code class="c-post__prompt-code">Basándote en los siguientes requisitos, crea un plan maestro detallado para el desarrollo:

[REQUISITOS DEL PROYECTO]

Necesito crear un servicio REST que procese imágenes por lotes. El servicio debe:

- Recibir múltiples imágenes en una sola petición
- Redimensionar imágenes según parámetros configurables
- Comprimir y optimizar para web
- Devolver imágenes procesadas en formato WebP
- Implementar caché para optimizar recursos
- Proporcionar endpoints para consultar estado de procesamiento

Consideraciones técnicas:

- Usar Bun por su rendimiento en operaciones intensivas
- Evaluar compatibilidad con librerías de procesamiento de imágenes
- Implementar procesamiento asíncrono para lotes grandes
- Incluir validación robusta de entrada

[FIN DE REQUISITOS]

Crea un plan maestro estructurado y guárdalo en `context/03-plan.md`.

Al terminar, espera instrucciones adicionales.</code></pre>

				<p>⚠️ Importante: Continúa dialogando con el agente si ves que al plan le falta o le sobra algo.</p>

				<h2>Paso 4: Creación del Backlog Detallado</h2>

				<p>En este punto pedimos al agente que transforme el plan maestro en tareas ejecutables, lo más pequeñas y específicas posible. Tareas más granulares resultan en código de mayor calidad.</p>

				<h3>Prompt para el agente:</h3>

				<pre class="c-post__prompt"><code class="c-post__prompt-code">Divide el plan maestro en tareas atómicas siguiendo estos criterios:

- Descripción detallada de requisitos técnicos
- Dependencias claramente identificadas

Guarda la lista en `context/04-backlog.md` con esta estructura:

# Backlog de Tareas - [Nombre del Proyecto]

## Resumen del Proyecto
[Breve descripción e implementación del plan en `context/03-plan.md`]

## Estado de Tareas

### FASE 1: [TÍTULO DE FASE]

- **1.1** ⏳ [título de tarea]
	- **Descripción detallada**:
	- **Dependencias**:
	- **Fecha**: 
	- **Trabajo realizado**: 

- **1.2** ⏳ [título de tarea]
	- **Descripción detallada**:
	- **Dependencias**:
	- **Fecha**: 
	- **Trabajo realizado**:

### FASE 2: [TÍTULO DE FASE]
[Continúa con el mismo formato...]

## Leyenda de Estados
- ⏳ Pendiente
- 🔄 En progreso
- ✅ Completada
- ⚠️ Bloqueada

## Notas y Dependencias
[Información adicional relevante]

## Seguimiento del Progreso
- Tareas totales: 0
- Tareas completadas: 0
- Progreso: 0%

Al terminar, espera instrucciones adicionales</code></pre>

				<p>⚠️ Importante: Es necesario indicar al LLM la estructura de backlog que queremos, si no se vuelve creativo 😬</p>

				<h2>Paso 5: Ejecución de Tareas</h2>

				<p>Con el backlog definido, procedemos a ejecutar tareas de manera sistemática.</p>

				<h3>Prompt para ejecutar una tarea:</h3>

				<pre class="c-post__prompt"><code class="c-post__prompt-code">Ejecuta la tarea 1.1 del backlog (`context/04-backlog.md`) siguiendo estrictamente su descripción.

Contexto adicional disponible en:
- `context/02-analysis.md` (si existe)
- `context/03-plan.md`

Requisitos de ejecución:
- Usar herramientas del agente para crear archivos y carpetas (no la terminal)
- Seguir convenciones establecidas en el prompt inicial
- Documentar código según estándares definidos
- No realizar acciones fuera del ámbito de la tarea

Al completar:
1. Actualizar estado de la tarea en `context/04-backlog.md`:
	- Cambiar estado a ✅
	- Añadir fecha de finalización
	- Describir trabajo realizado
	- Actualizar Seguimiento del Progreso
2. Esperar instrucciones adicionales sin ejecutar más tareas</code></pre>

				<p>⚠️ Importante: Es necesario pedir al LLM que no haga nada más de lo indicado en la tarea para evitar que se extralimite.</p>

				<h2>Paso 6: Reinicio de Ventana de Contexto</h2>

				<p>Para mantener la calidad y coherencia, es necesario reiniciar periódicamente la ventana de contexto.</p>

				<p>Es evidente que debemos reiniciar la ventana de contexto cuando notemos que el agente empieza a "perder el norte". Pero el enfoque óptimo es no llegar nunca a este punto y abrir un chat nuevo:</p>

				<ul>
					<li>Cada 4-6 tareas completadas</li>
					<li>Al cambiar de fase (el backlog de nuestro ejemplo está estructurado en fases que se dividen en tareas).</li>
				</ul>

				<h3>Prompt para reiniciar:</h3>

				<pre class="c-post__prompt"><code class="c-post__prompt-code">Instrucciones iniciales:

1. Lee `context/01-expert.md` para entender tu rol en este proyecto
2. Lee `context/02-analysis.md` para conocer el estado actual del código
3. Lee `context/03-plan.md` para entender los objetivos
4. Lee `context/04-backlog.md` para ver el progreso y tareas pendientes

Proporciona un breve resumen de:

- Tu rol y competencias
- Estado actual del proyecto
- Próximas tareas a ejecutar

Al terminar, espera instrucciones adicionales.</code></pre>

				<h2>Automatización con Atajos</h2>

				<p>Tanto GitHub Copilot como Cursor permiten crear atajos personalizados para prompts frecuentes:</p>

				<h3>GitHub Copilot</h3>
				<ul>
					<li>
						<a href="https://code.visualstudio.com/docs/copilot/copilot-customization#_instruction-files" target="_blank" rel="noopener" title="Custom instructions (VSCode)">
							Instructions
						</a>
					</li>
					<li>
						<a href="https://code.visualstudio.com/docs/copilot/copilot-customization#_prompt-files-experimental" target="_blank" rel="noopener" title="Custom prompts (VSCode)">
							Prompts
						</a>
					</li>
				</ul>

				<h3>Cursor</h3>
				<ul>
					<li>
						<a href="https://docs.cursor.com/context/rules" target="_blank" rel="noopener" title="Custom rules (Cursor)">
							Rules
						</a>
					</li>
				</ul>

				<h2>Beneficios del Sistema</h2>

				<p>Esta estrategia de gestión de contexto transforma la limitación de la ventana de contexto de un obstáculo en una oportunidad para trabajar de manera más estructurada y eficiente. Los principales beneficios incluyen:</p>

				<ul>
					<li>Continuidad: Mantener el progreso sin perder información crítica</li>
					<li>Calidad consistente: El agente mantiene el mismo nivel de detalle y precisión</li>
					<li>Trazabilidad: Registro completo de decisiones y evolución del proyecto</li>
					<li>Mejor colaboración: Facilita el trabajo en equipo y la incorporación de nuevos miembros</li>
				</ul>

				<h2>Conclusión</h2>

				<p>Al implementar este sistema, no solo evitas las limitaciones técnicas de los LLM sino que estableces una metodología de desarrollo más profesional y escalable para proyectos asistidos por IA.</p>

				<hr>

				<p>¿Preguntas o sugerencias? Comparte tu experiencia implementando esta estrategia y ayuda a mejorar la guía para la comunidad.</p>
]]>
      </content:encoded>
      <pubDate>Sun, 25 May 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Contexto extendido. Los agentes también necesitan tomar notas</title>
      <link>https://xulioze.com/blog/contexto-extendido.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/contexto-extendido.html</guid>
      <description>
        Descubre la estrategia de 'contexto extendido' para mantener coherencia en proyectos complejos con agentes IA usando archivos markdown como memoria externa para tus LLMs.
      </description>
      <content:encoded>
        <![CDATA[				<img class="c-post__body-img" src="https://xulioze.com/img/extended-context-her.jpg" alt="pantalla con notas a mano" width="768" loading="lazy">

				<p>El propósito de este post es describir una estrategia de ampliación de contexto en el desarrollo de proyectos complejos con agentes. Pero como no solo los LLMs necesitan contexto para comprender ideas, comienzo con un poco de contexto para humanos.</p>

				<p><em>Si tienes prisa y pasas de contexto previo, <a href="https://xulioze.com/blog/contexto-extendido.html#contexto-extendido">adelante</a> y no te preocupes, nadie sabrá que has tenido este mini ataque de holgazanería </em> 😬</p>

				<h2>Contexto para humanos</h2>

				<p>La aparición de los agentes en los asistentes de código ha supuesto un salto enorme en el desarrollo de software asistido por IA.</p>

				<p>Lo primero que llama la atención es su capacidad para iterar de forma automática sobre sus propias respuestas, crear/modificar archivos y correr comandos en la terminal. Pero creo que la habilidad que realmente marca la diferencia es que son capaces de indexar y analizar el código de un proyecto, incluídas las dependencias entre archivos y las relaciones entre sus componentes.</p>

				<p>Si los asistentes nos permitían trabajar a nivel archivo, con la aparición de los agentes hemos pasado a trabajar a nivel arquitectura. Ahora la IA no sólo nos ayuda en la escritura/fixing de partes de nuestro código, si no que nos asiste en la construcción de proyectos completos (a una velocidad que a veces da vértigo).</p>

				<p>Pero este aumento en la complejidad de las tareas desarrolladas provoca algo que antes era difícil de ver, llevamos al límite la ventana de contexto de los propios agentes. Desarrollar un proyecto completo requiere muchas tareas, por lo que llegado a un punto el agente empieza a olvidar partes de la conversación, haciendo muy difícil (por no decir imposible) mantener la coherencia del trabajo que estamos realizando.</p>

				<p>Cuando ocurre esto lo más normal es abrir un nuevo chat para reiniciar la ventana de contexto, pero, ¿cómo llevamos al agente al punto en el que estábamos? ¿Cómo hacerle recordar que había construido ya y que le queda por desarrollar?</p>

				<p>En mi caso estoy usando una estrategia a la que he llegado a partir de mis interacciones con Cursor primero y GitHub Copilot Agent Mode después y a la que llamo Contexto Extendido. Vale, sé que no soy muy original, pero creo que expresa decentemente la idea 🤓</p>

				<h2 id="contexto-extendido">Contexto extendido (usando markdowns como memoria)</h2>

				<p>Esta estrategia se basa en el almacenamiento de archivos markdown con información del proyecto en una carpeta llamada <code>context/</code></p>

				<p>La idea es crear una memoria a la que el agente (o nosotros) puede recurrir en todo momento permitiéndole saber en qué punto está y qué le queda por hacer.</p>
				
				<p>Gracias a esta memoria podemos dividir el trabajo en tareas pequeñas y usar tantos chats como sean necesarios para evitar alcanzar el límite de la ventana de contexto. Manteniendo de esta forma la coherencia y calidad del trabajo de principio a fin.</p>

				<h3>Esquema de trabajo</h3>

				<p>En la siguiente imagen se resume el esquema de trabajo.</p>

				<img class="c-post__body-img" src="https://xulioze.com/img/extended-context.png" alt="Esquema de trabajo con 3 chats" width="840" loading="lazy">

				<p>Chat 0</p>

				<ol>
					<li>Prompt para crear un experto sintético en la tecnología del proyecto: rol, experiencia, stack técnico, forma de razonamiento y formato de respuesta. Finalizado con un "no escribas código aun".</li>
					<li>Prompt donde pedimos que:
						<ul>
							<li>analice el código del proyecto,</li>
							<li>genere un informe de su análisis,</li>
							<li>y lo guarde en formato <code>.md</code> dentro de la carpeta <code>context/</code> con un 00- delante del nombre del archivo.
							Si el informe no nos gusta del todo, podemos iterar sobre él hasta quedar satisfechos.</li>
						</ul>
					</li>
					<li>Prompt donde:
						<ul>
							<li>indicamos qué queremos hacer (requisitos),</li>
							<li>pedimos que genere un plan maestro,</li>
							<li>y lo guarde en formato <code>.md</code> dentro de la carpeta <code>context/</code> con un 01- delante del nombre del archivo.
							Al igual que con el análisis, podemos iterar sobre él hasta quedar satisfechos.</li>
						</ul>
					</li>
				</ol>

				<p>Chat 1</p>

				<ol>
					<li>Mismo prompt para creación de experto sintético.</li>
					<li>Prompt pidiendo que lea e interiorice el análisis del proyecto.</li>
					<li>Prompt pidiendo que lea e interiorice el plan maestro.</li>
					<li>Prompt pidiendo que ejecute el punto 1 del plan maestro.</li>
					<li>Iteración normal hasta terminar el punto 1.</li>
					<li>Prompt pidiendo que documente el trabajo desarrollado en el punto 1. en un <code>.md</code> dentro de <code>context/</code> siguiendo la numeración actual y que marque el punto como resuelto en el plan maestro.</li>
				</ol>

				<p>Chat n</p>

				<ol>
					<li>Mismo prompt para creación de experto sintético</li>
					<li>Prompt pidiendo que lea e interiorice el análisis del proyecto</li>
					<li>Prompt pidiendo que lea e interiorice el plan maestro</li>
					<li>Prompt pidiendo que ejecute el punto n del plan maestro</li>
					<li>Iteración normal hasta terminar el punto n.</li>
					<li>Prompt pidiendo que documente el trabajo desarrollado en el punto n. dentro del <code>.md</code> de documentación creado anteriormente y que marque el punto como resuelto en el plan maestro.</li>
				</ol>

				<p>Evidentemente, este esquema se trata de una base de trabajo que puede ser modificada en función de las necesidades de cada proyecto y que espero mejorar con el tiempo. Aun así, en esta primera versión, ya aporta algunas ventajas respecto a no usar ninguna estrategia.</p>

				<h2>Ventajas del contexto extendido</h2>

				<ol>
					<li>Evitamos la pérdida de contexto: el agente puede consultar los archivos cuando necesite recordar de dónde viene y a dónde va.</li>
					<li>Continuidad: podemos cerrar el ordenador y retomar el trabajo días después sin perder el hilo.</li>
					<li>Colaboración: otros miembros del equipo pueden entender fácilmente el estado del proyecto y continuarlo (con sus agentes).</li>
					<li>Documentación automática: al finalizar, tenemos ya una documentación estructurada.</li>
					<li>Facilita la división de tareas: orientando el trabajo hacia metodologías ágiles y sprints.</li>
				</ol>

				<h2>Terminando</h2>

				<p>Resulta irónico que en esta imitación del pensamiento humano que representan los modelos de lenguaje, no sólo hayamos copiado sus capacidades, sino también sus limitaciones. Y entre ellas está una muy humana: el olvidar. Así que al igual que los imperfectos humanos, los imperfectos LLMs también necesitan tomar notas. Eso sí, si son en markdown mejor, ¡aman el markdown!</p>

				<p>Por cierto, ¿tú haces tomar notas a tus agentes o tienes alguna otra estrategia a la hora de desarrollar proyectos complejos? Si trabajas de otra forma, me encantaría conocer tu experiencia 😊</p>
]]>
      </content:encoded>
      <pubDate>Tue, 22 Apr 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Claude Talk to Figma, mi primer servidor MCP</title>
      <link>https://xulioze.com/blog/claude-talk-to-figma-mcp.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/claude-talk-to-figma-mcp.html</guid>
      <description>
        Mi experiencia creando un servidor MCP que conecta Claude con Figma, permitiendo que la IA interactúe directamente con diseños UX/UI.
      </description>
      <content:encoded>
        <![CDATA[				<img class="c-post__body-img" src="https://xulioze.com/img/claude-talk-to-figma-metas.jpg" alt="Theodore pensando" width="768" loading="lazy">

				<p>La semana pasada <a href="https://www.linkedin.com/in/marc-wabnitz-0135ba24/" target="_blank" rel="noopener" title="perfil de LinkedIn">Marc</a>, compañero del increíble equipo UX/UI de <a href="https://www.makingscience.es/" target="_blank" rel="noopener" title="AI Powered Digital Acceleration">Making Science</a>, nos pasó un servidor MCP para conectar Cursor a Figma y proporcionarle a sus agentes la capacidad no sólo de ver diseños en Figma, sino también de manipularlos 😳</p>

				<p>El MCP era <a href="https://xulioze.com/blog/ht""tps://github.com/sonnylazuardi/cursor-talk-to-figma-mcp"  target="_blank" rel="noopener" title="repositorio del proyecto">Cursor Talk to Figma</a>, de <a href="https://sonnylab.framer.website/" target="_blank" rel="noopener" title="página personal">Sunny Lazuardi</a>. Si estás buscando la forma de conectar Cursor con Figma no sigas, este es tu MCP 👌🏻</p>
    
				<p>Como tengo una licencia de Cursor, le dije que podía instalarlo y hacer con ellos una prueba. La prueba salió bien, la verdad que fue bastante sorprendente ver al agente de Cursor tomar el control de Figma y modificar un diseño, pero poco después me entró la duda de si era la forma correcta de que el equipo de UX/UI introdujese en su flujo de trabajo la IA, fundamentalmente porque Cursor es una herramienta enfocada al desarrollo de código.</p>
				
				<p>Revisando el código del MCP vi que quizás se podría adaptar para usarlo en Claude Desktop, ya que mis compañeros de UX/UI tienen licencias de esta herramienta. Lo cierto es que el original se podía conectar ya a Claude, pero la forma de hacerlo no era evidente y no estaba descrita en la documentación, así que con ánimo de trastear un poco y aprender cómo funciona un MCP server por dentro, me puse manos a la obra:</p>
				
				<ol>
					<li>Escribí <a href="https://github.com/arinspunk/claude-talk-to-figma-mcp/blob/main/scripts/configure-claude.js" target="_blank" rel="noopener" title="código en GitHub">un script para configurar Claude de forma automática</a> lanzando un comando vía terminal: <code>bun run configure-claude</code>.</li>
					<li><a href="https://github.com/arinspunk/claude-talk-to-figma-mcp/commit/9de571d6bff9ea552b2a22cb2ca0b89f0108853c#diff-8d97fde957b1b60105e210d02f027f6a1babb3f5521e88d87d888171763bf08e" target="_blank" rel="noopener" title="commit de los cambios">Amplié las características del socket</a>:
						<ol>
							<li>Logging mejorado</li>
							<li>Creación de endpoint de estado <code>/status</code></li>
							<li>Sistema de canales para permitir que diferentes clientes se unan a canales específicos</li>
							<li>Inclusión de estadísticas de cada canal</li>
						</ol>
					</li>
					<li><a href="https://github.com/arinspunk/claude-talk-to-figma-mcp/blob/main/TESTING.md" target="_blank" rel="noopener" title="documentación de los test en GitHub">Añadí tests</a> para comprobar la correcta integración del proyecto.</li>
					<li>Redacté un <a href="https://github.com/arinspunk/claude-talk-to-figma-mcp/blob/main/readme.md" target="_blank" rel="noopener" title="documentación del proyecto">README.md</a> con la documentación ya orientada a su uso en Claude.</li>
					<li>Publiqué el MCP server como <a href="https://www.npmjs.com/package/claude-talk-to-figma-mcp" target="_blank" rel="noopener" title="página del paquete en NPM">paquete de npm</a>.</li>
					<li>Publiqué el proyecto en GitHub...</li>
				</ol>
				
				<p>Y voilá, mi primer MCP server: <a href="https://github.com/arinspunk/claude-talk-to-figma-mcp" target="_blank" rel="noopener" title="repositorio del proyecto">Claude Talk To Figma MCP</a> 🥳</p>

				<h2>Actualización, 11 de abril</h2>
				
				<p>Después de unos días de pruebas, el equipo de UX/UI detectó que en la colección inicial de herramientas para modificar diseños faltaban algunas importantes como auto layout (layoutMode, paddingTop, paddingBottom, etc.), control tipográfico (fontName, fontSize, fontWeight, etc.) o creación de formas (createEllipse, createPolygon, createStar, etc.), por lo que actualmente estamos añadiéndolas poco a poco. Puedes seguir el progreso en <a href="https://github.com/arinspunk/claude-talk-to-figma-mcp/blob/main/CHANGELOG.md" target="_blank" rel="noopener" title="visita el changelog en GitHub">el changelog del proyecto</a>.</p>
]]>
      </content:encoded>
      <pubDate>Tue, 08 Apr 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>IA para developers. ¿Nos enamoramos?</title>
      <link>https://xulioze.com/blog/desarrollo-con-ia.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/desarrollo-con-ia.html</guid>
      <description>
        Las cinco vías que existen a día de hoy para escribir código asistido por Inteligencia Artificial y para desarrollar herramientas con IA integrada.
      </description>
      <content:encoded>
        <![CDATA[				<img class="c-post__body-img" src="https://xulioze.com/img/ia-developing-status-her.jpg" alt="Theodore pensando" width="768" loading="lazy">

				<p>Si has comenzado a leer este post atraído por su título, quizás te lleves un chasco. No encontrarás aquí una historia de amor entre humanos e IAs, ni siquiera una narración al uso. Son simplemente unas notas, con cierta estructuración, sobre mi visión del estado actual del desarrollo de software con y para inteligencia artificial.</p>

				<p>Con "con" me refiero a escribir código con la ayuda de la IA. Y con "para", a desarrollar software específico con IA integrada.</p>

				<h2>Vías para desarrollar con/para IA</h2>

				<p>A día de hoy existen 5:</p>

				<ol>
					<li>No usar IA</li>
					<li>Chats</li>
					<li>Asistentes de código</li>
					<li>Asistentes de código con agentes IA</li>
					<li>Desarrollo de agentes propios</li>
				</ol>

				<h3>No usar IA</h3>

				<p>Entiendo esta postura, sobre todo si eres Senior y además estás un poco harto/a de toda la matraca que se está dando con el tema. Reconozco que <a href="https://www.wheresyoured.at/longcon/" title="Artículo sobre el hype de la IA" target="_blank" rel="noopener">en la IA hay mucho de hype</a> (dale una oportunidad al artículo, siempre viene bien algo de viento entre tanto humo 😉), pero merece la pena usarla, aunque sólo sea para ahorrarte dar doscientas vueltas por <a href="https://stackoverflow.com/" title="Comunidad de preguntas y respuestas para programadores" target="_blank" rel="noopener">Stack Overflow</a> para solucionar un error que se te atasca o evitar tener que leerte toda la doc de una nueva API para desarrollar algo sencillo.</p>

				<h3>Chats</h3>

				<p><a href="https://chat.openai.com/" title="ChatGPT de OpenAI" target="_blank" rel="noopener">ChatGPT</a>, <a href="https://www.deepseek.com/" title="Plataforma de IA DeepSeek" target="_blank" rel="noopener">DeepSeek</a>, <a href="https://gemini.google.com/" title="Modelo de IA de Google Gemini" target="_blank" rel="noopener">Gemini</a>, <a href="https://claude.ai/" title="Asistente de IA de Anthropic" target="_blank" rel="noopener">Claude</a>, etc.</p>

				<p>Son el tipo de herramienta más usadas. Tanto por antigüedad como por accesibilidad, ya que todos los modelos tienen versiones gratuitas a través del navegador o App.</p>

				<p>El tipo de interacción con la IA es conversacional: hacemos preguntas y obtenemos respuestas. Pero la desconexión del chat con nuestros archivos locales nos obliga a andar moviendo el código de un lado a otro.</p>

				<p>En los chats, proporcionar el contexto adecuado es fundamental. Dado que su conocimiento es vastísimo, para obtener respuestas precisas sobre un lenguaje de programación específico, es necesario acotar y delimitar claramente el ámbito de la consulta. Para esto usamos prompts con:</p>

				<ul>
					<li>Rol</li>
					<li>Experiencia</li>
					<li>Staff técnico</li>
					<li>Técnicas de prompting como:
						<ul>
							<li>Chain-of-Thought</li>
							<li>Knowledge Generation</li>
						</ul>
					</li>
				</ul>

				<p>Además los chats han evolucionado, incorporando la posibilidad de añadir contexto extra mediante la carga de archivos desde tu local o incluso directamente desde repositorios de GitHub, como en el caso de Claude.</p>

				<h3>Asistentes de código</h3>

				<p><a href="https://github.com/features/copilot" title="GitHub Copilot" target="_blank" rel="noopener">GitHub Copilot</a>, <a href="https://developers.google.com/gemini-code-assist" title="Asistente de código de Google Gemini" target="_blank" rel="noopener">Gemini Code Assist</a>, <a href="https://v0.dev/" title="Plataforma de generación de código V0" target="_blank" rel="noopener">V0</a>, etc.</p>

				<p>Su uso no está tan extendido. Por ser más recientes que los chats y porque sus versiones gratuitas sólo duran unos días de prueba. Aunque esta situación parece que está cambiando, por ejemplo, Google ofrece de forma gratuita su <a href="https://developers.google.com/gemini-code-assist/docs/overview#supported-features-gca" title="Características de Gemini Code Assist" target="_blank" rel="noopener">Gemini Code Assist</a> para uso individual.</p>

				<p>Además de poder conversar con la IA, los asistentes ofrecen sugerencias de código sobre el archivo que estamos editando. Al contrario que los Chats, aquí no tenemos que andar copiando y pegando código.</p>

				<p>Darle contexto no es tan importante. Su conocimiento está limitado al desarrollo de código y lee el archivo que tenemos abierto, lo que le permite conocer el lenguaje que estamos usando.</p>

				<p>A la hora de realizar consultas se pueden añadir archivos o líneas específicas dentro de un archivo, pero los asistentes no tienen el contexto de todos los archivos de un proyecto.</p>

				<h3>Asistentes de código con agentes IA</h3>

				<p><a href="https://www.cursor.com/" title="Cursor: Asistente de código con IA" target="_blank" rel="noopener">Cursor</a>, <a href="https://pythagora.ai/" title="Pythagora.ai: Plataforma de desarrollo con IA" target="_blank" rel="noopener">Pythagora.ai</a>, <a href="https://codegpt.com/" title="CodeGPT: Asistente de código con inteligencia artificial" target="_blank" rel="noopener">CodeGPT</a>, y próximamente <a href="https://github.blog/news-insights/product-news/github-copilot-the-agent-awakens/" title="Próximo modo agente de GitHub Copilot" target="_blank" rel="noopener">GitHub Copilot Agent Mode</a> (si tienes una licencia de GitHub Copilot y quieres probarlo, apúntate a <a href="https://github.com/github-copilot/workspace_waitlist_signup/" title="Lista de espera para GitHub Copilot" target="_blank" rel="noopener">la lista de espera</a>, quizás fue suerte pero a mí me dieron acceso en menos de 24h).</p>

				<p>Además de la conversación y las sugerencias de código, este tipo de asistentes incluyen Agentes IA.</p>

				<p>Mientras que para los asistentes de código tradicionales el contexto no era tan importante, con el uso de agentes vuelve a ser imprescindible, sobre todo si vamos a construir software desde cero. Así que nada de dejar de lado la <a href="https://www.promptingguide.ai/es" title="Guía de ingeniería de prompt" target="_blank" rel="noopener">ingeniería de prompt</a>, ¡y menos mal porque considero que es una de las partes más divertidas del trabajo con IAs!</p>

				<p>Al contrario que en los asistentes "tradicionales", los agentes sí tienen el contexto de todos los archivos de un proyecto, incluidas sus relaciones (como imports de funciones). Además, son capaces de:</p>

				<ul>
					<li>Crear y modificar archivos. Siempre pendiente de tu aprobación final</li>
					<li>Hacer uso de la terminal. Verlo las primeras veces da un poco de impresión 😅</li>
					<li>Crear ramas y hacer commits. Los mergeos quedan a cargo de un mamífero bípedo.</li>
					<li>Trabajar en paralelo contigo. Sí, puedes revisar el código de la conexión a una API mientras él desarrolla los 5 nuevos componentes que le has pedido 😳</li>
				</ul>

				<h3>Desarrollo de agentes propios</h3>

				<p>Esta vía es la más diferente, ya que su verdadera función no es ayudarnos a desarrollar código, sino crear software con IA integrada.</p>

				<p>Existen varios frameworks (principalmente de Python) que facilitan el desarrollo del código, la creación de agentes y la integración de LLMs. Entre los más usados están <a href="https://docs.llamaindex.ai/en/stable/" title="Documentación de LlamaIndex" target="_blank" rel="noopener">LlamaIndex</a> y <a href="https://docs.crewai.com/introduction" title="Documentación de Crew AI" target="_blank" rel="noopener">Crew AI</a>.</p>

				<p>En teoría, podríamos desarrollar herramientas propias para la creación de código. Sin embargo, mi opinión es que, a menos que busques una solución muy específica, construir un agente de asistencia no compensa el esfuerzo. La razón es simple: requiere desarrollar múltiples componentes desde cero que en el caso de los Asistentes como Cursor o Pythagora ya vienen incluidos:</p>

				<ul>
					<li>Herramientas para leer el código de un repositorio</li>
					<li>RAG (Retrieval-Augmented Generation) para dar contexto al LLM:
						<ul>
							<li>Base de datos vectorial con el código del repositorio</li>
							<li>Retrievers para hacer consultas a la base de datos y devolver resultados al LLM</li>
						</ul>
					</li>
					<li>Agentes y tareas</li>
					<li>Herramientas para escribir código</li>
					<li>Otros componentes técnicos</li>
				</ul>

				<p>Sin embargo, creo que la potencia de esta vía está en que podemos incorporar IA de forma relativamente sencilla en nuestro software y desarrollar herramientas IA propias sin depender de las ofrecidas (y cobradas) por terceros. Aunque por ahora no podemos librarnos completamente de pagar por las consultas a las APIs de los modelos que usemos en nuestros desarrollos. Una alternativa a las APIs, sobre todo si no necesitas gran profundidad de razonamiento, es usar <a href="https://ollama.com/search" title="Modelos de IA locales con Ollama" target="_blank" rel="noopener">modelos en local</a>, pero esa es una historia para abordar en otro post 😊</p>

				<h2>Algunas reflexiones finales</h2>

				<p>Creo que el uso de los chats no va a desaparecer. Quedarse insatisfecho con la propuesta del asistente, preferir contrastar la respuesta con otros modelos, o aprender sobre un nuevo lenguaje mientras vas en el tren, son situaciones en las que recurrir a estas herramientas seguirá siendo una buena opción. Así que si ves a una persona haciendo preguntas a su móvil sobre Redux mientras coge un cartón de leche en el súper, dale una oportunidad, quizás no esté del todo loca y simplemente pretenda arrancar esa duda que se trajo clavada del trabajo usando la interfaz de voz de ChatGPT.</p>

				<p>Creo que todos los asistentes de código van a acabar por incluir agentes y que se convertirán en el estándar de trabajo para desarrolladores en un futuro próximo. También creo que la forma de trabajar va a cambiar radicalmente con ellos, aunque no tengo ni idea de cómo será nuestra profesión después de la transformación.</p>

				<p>Creo que merece la pena adentrarse en la creación de software con IA integrada. Comenzar es asequible, con una curva de aprendizaje suave. Una parte importante de nuestra profesión se va orientar hacia ahí. Y fundamentalmente porque está todo por hacer, lo que supone ¡mucha diversión!</p>

				<p>Entonces, ¿nos dejamos arrastrar por la locura generalizada y nos enamoramos? Bueno, si algo aprendimos de Theodore es que prendarse de una IA no es un buen negocio, así que mejor exploremos estas nuevas herramientas con calma, aprendamos a usarlas (y a disfrutarlas) y veamos qué queda cuando se disipe toda esta aparente pasión. Porque lo que es seguro es que durante mucho tiempo, detrás de cada línea de código segirá estando el criterio humano.</p>
]]>
      </content:encoded>
      <pubDate>Wed, 26 Mar 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Introducción a las bases de datos vectoriales: ¡datos, más datos!</title>
      <link>https://xulioze.com/blog/bases-datos-vectoriales-introduccion.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/bases-datos-vectoriales-introduccion.html</guid>
      <description>
        Descubre qué son las bases de datos vectoriales, cómo almacenan embeddings y por qué son clave en el desarrollo de software con IA.
      </description>
      <content:encoded>
        <![CDATA[				<img class="c-post__body-img" src="https://xulioze.com/img/vectorstores-johnny-5-input.webp" alt="Johnny nº5 leyendo un libro" width="768" loading="lazy">

				<p>Llevo ya unos días desarrollando con mi colega Olivier un proyecto de IA. Nuestra idea es crear una herramienta que permita automatizar tareas de documentación, refactorización y escritura de tests para el código de un repositorio. A día de hoy, no tenemos claro si desde el punto de vista operativo merece la pena el esfuerzo, principalmente porque estamos viendo que existen servicios desarrollados específicamente para esto, como <a href="https://www.cursor.com/" target="_blank" rel="noopener" title="Web oficial">Cursor</a> o <a href="https://www.pythagora.ai/" target="_blank" rel="noopener" title="Web oficial">Pythagora</a>. Sin embargo, lo que sí es seguro es que estamos aprendiendo mucho, además de perder algunas horas de sueño… 😴</p>

				<p>Cuando nos acercamos por primera vez a una tecnología, lo habitual es sentirnos arrastrados por un torrente de nuevos conceptos y herramientas. En el caso del desarrollo de software con IA, la inundación inicial nos trae términos como LLMs, bases de datos vectoriales, retrievers, RAGs, agentes de IA, sentence transformers, etc.</p>

				<p>En este post voy a centrarme en las bases de datos vectoriales (el título no engaña). Por ser una de las piezas fundamentales en en este ámbito y también por eso de que la mejor manera de comprender un concepto es ser capaz de explicarlo de manera sencilla. Si a ti también te ayuda, significará que no las he entendido mal del todo. 😊</p>

				<h2>Vectores</h2>

				<p>Para entender qué son y cómo funcionan las bases de datos vectoriales, primero debemos saber qué es un vector.</p>

				<p>En el ámbito del aprendizaje automático, un vector es una lista ordenada de números que representa datos de cualquier tipo, incluso no estructurados, como documentos de texto, imágenes, audios o vídeos.</p>

				<p>La cantidad de números que componen un vector se conoce como dimensión, y las bases de datos vectoriales manejan vectores de varios cientos de dimensiones. Por ejemplo, el modelo <a href="https://platform.openai.com/docs/guides/embeddings#how-to-get-embeddings" target="_blank" rel="noopener" title="How to get embeddings, por Open AI"><code>text-embedding-3-small</code></a> de OpenAI genera vectores de 1536 dimensiones.</p>

				<p>1536 dimensiones conforman una lista de números muy grande. Si colocáramos uno aquí, lo más seguro es que abandonaras el post aburrido de hacer scroll. Así que, para un ejemplo más manejable, podemos mostrar la representación vectorial en 3 dimensiones de la palabra “amor”:</p>

				<pre><code>[ 0.1234, -0.2567, 0.5432 ]</code></pre>

				<h2>Embeddings</h2>

				<p>Ahora que tenemos más claro lo que son los vectores, toca conocer cómo se almacenan en una base de datos vectorial. La forma de hacerlo es incrustándolos como puntos en un espacio multidimensional.</p>

				<p>El número de dimensiones del espacio viene dado por la dimensionalidad de los vectores guardados. A mí, imaginar puntos distribuidos en 768, 1536 o 3072 dimensiones me resulta un poco complicado. Aunque quizás tú hayas visto <em>Interstellar</em> n veces y te sientas capaz de hacerlo. 😅</p>

				<p>Si no es el caso, volvamos a nuestro ejemplo anterior. Como hemos representado “amor” con un vector de solo 3 dimensiones, este se dispondrá junto al resto de embeddings como un punto en un eje de coordenadas XYZ. Así es más fácil de visualizar, ¿verdad?</p>

				<img class="c-post__body-img" src="https://xulioze.com/img/vectorstores-embeddings.png" alt="embeddings en un espacio multidimensional" width="768" loading="lazy">

				<h2>Consultas</h2>

				<p>Ahora que sabemos cómo se almacenan los datos en una base de datos vectorial, veamos cómo se realizan las consultas.</p>

				<p>En primer lugar, la consulta se convierte en un embedding que puede ser comparado con el resto de vectores de la base de datos.</p>

				<p>Dado que los embeddings son representaciones numéricas, es posible medir la distancia entre ellos utilizando distintas métricas matemáticas, entre las más comunes:</p>

				<ul>
					<li>Distancia euclidiana ( √Σ(xᵢ - yᵢ)² ): mide la distancia geométrica en un espacio multidimensional.</li>
					<li>Similitud del coseno ( cosθ ): mide el ángulo entre dos vectores, indicando cuán similares son en dirección.</li>
					<li>Distancia de Manhattan ( Σ |xᵢ - yᵢ| ): calcula la suma de las diferencias absolutas entre cada coordenada.</li>
				</ul>

				<p>Las bases de datos vectoriales emplean algoritmos como <code>k-NN</code> (k-Nearest Neighbors) y <code>ANN</code> (Approximate Nearest Neighbors) que utilizan esta métricas para devolver los vectores más cercanos al de la consulta.</p>

				<p>Esta forma de trabajar permite realizar búsquedas eficientes en grandes volúmenes de datos, ya que no es necesario analizar el contenido interno de cada vector, basta simplemente con comparar sus posiciones dentro del espacio multidimensional.</p>

				<p>Aunque la eficiencia en las consultas es muy importante, la característica fundamental de las bases de datos vectoriales es su capacidad para encontrar los vectores más cercanos a la consulta, proceso conocido como búsqueda por similitud.</p>

				<h2>Importancia de la búsqueda por similitud</h2>

				<p>Pero, ¿por qué es tan importante la búsqueda por similitud? Para entenderlo bien, tenemos que volver al punto inicial: la transformación de los datos en vectores, también conocida como embedding.</p>

				<p>Quien se encarga de generar los embeddings no es la propia base de datos, sino un modelo de lenguaje especializado, llamado modelo de embedding. Estos modelos no hacen una simple traducción numérica de los datos, sino que encapsulan su semántica y contexto.</p>

				<img class="c-post__body-img" src="https://xulioze.com/img/vectorstores-semantic-similarity.png" alt="embeddings próximos semánticamente" width="768" loading="lazy">

				<p>Y aquí es donde encontramos la clave para comprender la importancia de este tipo de búsqueda. Las búsquedas por similitud no solo identifican elementos cercanos en términos numéricos, sino que capturan similitudes semánticas, permitiendo a los LLMs reconocer relaciones profundas dentro de los datos almacenados.</p>

				<p>En definitiva, las bases de datos vectoriales no solo facilitan el acceso a la información, sino que amplían la capacidad de los LLMs para interpretar y aprovechar el conocimiento disponible. ¡<a href="https://www.youtube.com/watch?v=WnTKllDbu5o" target="_blank" rel="noopener" title="input, more input!">Lo que hubiese dado Stephanie por tener una en 1986</a>!</p>
]]>
      </content:encoded>
      <pubDate>Wed, 05 Mar 2025 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Impresoras 3D y la muerte de la simetría</title>
      <link>https://xulioze.com/blog/impresoras-3d-muerte-simetria.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/impresoras-3d-muerte-simetria.html</guid>
      <description>Producción sustractiva vs. aditiva, diseñar como lo hace la naturaleza</description>
      <content:encoded>
        <![CDATA[				<p>
					<em>Este post que hoy recupero aquí lo publiqué en febrero de 2016 en el ya extinto blog de las <a href="https://arinspunk.com/" target="_blank" rel="noopener" title="Arquivo do estúdio">Arinspunk</a>. Lo escribí después de ver una <a href="https://www.youtube.com/watch?v=kbAac9DxM1I&ab_channel=TEDxTalks" target="_blank" rel="noopener" title="3D Printing Our Future in Space - Youtube (en)">charla TEDx</a> de Tommaso Ghidini (ESA) que me dejó loco. En ella, Tommaso argumentaba que, con las impresoras 3D, deberíamos olvidarnos de la simetría y abrazar la asimetría, la forma en que la naturaleza proyecta.</em>
				<p>
				<p>
					<em>Quizás sea solo la opinión equivocada de alguien que no conoce mucho sobre la impresión 3D, pero tengo la sensación de que aún queda mucho camino por recorrer en esta aproximación. ¿Tú qué opinas?</em>
				</p>
				<span class="separator" role="separator"></span>
				<p>
					Nuestra tecnología, desde las primeras y rudimentarias herramientas, es principalmente de tipo sustractivo. Esto significa que para construir un objeto, quitamos material de una porción inicial de materia prima hasta obtener la forma deseada.
				</p>
				<figure class="figure-img">
					<img class="c-post__body-img" src="https://xulioze.com/img/bifaces-pedra.gif" alt="flechas de sílex" loading="lazy">
					<figcaption>Bifaces de piedra</figcaption>
				</figure>
				<p>
					Con la aparición de las impresoras 3D, este enfoque cambia. Pasamos de una técnica sustractiva a una aditiva, ya que las impresoras 3D no quitan, sino que añaden material.
				</p>
				<p>
					Este cambio puede pasar desapercibido inicialmente, oculto detrás de otros aspectos con los que el fabbing está revolucionando la producción industrial:
				</p>
				<ul>
					<li>
						Reducción al máximo de la <a href="https://web.archive.org/web/20160729132020/https://lasindias.com/indianopedia/crisis-de-las-escalas" target="_blank" rel="noopener" title="Crisis de las escalas - Indianopedia (es)">escala óptima de producción</a>.
					</li>
					<li>
						Extensión de la piratería al campo de las patentes.
					</li>
					<li>
						Inicio de la <a href="https://www.youtube.com/watch?v=kbAac9DxM1I&ab_channel=TEDxTalks" target="_blank" rel="noopener" title="3D Printing Our Future in Space - Youtube (en)">fabricación de objetos en el espacio</a>.
					</li>
				</ul>
				<p>
					Pero conlleva una consecuencia significativa (y muy interesante) desde el punto de vista del diseño (de producto): la muerte de la simetría (o su inutilidad).
				</p>
				<p>
					La simetría es fundamental a la hora de producir piezas de forma sustractiva, ya que un objeto es más fácil de fabricar si tiene formas simples dispuestas en ejes simétricos. Pero con la técnica aditiva, esta simetría ya no es necesaria. Para una impresora 3D, tanto da imprimir un objeto simétrico como uno asimétrico.	
				</p>
				<p>
					Entonces, ¿por qué no seguir diseñando objetos simétricos[<a id="termo-1" href="https://xulioze.com/blog/impresoras-3d-muerte-simetria.html#nota-1">1</a>] y aprovechar la reducción/simplificación en la fabricación mediante la fabricación? Porque la asimetría abre una nueva puerta: diseñar/producir como lo hace la naturaleza.
				</p>
				<figure class="figure-img">
					<img class="c-post__body-img" src="https://xulioze.com/img/raiz.jpeg" alt="células vegetais vistas com microscópio" loading="lazy">
					<figcaption>
						Raíz de una lenteja creciendo en la Estación Internacional. <a href="https://www.esa.int/ESA_Multimedia/Images/2016/01/Plant_gravity" target="_blank" rel="noopener" title="Más info en el site de la ESA (en)">ESA/Université Blaise Pascal</a>
					</figcaption>
				</figure>
				<p>
					En la naturaleza, nada es realmente simétrico[<a id="termo-2" href="https://xulioze.com/blog/impresoras-3d-muerte-simetria.html#nota-2">2</a>], pero esta ausencia de simetría no disminuye la calidad de las estructuras naturales, todo lo contrario. Millones de años de evolución han creado innumerables (y excelentes) soluciones para tantos problemas. Soluciones que están esperando por nosotros para ser aplicadas en nuestros objetos.
				</p>
				<p>
					Por eso, replicar piezas simétricas con una impresora 3D, solo porque es más fácil y barato, es un error. Para aprovechar toda la potencialidad que esta nueva tecnología nos ofrece, debemos dejar de pensar como lo hicimos hasta ahora y comenzar a diseñar como lo hace la naturaleza, de manera orgánica y asimétrica.
				</p>
				<figure class="figure-img">
					<img class="c-post__body-img" src="https://xulioze.com/img/cadeira-celular.jpeg" alt="Sofá de estructura orgánica" loading="lazy">
					<figcaption>
						3D printed soft seat by <a href="https://www.lilianvandaal.com/biomimicry-3d-printed-soft-seat" target="_blank" rel="noopener" title="la silla en la web de Lilian (en)">Lilian van Daal</a>
					</figcaption>
				</figure>
				<h2>Futuro</h2>
				<p>
					¿Permeará en algún momento este diseño orgánico, del diseño de producto al diseño gráfico?
				</p>
				<p>
					Aplicarlo en el diseño editorial y web, quizás sea un poco forzado. Pero, ¿cómo diseñaremos para una <a href="https://www.youtube.com/watch?v=KHSdObeUdxI&ab_channel=CNET" target="_blank" rel="noopener" title="LG OLED TV - Youtube (en)">pantalla flexível</a> adaptada a las formas de un objeto tridimensional? ¿Cómo será el diseño gráfico para la piel digital de un <a href="https://www.youtube.com/watch?v=uJF75t1fFRA&ab_channel=IEEESpectrum" target="_blank" rel="noopener" title="Robot Octopus Takes to the Sea - Youtube">pulpo elétrico</a>?
				</p>
				<p>
					<small id="nota-1">
						[<a href="https://xulioze.com/blog/impresoras-3d-muerte-simetria.html#termo-1">1</a>] El trabajo con formas asimétricas rara vez fue más allá del carácter ornamental, o <a title="Postmodernism - Victoria and Albert Museum (en)" href="http://www.vam.ac.uk/page/p/postmodernism/" target="_blank" rel="noopener">lúdico/provocativo</a>.
					</small><br>
					<small id="nota-2">
						[<a href="https://xulioze.com/blog/impresoras-3d-muerte-simetria.html#termo-2">2</a>] <a title="Simetría bilateral en la Wikipedia" href="https://es.wikipedia.org/wiki/Simetr%C3%ADa_bilateral" target="_blank" rel="noopener">Simetría bilateral</a> y <a title="Simetría radial en la Wikipedia" href="https://es.wikipedia.org/wiki/Simetr%C3%ADa_radial_(biolog%C3%ADa)" target="_blank" rel="noopener">radial</a> no son simetrías exactas (geométricas).
					</small>
				</p>
				<p>
					<small>
						La imagen "Bifaces de piedra" es un gif hecho a partir de <a href="https://fr.wikipedia.org/wiki/Acheul%C3%A9en#/media" title="Biface - Wikipedia (fr)" target="_blank" rel="noopener">fotos de Didier Descouens</a> – <a href="http://creativecommons.org/licenses/by-sa/4.0/" title="licença no site de Creative Commons (en)" target="_blank" rel="noopener">CC BY-SA 4.0</a>
					</small>
				</p>
]]>
      </content:encoded>
      <pubDate>Mon, 12 Feb 2024 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Resarcimiento</title>
      <link>https://xulioze.com/blog/resarcimiento.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/resarcimiento.html</guid>
      <description>Un post sobre el feísmo en Galicia escrito hace más de 10 años</description>
      <content:encoded>
        <![CDATA[				<p>
					<em>Este post mío que hoy recupero aquí, se publicó hace 10 años en el blog <a href="https://niquelarte.prazapublica.com/post/41122929792/ressarcimento" target="_blank" rel="noopener" title="post original (galego-português)">Canibalismo Patrimonial Periférico</a> del periódico gallego <a href="https://praza.gal/" target="_blank" rel="noopener" title="web del periódico">Praza.gal</a>. En ese momento, además de mi trabajo en <a href="https://arinspunk.com/" target="_blank" rel="noopener" title="Archivo del fallecido estudio">Arinspunk</a>, participaba intensamente en Niquelarte, un colectivo que trabajaba con el patrimonio material e inmaterial de una manera un tanto heterodoxa</em> 😬
				</p>
				<span class="separator" role="separator"></span>
				<img class="c-post__body-img" src="https://xulioze.com/img/cicatriz.png" alt="" width="655" loading="lazy">
				<p>
					En nuestro país, el camino desde la tradición hasta la contemporaneidad lo recorrimos de golpe, sin transición. Se mezclaron la piedra, la madera, la teja, el lino, con el cemento, el aluminio, el fibrocemento, el nailon, y lo nuevo y lo antiguo quedaron separados pero también unidos en una gran cicatriz.
				</p>
				<p>
					Algunos lo llamaron "<a href="https://es.wikipedia.org/wiki/Fe%C3%ADsmo_(arquitectura_gallega)" title="artigo na Galipedia">feísmo</a>", pero debemos hablar con claridad, eso es solo basura intelectual (una más) arrojada desde el Polígono Industrial de Sabón. ¿Por qué feo? ¿Por no ajustarse a un canon de belleza que nunca le importó a las instituciones? ¿Por qué nuestro entorno rural y nuestros pueblos difícilmente pueden convertirse en parques temáticos patrimoniales como muchas de las calles de Compostela? ¿Porque arruinamos <a href="http://www.culturagalega.org/noticia.php?id=11704" title="Un país de postal - Culturagalega">la postal</a>?
				</p>
				<p>
					Podríamos pensar que su afirmación se insertaba dentro de una estrategia mayor de asimilación y uniformización (que existe), pero sería suponerles una mayor capacidad. El proyecto capitalista que nuestras élites desarrollaron durante el siglo XX obtuvo, desde la propia óptica capitalista, un resultado mediocre, y al final del proceso, quisieron disfrazar parte de su fracaso diciendo que lo que fue una adaptación apresurada de la gente frente a su negligencia, era algo feo que debíamos borrar. Pobres...
				</p>
				<p>
					La cicatriz está ahí, es completamente evidente y no puede ser borrada. Pero no tiene sentido hablar de si es más o menos fea. Eso no es lo importante de una cicatriz. La lectura provechosa, además de recordarnos que a pesar de todo estamos vivos, es que cada cicatriz encierra una historia, una historia en este caso que es nuestra.
				</p>
				<p>
					Dejemos de mirarla como algo de lo que avergonzarnos y sumerjámonos en ella. Vamos a conocer más sobre lo que fuimos y somos, y también nos ayudará a crear nuestro propio relato. Porque aquí, en la herida curada a toda prisa con aires salados y agrios, encontraremos belleza. No la verdadera, eso no existe, pero sí la nuestra propia.
				</p>
]]>
      </content:encoded>
      <pubDate>Mon, 25 Sep 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>El arte de conversar con ChatGPT (y otros LLMs)</title>
      <link>https://xulioze.com/blog/como-hablar-con-chatgpt.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/como-hablar-con-chatgpt.html</guid>
      <description>Cómo escribir prompts adecuados a la hora de desarrollar código</description>
      <content:encoded>
        <![CDATA[				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-rachael.jpg" alt="Rachael y el Voight-Kampff test" width="655" loading="lazy">
				<p>
					En un intercambio de correos electrónicos sobre ChatGPT, un colega me preguntó cuál sería la mejor forma de escribir prompts al desarrollar código. Bueno, la respuesta no es simple, después de todo esto implica conversar con una red neuronal y muchas veces ya es difícil hacerlo con otras personas, cuanto más con una máquina. Sin embargo, como soy una persona muy educada y que siempre le gusta ayudar cuando es posible, reflexioné y respondí de la mejor manera que pude.
				</p>
				<p>
					La red está llena <a href="https://github.com/readme/guides/coding-generative-ai" title="Harness the power of generative AI for software development - ReadME Project" target="_blank" rel="noopener">consejos</a> para mejorar nuestros prompts y he incorporado muchos de ellos, pero al analizarlos individualmente, no sé qué grado de mejora han traído. Incluso hay algunos en los que no estoy seguro de si tuvieron un impacto significativo. Es normal, la experiencia que acumulo todavía no es suficiente para hacer estadística. Sin embargo, lo que puedo afirmar es que en conjunto y en comparación con mis toscas primeras pruebas, su incorporación ha resultado en una mejora innegable en los resultados obtenidos.
				</p>
				<p>
					Un caso diferente son las estrategias enfocadas en la resolución de tareas más complejas, ya que a diferencia de las simples en las que podemos obtener una respuesta válida e incluso muy similar, usando o no un determinado consejo, la adopción de estas técnicas trae una mejora inmediata y evidente. <a href="https://xulioze.com/blog/construir-pwa-con-chatgpt.html" title="Cómo construir una PWA con ChatGPT antes de que nos mande al paro" target="_blank" rel="noopener">Sin una estrategia definida</a>, el LLM tendía a dispersarse y cometer errores, obligándome a corregirlo y guarlo con nuevas preguntas o instrucciones. Sin embargo, cuando incluí en mi trabajo el <a href="https://www.promptingguide.ai/es/techniques/cot" title="descripción en la Prompt Engineering Guide" target="_blank" rel="noopener">Chain-of-Thought</a> y el <a href="https://www.promptingguide.ai/es/techniques/knowledge" title="descripción en la Prompt Engineering Guide" target="_blank" rel="noopener">Generated Knowledge</a>, estos problemas se resolvieron. (Tengo pendiente un artículo contando cómo desarrollé un blog en React con la ayuda de ChatGPT).
				</p>
				<figure>
					<blockquote cite="https://www.promptingguide.ai/models">
						<p>Understanding these capabilities are important to understand the limitations of these models and how to use them effectively.</p>
					</blockquote>
					<figcaption><cite>Prompt Engineering Guide</cite></figcaption>
				</figure>
				<p>
					Entonces, ¿cómo evaluamos los pequeños consejos que encontramos en la red? Un enfoque inicial (y obvio) es seguir las indicaciones de fuentes confiables. A mí me gusta mucho <a href="https://learnprompting.org/" title="Your Guide to Communicating with Artificial Intelligence" target="_blank" rel="noopener">learnprompting.org</a> y <a href="https://www.promptingguide.ai/es" title="Guía de Ingeniería de Prompt" target="_blank" rel="noopener">promptingguide.ai</a>, pero <a href="https://github.com/openai/openai-cookbook#prompting-guides" title="Prompting guides - OpenAI" target="_blank" rel="noopener">hay muchas más</a>. Otro, complementario, es determinar si el propósito de un consejo tiene sentido con el funcionamiento de los LLM. Es evidente que seguir este enfoque implica un gasto extra de tiempo, ya que:
				</p>
				<ol>
					<li>
						Tenemos que determinar el propósito del consejo, aunque todos tiendan a buscar:
						<ul>
							<li>
								Reducir el <a href="https://platform.openai.com/tokenizer" title="Contador de tokens - OpenAI (En)" target="_blank" rel="noopener">número de tokens</a> utilizados en las preguntas y respuestas.
							</li>
							<li>
								Optimizar el trabajo del LLM en el procesamiento de las preguntas y en la generación de las respuestas.
							</li>
							<li>
								Obtener la mejor respuesta posible para nuestra tarea.
							</li>
						</ul>
					</li>
					<li>
						Y nos obliga a profundizar en la <a href="https://www.promptingguide.ai/es/models" title="principales modelos de lenguaje" target="_blank" rel="noopener">comprensión y el conocimiento de estas herramientas</a>.
					</li>
				</ol>
				<p>
					Sin embargo, esta siempre es una buena inversión, ya que ayuda a mejorar nuestro trabajo diario y nos permite disfrutar del placer de aprender algo nuevo.
				</p>
				<p>
					Finalmente mi colega, que también es muy educado, agradeció la respuesta. Pero como igualmente es pragmático y directo, quiso después saber si yo había identificado alguna buena práctica. Resumiendo, buscaba una lista de consejos 😬
				</p>
				<h2>Mis consejos</h2>
				<p>
					Dejo aquí las prácticas que siempre incluyo en mis prompts orientados al desarrollo de tareas simples. Para aprender a escribir código complejo con ChatGPT, te recomiendo comenzar por el artículo "<a href="https://martinfowler.com/articles/2023-chatgpt-xu-hao.html" title="How Xu Hao uses chain of thought and general knowledge prompting with ChatGPT" target="_blank" rel="noopener">An example of LLM prompting for programming</a>".
				</p>
				<ul>
					<li>
						Evito la formalidad. Nada de "Buenos días", "podría usted…", "muchas gracias", etc. No te preocupes, el LLM no es un ser consciente y siempre es bueno ahorrar algunos tokens.
					</li>
					<li>
						Siempre empiezo con un "As a [rol name]". Con esto busco formatear la respuesta del modelo de una manera más específica.
					</li>
					<li>
						Incluyo detalles con terminología especializada. La idea es proporcionar suficiente contexto para evitar que el modelo tenga que adivinar lo que quiero decir.
					</li>
					<li>
						Procuro ser lo más sintético posible, en equilibrio con el punto anterior. Cuanto más breve y directo sea nuestro prompt, más concisa será la respuesta, además de ahorrar algunos tokens.
					</li>
					<li>
						Limpio mis códigos de ejemplo. Todo lo que no es necesario para desarrollar la tarea solo agrega ruido y desperdicia tokens.
					</li>
				</ul>
				<p>
					Lo que pretendía ser un borrador de un método para aprender a conversar con las máquinas se ha convertido en otro artículo con consejos para usar ChatGPT. ¿Crees que el propósito de cada uno tiene sentido con el funcionamiento de los LLMs?
				</p>
]]>
      </content:encoded>
      <pubDate>Fri, 30 Jun 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Cómo construir una PWA con ChatGPT antes de que nos mande al paro</title>
      <link>https://xulioze.com/blog/construir-pwa-con-chatgpt.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/construir-pwa-con-chatgpt.html</guid>
      <description>Experimentando ChatGPT antes de que nos mande al paro</description>
      <content:encoded>
        <![CDATA[				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-hal-9000.jpg" alt="David Bowman delante de HAL 9000" width="655" loading="lazy">
				<figure>
					<blockquote>
						<p>Cualquier tecnología lo suficientemente avanzada es indistinguible de la magia.</p>
					</blockquote>
					<figcaption><cite>Arthur C. Clarke</cite></figcaption>
				</figure>
				<p>
					La primera IA que utilicé (conscientemente) fue <a href="https://www.midjourney.com/" title="site de la IA" target="_blank" rel="noopener">Midjourney</a>: escribir un prompt, presionar enter, esperar un instante y la imagen aparecía de la nada. Bonita, sofisticada y extraña. Fue como presenciar un acto mágico.
				</p>
				<p>
					Luego probé <a href="https://openai.com/research/dall-e" title="site de la IA" target="_blank" rel="noopener">Dall·E</a> y <a href="https://stablediffusionweb.com/" title="site de la IA" target="_blank" rel="noopener">Stable Diffusion</a>, igualmente espectaculares, pero al final el aburrimiento venció a la magia. No encontré utilidad para mí, prefiero <a href="https://twitter.com/naia_ze/status/1621621795907420162" title="fio em Twitter" target="_blank" rel="noopener">generar imágenes a mi manera</a>.
				</p>
				<p>
					Los meses pasaron y se dejó de hablar tanto sobre ellas, había un nuevo juguete, <a href="https://stablediffusionweb.com/" title="site de la IA" target="_blank" rel="noopener">ChatGPT</a>.
				</p>
				<p>
					Tardé en usarlo, pero la semana pasada copié un snippet de JavaScript de un sitio antiguo, lo pegué en el cuadro de chat y pregunté: "¿Podrías optimizar este fragmento de código?" Y el texto fue creciendo mientras decía, claro, puedes mejorar esto con aquello, y aquello con esto, etc. Te dejo un ejemplo. El ejemplo tenía sentido y funcionaba. De nuevo un acto aparentemente mágico. De nuevo la emoción. Pero ahora también una sensación diferente, un poco de miedo.
				</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/fired.gif" alt="está despedido" width="655" loading="lazy">
				<p>
					Solo un poquito. La verdad es que no creo en la magia (excepto en la de <a href="https://www.nytimes.com/2023/01/02/magazine/juan-tamariz-magic.html" title="The Man Who Made Spain the Magic Capital of the World - NYT" target="_blank" rel="noopener">Tamariz</a>), ya vi gastar el adjetivo disruptivo en la primera década del siglo y como la mejor manera de perder el miedo a algo es conocerlo, me puse manos a la obra, antes de que nos enviara derechas al paro.
				</p>
				<h2>
					Experimento
				</h2>
				<p>
					Hmm… ¿Por dónde empezar? Bueno, <a href="https://twitter.com/naia_ze" title="NZ&A en Twitter" target="_blank" rel="noopener">Naia y yo</a> tenemos la idea de crear una aplicación meteorológica en la que, en lugar de los clásicos iconos, se muestren unos dibujos un poco más divertidos. Así que aprovechando la excusa, escribí la siguiente pregunta:
				</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-01.jpg" alt="primera pregunta a ChatGPT y su respuesta" width="655" loading="lazy">
				<p>
					Perfecto. En su primera respuesta, ChatGPT proporcionó un HTML, un fragmento de JS y una explicación detallada de todo el código.
				</p>
				<p>
					Reemplacé <code>your_openweathermap_api_key_here</code> por una clave válida de la API OpenWeatherMap y funcionó. El único error reseñable fue la temperatura de la ciudad, ya que indicaba que estaba en grados Celsius, pero en realidad el valor estaba en Kelvin.
				</p>
				<iframe class="c-post__body-iframe" height="300" style="width: 100%;" scrolling="no" title="chatGPT 01" src="https://codepen.io/arinspunk/embed/GRYpLrL?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
					See the Pen <a href="https://codepen.io/arinspunk/pen/GRYpLrL">
					chatGPT 01</a> by Arinspunk (<a href="https://codepen.io/arinspunk">@arinspunk</a>)
					on <a href="https://codepen.io/">CodePen</a>.
				</iframe>
				<p>Después de algunas pruebas más, noté que si el nombre de la ciudad no existía en la base de datos de la API, por ejemplo Portox, obtenía un error en el fetch (con el mensaje que pasábamos en el código, "Failed to fetch weather data for Portox"). También ocurría que si varias ciudades compartían el mismo nombre, como Porto, que hay en Portugal, Brasil y España, los datos que veíamos pertenecían solo a una de ellas. Por lo que escribí una segunda pregunta:</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-02.jpg" alt="segunda pregunta a ChatGPT y su respuesta" width="655" loading="lazy">
				<p>Esta vez ChatGPT no acertó. O mejor dicho, acertó pero yo no le proporcioné la pregunta correcta. Simplemente verificaba si la ciudad existía en la base de datos antes de buscar la información meteorológica. Sin embargo, para el usuario no había diferencia en comparación con la versión anterior, excepto por el intercambio de mensajes. Además, el problema de las ciudades con el mismo nombre no se resolvía.</p>
				<iframe class="c-post__body-iframe" height="300" style="width: 100%;" scrolling="no" title="PWA com ChatGPT 02" src="https://codepen.io/arinspunk/embed/qBJOzJX?default-tab=js%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
					See the Pen <a href="https://codepen.io/arinspunk/pen/qBJOzJX">
					PWA com ChatGPT 02</a> by Arinspunk (<a href="https://codepen.io/arinspunk">@arinspunk</a>)
					on <a href="https://codepen.io/">CodePen</a>.
				</iframe>
				<p>Mea culpa y nueva pregunta. Ahora enfocada en las ciudades con el mismo nombre:</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-03.jpg" alt="tercera pregunta a ChatGPT y su respuesta" width="655" loading="lazy">
				<p>Con el nuevo código se mostraba la lista de ciudades, pero no era posible hacer clic en ellas para obtener los datos de solo una al presionar el botón "Buscar".</p>
				<iframe class="c-post__body-iframe" height="300" style="width: 100%;" scrolling="no" title="PWA com ChatGPT 02" src="https://codepen.io/arinspunk/embed/oNajrao?default-tab=js%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
					See the Pen <a href="https://codepen.io/arinspunk/pen/oNajrao">
					PWA com ChatGPT 02</a> by Arinspunk (<a href="https://codepen.io/arinspunk">@arinspunk</a>)
					on <a href="https://codepen.io/">CodePen</a>.
				</iframe>
				<p>Otra pregunta más:</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-04.jpg" alt="cuarta pregunta a ChatGPT y su respuesta" width="655" loading="lazy">
				<p>Con el cambio, sí era posible hacer clic en una de las ciudades de la lista y, al hacerlo, se obtenían los datos meteorológicos de esa ciudad.</p>
				<iframe  class="c-post__body-iframe" height="300" style="width: 100%;" scrolling="no" title="PWA com ChatGPT 04" src="https://codepen.io/arinspunk/embed/abRpbjQ?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
					See the Pen <a href="https://codepen.io/arinspunk/pen/abRpbjQ">
					PWA com ChatGPT 04</a> by Arinspunk (<a href="https://codepen.io/arinspunk">@arinspunk</a>)
					on <a href="https://codepen.io/">CodePen</a>.
				</iframe>
				<p>Pero aún quedaban algunos puntos por pulir:</p>
				<ul>
					<li>El botón "Buscar" realmente no servía para nada.</li>
					<li>La lista debería desaparecer al hacer clic en una de las opciones.</li>
					<li>Había que cambiar la temperatura a Celsius.</li>
					<li>Sería bueno indicar el nombre del país a la derecha de cada ciudad.</li>
				</ul>
				<p>Fue en este punto donde decidí dejar el piloto automático y pasar al "modo manual", ya que creí que sería más rápido modificar el código yo mismo que seguir preguntando.</p>
				<p>Aquí está el resultado con las "modificaciones humanas":</p>
				<iframe class="c-post__body-iframe" height="300" style="width: 100%;" scrolling="no" title="PWA com ChatGPT 05" src="https://codepen.io/arinspunk/embed/wvYgBdP?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
					See the Pen <a href="https://codepen.io/arinspunk/pen/wvYgBdP">
					PWA com ChatGPT 05</a> by Arinspunk (<a href="https://codepen.io/arinspunk">@arinspunk</a>)
					on <a href="https://codepen.io/">CodePen</a>.
				</iframe>
				<p>Ahora que el código estaba listo, era hora de convertir nuestro sitio en una PWA (aplicación web progresiva):</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-05.jpg" alt="quinta pregunta a ChatGPT y su respuesta" width="655" loading="lazy">
				<p>En el primer intento funcionó 🥳</p>
				<p>Este es el resultado: <a href="https://xulioze.com/test/pwa/" target="_blank" rel="noopener" title="Visita y descarga la PWA">Pe Man</a></p>
				<p>¡Muchas gracias ChatGPT!</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/chatgpt-06.jpg" alt="última pergunta a ChatGPT e a sua resposta" width="655" loading="lazy">
				<h2>
					Conclusiones
				</h2>
				<p>
					La primera conclusión es que ChatGPT es capaz de comprender muy bien incluso un inglés malo como el mío 😬
				</p>
				<p>
					La segunda es que puede ser útil para:
				</p>
				<ul>
					<li>
						Escribir un código base, ayudándonos a ahorrar tiempo. Después de analizar mi experimento, debo constatar que la mejor estrategia es escribir un prompt lo más amplio y contextualizado posible, en lugar de formular muchas preguntas cortas.
					</li>
					<li>
						Hacer mejoras/cambios en el código. Hasta cierto punto, luego es mejor pasar al modo manual/humano.
					</li>
					<li>
						Realizar consultas a una API que no conocemos sin necesidad de visitar su documentación.
					</li>
					<li>
						Optimizar el código.
					</li>
					<li>
						Ampliar el conocimiento sobre un lenguaje, conociendo otros enfoques.
					</li>
					<li>
						Iniciarse en nuevos lenguajes/tecnologías.
					</li>
				</ul>
				<p>
					Y la última y más importante, es que no nos va a enviar a las programadoras directamenteal paro. Al menos en los próximos meses…
				</p>
				<p>
					🥹
				</p>
				<img class="c-post__body-img" src="https://xulioze.com/img/fired.gif" alt="Estás despedido" width="655" loading="lazy">
]]>
      </content:encoded>
      <pubDate>Fri, 14 Apr 2023 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>¿Custom Page Templates en Frontity? Vigentes y muy sencillas</title>
      <link>https://xulioze.com/blog/frontity-custom-page-templates.html</link>
      <guid isPermaLink="false">https://xulioze.com/blog/frontity-custom-page-templates.html</guid>
      <description>Cómo crear Custom Page Templates en Wordpress y desarrollar sus layouts en Frontity</description>
      <content:encoded>
        <![CDATA[				<p>
					Las <a href="https://developer.wordpress.org/themes/template-files-section/page-template-files/#creating-custom-page-templates-for-global-use" title="documentación oficial de Wordpress" target="_blank" rel="noopener">Custom Page Templates</a> son el mecanismo del que disponemos en Wordpress para crear plantillas globales con diseños específicos que se pueden aplicar a una o varias páginas.
				</p>
				<p>
					Por ejemplo, si en un site necesitamos dos tipos de página: una a una columna y otra con dos (contenido principal y barra lateral), una buena opción es usar la página por defecto, <code>page.php</code>, para la primera y crear un template, <code>sidebar-page.php</code>, para la segunda. De esta forma, para cada nueva página, podemos elegir uno u otro diseño desde el editor.
				</p>
				<p>
					¿Y en <a href="https://frontity.org/" title="Site del framework" target="_blank" rel="noopener">Frontity</a>, donde el front no se genera a partir de los templates en php del theme de Wordpress si no desde una app en React? Pues las Custom Page Templates continuan siendo la mejor opción para trabajar con múltiples diseños de página porque permiten:
				</p>
				<ul>
					<li>
						seleccionar el diseño deseado desde el editor de una página,
					</li>
					<li>
						asignarles grupos de campos <a href="https://www.advancedcustomfields.com/" title="página oficial del plugin" target="_blank" rel="noopener">ACF</a>, extendiendo las posibilidades de edición,
					</li>
					<li>
						que en la REST API (y en el <a href="https://gitbook-docs.frontity.org/learning-frontity/state" title="Descripción en la documentación de Frontity" target="_blank" rel="noopener">state</a> de Frontity) se muestre el nombre del archivo del template asignado a una página, lo que facilita a Frontity servir el layout correcto en cada caso.
					</li>
				</ul>
				<p>
					Veamos a hora el proceso completo con un ejemplo sencillo.
				</p>
				<h2>
					Wordpress
				</h2>
				<p>
					Creamos un archivo php, <code>custom-page-template.php</code> por ejemplo, con un comentario al inicio como el siguiente:
				</p>
				<script src="https://gist.github.com/arinspunk/c1c7b8d374b0608a64a4f4e63cbb4448.js"></script>
				<p>
					Donde “Template name:” es la marca que indica a Wordpress que ese archivo es un page template y “My Custom Page Template Name” el nombre de nuestro nuevo template, que aparecerá en selector de templates del editor de cada página.
				</p>
				<p>
					¿Algo más por hacer? no, eso es todo en la parte del Wordpress 😎
				</p>
				<p>
					Eso sí, para evitar errores (y algún dolor de cabeza) debemos tener en cuenta que:
				</p>
				<ul>
					<li>
						las plantillas personalizadas solo funcionan si tenemos un <code>index.php</code> (puede estar vacío) en la raíz de nuestro theme de Wordpress,
					</li>
					<li>
						no debemos usar nunca <code>page-</code> como prefijo en el nombre del archivo, ya que WordPress lo interpretará como una plantilla especializada destinada a aplicarse solo a una página del sitio.
					</li>
				</ul>
				<h2>
					Frontity
				</h2>
				<p>
					Creamos tres componentes:
				</p>
				<ol>
					<li>
						<code>
							Page
						</code>
					</li>
					<li>
						<code>
							PageDefault
						</code>
					</li>
					<li>
						<code>
							PageTemplate
						</code>
					</li>
				</ol>
				<p>
					En el primero incluimos un <code>Switch</code> que sirve el segundo, <code>PageDefault</code>, o el tercero, <code>PageTemplate</code>, en función del valor de la propiedad <code>template</code> que aparece en los datos de la página del state de Frontity. Si la página publicada en Wordpress usa la plantilla de página por defecto, este valor llegará vacío y si usa una custom, vendrá con el nombre del archivo de la plantilla, <code>custom-page-template.php</code> en nuestro caso.
				</p>
				<script src="https://gist.github.com/arinspunk/dbe49b71f4ab06ad1b872beb0b02d53d.js"></script>
				<p>
					Y ya por último, en el segundo y tercero incluimos los layouts propiamente dichos de ambos tipos de página.
				</p>
				<p>
					Sencillo, ¿no? 
				</p>
				<p>Si tenéis alguna duda, consideráis que se puede mejorar algo o simplemente queréis saludar, podéis escribirme a <a href="mailto:hola@xulioze.com" title="mi email">hola@xulioze.com</a> 😋</p>
]]>
      </content:encoded>
      <pubDate>Thu, 03 Feb 2022 00:00:00 GMT</pubDate>
    </item>
  </channel>
</rss>