<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: John Serrano (DEV)</title>
    <description>The latest articles on Forem by John Serrano (DEV) (@johnserranodev).</description>
    <link>https://forem.com/johnserranodev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1539179%2F0b0365d0-77b0-4d83-8a6e-2769a03ec7b2.png</url>
      <title>Forem: John Serrano (DEV)</title>
      <link>https://forem.com/johnserranodev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/johnserranodev"/>
    <language>en</language>
    <item>
      <title>Aprende lógica de programación: la base para convertirte en programador</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sat, 20 Sep 2025 21:06:26 +0000</pubDate>
      <link>https://forem.com/johnserranodev/aprende-logica-de-programacion-la-base-para-convertirte-en-programador-1674</link>
      <guid>https://forem.com/johnserranodev/aprende-logica-de-programacion-la-base-para-convertirte-en-programador-1674</guid>
      <description>&lt;p&gt;¿Quieres aprender a programar y no sabes por dónde empezar?&lt;br&gt;&lt;br&gt;
La respuesta es sencilla: &lt;strong&gt;lógica de programación&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Este es el punto de partida para adentrarte en el mundo de la informática y el desarrollo de software. En este artículo descubrirás qué es la lógica de programación, qué papel juegan los algoritmos, cómo aplicarlos a tu vida diaria y dónde puedes comenzar a entrenar estas habilidades.  &lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por qué la lógica de programación es tan importante?
&lt;/h2&gt;

&lt;p&gt;Antes de aprender un lenguaje como JavaScript, Python o C#, necesitas algo más fundamental: aprender a &lt;strong&gt;pensar como programador&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;La lógica de programación es la base que te permite dar instrucciones claras y ordenadas a una computadora para que pueda ejecutar una tarea. No importa con qué lenguaje comiences; todos comparten la misma lógica.  &lt;/p&gt;

&lt;p&gt;Además, hay dos aliados que te serán de gran ayuda en este camino:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Las matemáticas&lt;/strong&gt;: porque entrenan tu capacidad de razonar con reglas y estructuras.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;El inglés&lt;/strong&gt;: porque la mayoría de lenguajes de programación y documentación están escritos en este idioma.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es la lógica de programación?
&lt;/h2&gt;

&lt;p&gt;La lógica de programación es la &lt;strong&gt;técnica para organizar y planificar instrucciones en una secuencia coherente&lt;/strong&gt; con el fin de resolver un problema o alcanzar un objetivo.  &lt;/p&gt;

&lt;p&gt;En otras palabras: es aprender a traducir ideas en pasos claros que una computadora pueda entender y ejecutar.  &lt;/p&gt;

&lt;p&gt;El reto del programador es estructurar esas instrucciones de manera precisa, porque las máquinas no entienden mensajes subjetivos. Para ellas, &lt;strong&gt;cada paso debe estar escrito en el orden correcto y sin ambigüedades&lt;/strong&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es un algoritmo?
&lt;/h2&gt;

&lt;p&gt;Un algoritmo es una &lt;strong&gt;secuencia de pasos finitos y ordenados&lt;/strong&gt; que permiten resolver un problema o completar una tarea.  &lt;/p&gt;

&lt;p&gt;Piensa en un algoritmo como una receta de cocina: te dice qué hacer, en qué orden y con qué ingredientes.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Ejemplo: Algoritmo de las papas fritas
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Tomar las papas  
2. Pelar las papas  
3. Cortarlas en tiras  
4. Colocar aceite en un sartén y encender la estufa  
5. Esperar a que el aceite esté caliente  
6. Poner las papas en el aceite  
7. Aguardar 10 minutos  
8. Retirar y servir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Fácil, verdad? Ese es un algoritmo. Si cambiaras el orden por ejemplo, intentar freír las papas antes de cortarlas el resultado sería incorrecto. Lo mismo sucede en programación.&lt;/p&gt;

&lt;p&gt;Con el tiempo, los algoritmos pueden representarse de varias formas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Textuales (como el ejemplo de arriba).&lt;/li&gt;
&lt;li&gt;Gráficas, usando flujogramas.&lt;/li&gt;
&lt;li&gt;Pseudocódigo, una forma intermedia entre el lenguaje humano y el código real.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Variables y constantes
&lt;/h3&gt;

&lt;p&gt;En programación, además de los pasos lógicos, necesitas manejar datos. Para eso existen variables y constantes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Una variable es un espacio donde guardas información que puede cambiar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una constante es un valor fijo que no cambia durante la ejecución del programa.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 &lt;strong&gt;Siguiendo el ejemplo de las papas fritas&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;El aceite es una variable, porque puede estar frío o caliente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;El tiempo de cocción es una constante, ya que siempre tarda aproximadamente lo mismo.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  La lógica en tu rutina diaria
&lt;/h3&gt;

&lt;p&gt;La lógica no se limita al mundo del software. Sin darte cuenta, ya aplicas algoritmos todos los días.&lt;/p&gt;

&lt;p&gt;Por ejemplo, tu rutina al despertar puede verse como un algoritmo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Apagar la alarma&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Levantarte de la cama&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cepillarte los dientes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Preparar el desayuno&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vestirte&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Incluso aquí puedes identificar &lt;strong&gt;variables&lt;/strong&gt; y &lt;strong&gt;constantes&lt;/strong&gt;: el clima del día puede variar (variable), pero cepillarte los dientes siempre es un paso fijo (constante).&lt;/p&gt;

&lt;p&gt;Ejercicios como este son una gran forma de entrenar tu razonamiento lógico antes de dar el salto al código.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Dónde aprender lógica de programación?
&lt;/h2&gt;

&lt;p&gt;Hoy tienes a tu alcance una infinidad de recursos gratuitos y de pago para aprender lógica de programación:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code.org&lt;/strong&gt;: una plataforma educativa pensada para principiantes, con cursos estructurados que van desde lo básico hasta conceptos más avanzados. Es utilizada en miles de escuelas y ofrece un camino guiado para aprender ciencias de la computación.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Codewars&lt;/strong&gt;: ideal para quienes ya tienen una base y quieren practicar con retos de programación. Sus katas te permiten mejorar progresivamente y comparar tus soluciones con las de otros programadores. Visita mi &lt;a href="https://www.codewars.com/users/johnserranodev" rel="noopener noreferrer"&gt;perfil&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cursos online&lt;/strong&gt;: en plataformas como Coursera, Platzi, Udemy o incluso YouTube.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comunidades digitales&lt;/strong&gt;: foros, Discords y grupos en redes sociales donde puedes resolver dudas y compartir tus avances.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mi recomendación personal
&lt;/h2&gt;

&lt;p&gt;Si quieres seguir aprendiendo lógica de programación y programación en general, te invito a explorar dos recursos que preparo con mucho detalle:&lt;/p&gt;

&lt;p&gt;📖 Mi blog: &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;John Serrano&lt;/a&gt;&lt;br&gt;
 — artículos fáciles de entender, desde fundamentos hasta temas avanzados.&lt;/p&gt;

&lt;p&gt;🎥 Mi canal de YouTube: &lt;a href="https://www.youtube.com/@johnserranodev" rel="noopener noreferrer"&gt;John Serrano Dev&lt;/a&gt;&lt;br&gt;
 — videos prácticos donde explico paso a paso con ejemplos reales.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;La lógica de programación es el primer escalón en la carrera de todo desarrollador.&lt;/p&gt;

&lt;p&gt;Es la habilidad que te permitirá pensar en soluciones, diseñar algoritmos y después llevarlos a cualquier lenguaje de programación.&lt;/p&gt;

&lt;p&gt;Recuerda:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Practicar es la clave.&lt;/li&gt;
&lt;li&gt;Equivocarte es parte del proceso.&lt;/li&gt;
&lt;li&gt;Aprender lógica es aprender a pensar como programador.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora que conoces la base, el siguiente paso es poner manos a la obra y comenzar a practicar. 🚀&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi blog, donde encontrarás más contenido sobre JavaScript, React, CSS, IA, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>algorithms</category>
    </item>
    <item>
      <title>Arquitectura Hexagonal con React y TypeScript: guía paso a paso (enfoque pragmático)</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sat, 16 Aug 2025 16:20:53 +0000</pubDate>
      <link>https://forem.com/johnserranodev/arquitectura-hexagonal-con-react-y-typescript-guia-paso-a-paso-enfoque-pragmatico-500o</link>
      <guid>https://forem.com/johnserranodev/arquitectura-hexagonal-con-react-y-typescript-guia-paso-a-paso-enfoque-pragmatico-500o</guid>
      <description>&lt;p&gt;Inspirado por enfoques pragmáticos: menos capas, más claridad. Aquí no seguimos el “purismo” hexagonal; tomamos lo que aporta valor en UI y evitamos sobre-ingeniería.&lt;/p&gt;

&lt;p&gt;Objetivo: que alguien que está aprendiendo pueda aplicarlo en 1 tarde.&lt;/p&gt;

&lt;h2&gt;
  
  
  Historia de usuario
&lt;/h2&gt;

&lt;p&gt;“Como usuario quiero entrar a la Home y ver un listado de productos con:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nombre&lt;/li&gt;
&lt;li&gt;imagen&lt;/li&gt;
&lt;li&gt;precio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tenemos una API que expone /products.”&lt;/p&gt;

&lt;p&gt;Pasemos a código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capas (lo justo y necesario)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Dominio: tipos y reglas (casi siempre son simples en UI).&lt;/li&gt;
&lt;li&gt;Aplicación: casos de uso (orquestan llamadas).&lt;/li&gt;
&lt;li&gt;Infraestructura: HTTP/SDKs, errores, auth.&lt;/li&gt;
&lt;li&gt;UI: componentes React.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsd4xlyyrju5ii3l68ojq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsd4xlyyrju5ii3l68ojq.png" alt=" " width="300" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota importante&lt;/strong&gt;:&lt;br&gt;
Si el proyecto crece o necesitas intercambiar fuentes de datos, añades un repositorio como puerto. Más abajo verás un ejemplo de cómo sería el funcionamiento y por qué conviene hacerlo en ese momento &lt;strong&gt;(no antes)&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dominio: ¿tipo o clase?
&lt;/h2&gt;

&lt;p&gt;Regla práctica: empieza con tipos. Si luego necesitas comportamiento/validación compleja, refactorizas a clase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/domain/Product.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Infra: un cliente HTTP pequeño (adapter)
&lt;/h2&gt;

&lt;p&gt;Aísla fetch/axios en un único punto. Centralizas errores y auth. Si cambias fetch por axios, solo tocas aquí.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/infrastructure/APIClient.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;fetchImpl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchImpl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Manejo de errores muy simple para el ejemplo&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; al GET &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Aplicación: caso de uso mínimo
&lt;/h2&gt;

&lt;p&gt;Empieza simple: sin repositorio. Orquesta la llamada y devuelve dominio directamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProducts.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProducts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Aquí podrías mapear/filtrar/ordenar si hace falta&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Qué es un DTO y cuándo usarlo?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsdg1ufopgooom1j3a85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsdg1ufopgooom1j3a85.png" alt=" " width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DTO (Data Transfer Object) es un objeto “de transferencia de datos”. Su objetivo es:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Formatear o adaptar datos para una capa específica (p. ej., la UI).&lt;/li&gt;
&lt;li&gt;Ocultar detalles del dominio que no quieres exponer.&lt;/li&gt;
&lt;li&gt;Combinar/dividir datos que vienen de distintas fuentes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuándo NO usar DTO:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si la UI necesita exactamente los mismos campos del dominio, añadir DTO genera ruido y “capas por capas”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuándo SÍ usar DTO:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Si necesitas cambiar nombres/formatos (p. ej., price en centavos → cadena “$12.99”).&lt;/li&gt;
&lt;li&gt;Si quieres estabilizar la UI frente a cambios del dominio o de la API.&lt;/li&gt;
&lt;li&gt;Si debes ocultar campos sensibles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ejemplo con DTO y mapeo en el caso de uso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ProductDTO.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ProductDTO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// renombrado para la UI&lt;/span&gt;
  &lt;span class="nl"&gt;displayPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// precio formateado&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsWithDTO.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductDTO&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ProductDTO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsWithDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ProductDTO&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;displayPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`$&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Idea práctica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empieza sin DTO.&lt;/li&gt;
&lt;li&gt;Si la UI empieza a necesitar transformaciones repetidas, crea un DTO y mueve la transformación al caso de uso.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  UI: un componente que llama al caso de uso
&lt;/h2&gt;

&lt;p&gt;Mantén la UI enfocada en presentar datos y gestionar estado/errores.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/ui/HomePage.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ListProducts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../application/ListProducts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Si prefieres DTO, importa ListProductsWithDTO y ProductDTO en su lugar.&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_URL&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ListProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;HomePage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;mounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;listProducts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No se pudo cargar productos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mounted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})();&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Cargando…&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;crimson&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Productos&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;data-testid&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`product-id-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Precio: $&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Cuándo añadir repositorios (puertos) “hexagonales”?
&lt;/h2&gt;

&lt;p&gt;Añádelos cuando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;necesites más de una fuente de datos (REST, GraphQL, IndexedDB, memoria),&lt;/li&gt;
&lt;li&gt;quieras desacoplarte fuertemente del backend,&lt;/li&gt;
&lt;li&gt;o quieras tests de aplicación ultra rápidos sin MSW.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recuerda la nota de arriba&lt;/strong&gt;: “Si el proyecto crece o necesitas intercambiar fuentes de datos, añades un repositorio como puerto.” Aquí abajo verás un ejemplo de cómo sería el funcionamiento.&lt;/p&gt;

&lt;h3&gt;
  
  
  Puerto de repositorio (dominio)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/domain/ProductRepository.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementación HTTP del repositorio (infra)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/infrastructure/HttpProductRepository.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/ProductRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./APIClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HttpProductRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Caso de uso usando el puerto (aplicación)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsWithRepo.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/ProductRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsWithRepo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Si solo delega, cuestiónate si esta capa aporta valor (Middle Man).&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Composición (decides la fuente en un único lugar)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/app/composition.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpProductRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/HttpProductRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ListProductsWithRepo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../application/ListProductsWithRepo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_URL&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpProductRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Si quisieras memoria, bastaría con cambiar la implementación del puerto:&lt;/span&gt;
&lt;span class="c1"&gt;// const repo = new InMemoryProductRepository([{ name: "A", image: "/a.png", price: 10 }]);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ListProductsWithRepo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cómo funciona en la práctica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La UI usa listProducts.execute().&lt;/li&gt;
&lt;li&gt;Si mañana cambias de REST a GraphQL o a IndexedDB, implementas otro repositorio y no tocas ni UI ni casos de uso (salvo wiring).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  (Mis) Problemas con ejemplos
&lt;/h2&gt;

&lt;h3&gt;
  
  
  No hay suficiente complejidad de dominio
&lt;/h3&gt;

&lt;p&gt;Si tu caso es casi-CRUD y el reto principal está en la UX/estado, no en reglas de negocio, muchas capas añaden fricción sin beneficio.&lt;/p&gt;

&lt;p&gt;Ejemplo suficiente para empezar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProducts.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProducts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Simple, testeable (stub de APIClient o MSW) y sin “capas por capas”.&lt;/li&gt;
&lt;li&gt;Cuando aparezca complejidad real (paginación, filtros, cacheo, merge de fuentes), puedes introducir repositorios y casos de uso más ricos.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Interfaces inútiles
&lt;/h3&gt;

&lt;p&gt;Crear interfaces “por si acaso” suele ser ruido. La regla práctica:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crea una interfaz si y solo si:

&lt;ul&gt;
&lt;li&gt;tendrás 2+ implementaciones, o&lt;/li&gt;
&lt;li&gt;buscas desacoplarte del backend/cliente HTTP.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Anti‑ejemplo con una interfaz sin valor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/domain/UselessProductRepo.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Única implementación y uso en un solo lugar -&amp;gt; poco valor&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HttpProductRepository&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternativa más simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsSimple.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClient&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsSimple&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Capas estrictas: tipos de retorno y “Middle Man”
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;DTO vs Dominio: si Product y ProductDTO tienen los mismos campos, el DTO no aporta valor.&lt;/li&gt;
&lt;li&gt;“Middle Man”: un caso de uso que solo delega al repositorio sin añadir semántica es un code smell.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anti‑ejemplo (Middle Man):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsMiddleMan.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/ProductRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsMiddleMan&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Indirección sin abstracción: no aporta nada.&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cómo aportar valor real en la capa de aplicación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsEnriched.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/ProductRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsEnriched&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;minPrice&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;minPrice&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minPrice&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DTO solo cuando transforme algo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsToDTO.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductDTO&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ProductDTO&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/ProductRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsToDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ProductDTO&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;displayPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`$&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pros de “saltar capas”:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Menos indirection.&lt;/li&gt;
&lt;li&gt;Código más fácil de seguir.
Contras:&lt;/li&gt;
&lt;li&gt;Requiere criterio para no perder consistencia.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Repositorios en frontend: cuándo sobran y cómo simplificar
&lt;/h3&gt;

&lt;p&gt;Muchas veces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hay una sola fuente (tu API),&lt;/li&gt;
&lt;li&gt;queries simples,&lt;/li&gt;
&lt;li&gt;y el repositorio se usa en un solo punto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En esos casos, puedes ir directo con un APIClient y mantener testabilidad.&lt;/p&gt;

&lt;p&gt;Anti‑ejemplo importando axios en la aplicación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsAxiosInline.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsAxiosInline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://.../products`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Funciona, pero mezclas infraestructura (axios) en aplicación.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mejor: encapsula axios en un adapter y centraliza errores.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/infrastructure/APIClientAxios.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AxiosError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotFoundError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;APIClientAxios&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;AxiosError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotFoundError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Recurso no encontrado&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// more methods: post, put, delete...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso de uso usando el adapter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsWithAPIClientAxios.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClientAxios&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClientAxios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsWithAPIClientAxios&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIClientAxios&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ir “al límite”: instanciar internamente el cliente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ProductListSelfContained.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIClientAxios&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../infrastructure/APIClientAxios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductListSelfContained&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;APIClientAxios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_URL&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Ojo: dependencia oculta -&amp;gt; más difícil de testear y de cambiar en composición.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing cuando no hay repos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opción A (recomendada): tests sociables con MSW sobre la UI (sección “Testing” al final).&lt;/li&gt;
&lt;li&gt;Opción B: stub del adapter en tests de aplicación.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/__tests__/ListProductsWithAPIClientAxios.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ListProductsWithAPIClientAxios&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../ListProductsWithAPIClientAxios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FakeAPI&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;devuelve productos desde el adapter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fake&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FakeAPI&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/a.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;}]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usecase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ListProductsWithAPIClientAxios&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fake&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usecase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;resolves&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si más adelante necesitas intercambiar fuentes (REST/IndexedDB/memoria), entonces sí: introduce el puerto ProductRepository y obtendrás tests de aplicación ultrarrápidos con una implementación en memoria.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Aplicando hexagonal junto al patrón repositorio te permite crear tests unitarios que cumplan con el acrónimo FIRST:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast: rápidos para obtener feedback veloz.&lt;/li&gt;
&lt;li&gt;Isolated: aislados de DB/red.&lt;/li&gt;
&lt;li&gt;Repeatable: mismo resultado siempre.&lt;/li&gt;
&lt;li&gt;Self-validating: se validan solos (asserts claros).&lt;/li&gt;
&lt;li&gt;Timely: idealmente antes de desarrollar (TDD).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Con el enfoque simplificado propuesto, así cumplo gran parte:&lt;/p&gt;

&lt;p&gt;Tipos de tests (filosofía):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Write tests. Not too many. Mostly integration” (Kent C. Dodds).&lt;/li&gt;
&lt;li&gt;Yo lo adapto a: “Write tests, mostly sociable tests”.

&lt;ul&gt;
&lt;li&gt;En esta historia de usuario, prefiero tests sociables de UI con un servidor HTTP simulado que devuelva respuestas predefinidas.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Trade-off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Al levantar un servidor HTTP simulado, quizá pierdas algo de “F” (velocidad). Lo asumo porque el test es más representativo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Herramienta:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MSW (Mock Service Worker): mokea a nivel de red, no tu código.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cómo testear esta funcionalidad:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Omito unitarios “puros” de aplicación si no hay lógica (evito tests que solo replican una llamada).&lt;/li&gt;
&lt;li&gt;Escribo tests de UI que cubren el flujo principal y el de error, falseando la API con MSW.&lt;/li&gt;
&lt;li&gt;Para mayor seguridad antes de desplegar: tests E2E happy path en pre con Playwright.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ejemplo con MSW:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/ui/HomePage.test.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;setupServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;msw/node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HomePage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./HomePage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setupServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/products`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product Zero&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/img0.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product One&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/img1.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]))&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nf"&gt;afterEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetHandlers&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nf"&gt;afterAll&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="c1"&gt;// Ajusta según tu runner (Vitest/Jest). Con Vitest podrías hacer:&lt;/span&gt;
&lt;span class="c1"&gt;// vi.stubEnv("VITE_API_URL", apiUrl);&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;muestra productos al cargar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HomePage&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findAllByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/product-id-&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product Zero&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product One&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;muestra error si la API falla&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/products`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;res&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HomePage&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/No se pudo cargar productos|HTTP 500/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E2E con Playwright (idea, sin código extenso):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crea un test “happy path” que:

&lt;ul&gt;
&lt;li&gt;visita la Home deployada en pre,&lt;/li&gt;
&lt;li&gt;espera ver el listado real,&lt;/li&gt;
&lt;li&gt;verifica al menos 1–2 productos.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Úsalo como smoke test en cada release.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Screaming Architecture (mini abrebocas)
&lt;/h2&gt;

&lt;p&gt;Que el repo “grite” el dominio. En vez de “components/services/utils”, prefiere por feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;src/domain/Product.ts&lt;/li&gt;
&lt;li&gt;src/application/ListProducts.ts&lt;/li&gt;
&lt;li&gt;src/infrastructure/APIClient.ts&lt;/li&gt;
&lt;li&gt;src/ui/HomePage.tsx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuando la app crezca, separa por features (products, cart, auth) manteniendo esta idea.&lt;/p&gt;

&lt;p&gt;En próximos artículos voy a traer uno sobre Screaming Architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist para aplicarlo hoy
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Define tipos de dominio (Product).&lt;/li&gt;
&lt;li&gt;Crea un APIClient pequeño para HTTP.&lt;/li&gt;
&lt;li&gt;Escribe 1 caso de uso (ListProducts) que use el APIClient.&lt;/li&gt;
&lt;li&gt;Implementa la HomePage que llama al caso de uso.&lt;/li&gt;
&lt;li&gt;Solo si lo necesitas, añade un ProductRepository y su implementación HTTP (ver ejemplo de funcionamiento arriba).&lt;/li&gt;
&lt;li&gt;Añade tests (lee la sección final “Testing” para decidir qué y cómo probar).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ponemos en el centro el dominio (si lo hay), pero priorizamos simplicidad: no siempre necesitas capas intermedias entre lógica de aplicación, fuente de datos y UI.&lt;/li&gt;
&lt;li&gt;Testea donde más valor aporta: UI sociable con MSW y un E2E de humo con Playwright. Si el dominio crece, añade repositorios y tests unitarios rápidos en memoria.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Glosario (términos clave)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Middle Man (code smell)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Qué es: un “intermediario” que solo pasa la llamada a otra capa/objeto sin añadir valor (sin validar, transformar, decidir, ni encapsular reglas). Es “indirección sin abstracción”.&lt;/li&gt;
&lt;li&gt;Por qué es problema: añade complejidad y archivos extra, dificulta navegar el código y no aporta semántica.&lt;/li&gt;
&lt;li&gt;Cómo detectarlo:

&lt;ul&gt;
&lt;li&gt;La clase/método solo delega 1:1 a otra llamada.&lt;/li&gt;
&lt;li&gt;No hay lógica de negocio, ni transformación de datos, ni control de errores propio.&lt;/li&gt;
&lt;li&gt;Si lo eliminas y llamas directamente a la dependencia, nada cambia (salvo menos líneas).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Ejemplo:
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/application/ListProductsMiddleMan.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../domain/ProductRepository&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ListProductsMiddleMan&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Alternativas:

&lt;ul&gt;
&lt;li&gt;Eliminar la capa y usar directamente la dependencia.&lt;/li&gt;
&lt;li&gt;O bien justificarla añadiendo valor (filtrados, orden, mapeos, políticas de reintento, validaciones, etc.).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  E2E de humo (smoke test)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Qué es: un test end-to-end mínimo y rápido que verifica el camino feliz crítico (la app arranca y la funcionalidad principal no “echa humo” tras un deploy).&lt;/li&gt;
&lt;li&gt;Objetivo: detectar roturas graves en producción o pre-producción con el menor coste.&lt;/li&gt;
&lt;li&gt;Alcance típico:

&lt;ul&gt;
&lt;li&gt;Cargar la Home sin errores.&lt;/li&gt;
&lt;li&gt;Ver que se lista al menos un producto.&lt;/li&gt;
&lt;li&gt;Opcional: una interacción clave.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Cuándo ejecutarlo: en cada build de pre o antes de un deploy (pipeline de CD).&lt;/li&gt;

&lt;li&gt;Relación con otros tests:

&lt;ul&gt;
&lt;li&gt;Complementa a los tests de UI con MSW (rápidos y representativos en local/CI).&lt;/li&gt;
&lt;li&gt;No reemplaza tests unitarios donde haya lógica compleja: si el dominio crece, añádelos.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Te invito a visitar mi blog, donde encontrarás más contenido sobre JavaScript, React, CSS, IA, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>react</category>
      <category>typescript</category>
    </item>
    <item>
      <title>¿Qué es SOLID? Principios de diseño para programar código limpio en TypeScript y React</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sat, 02 Aug 2025 16:11:40 +0000</pubDate>
      <link>https://forem.com/johnserranodev/que-es-solid-principios-de-diseno-para-programar-codigo-limpio-en-typescript-y-react-118l</link>
      <guid>https://forem.com/johnserranodev/que-es-solid-principios-de-diseno-para-programar-codigo-limpio-en-typescript-y-react-118l</guid>
      <description>&lt;h1&gt;
  
  
  Introducción a los principios SOLID en la Programación Orientada a Objetos
&lt;/h1&gt;

&lt;p&gt;En el desarrollo de software, escribir código limpio, modular y fácil de mantener es fundamental. Aquí es donde entran los principios &lt;strong&gt;SOLID&lt;/strong&gt;: un conjunto de reglas que ayudan a diseñar clases y componentes bien estructurados.  &lt;/p&gt;

&lt;p&gt;Pero, ¿qué es SOLID? ¿Es un patrón de diseño, una arquitectura, o algo más?  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SOLID no es un patrón ni una arquitectura&lt;/strong&gt;, sino cinco principios de diseño que nos ayudan a organizar mejor nuestro código, especialmente en la &lt;strong&gt;Programación Orientada a Objetos (POO)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;En este artículo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicaremos qué es la POO y por qué es importante para entender SOLID.&lt;/li&gt;
&lt;li&gt;Veremos cada uno de los principios SOLID con ejemplos prácticos en &lt;strong&gt;TypeScript&lt;/strong&gt; (backend) y &lt;strong&gt;React&lt;/strong&gt; (frontend).&lt;/li&gt;
&lt;li&gt;Analizaremos las ventajas de aplicar SOLID y cómo empezar a implementarlo.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Conceptos básicos de la POO
&lt;/h2&gt;

&lt;p&gt;La &lt;strong&gt;Programación Orientada a Objetos (POO)&lt;/strong&gt; es un paradigma que organiza el código en “objetos” que representan elementos del mundo real.&lt;br&gt;&lt;br&gt;
Cada objeto tiene &lt;strong&gt;atributos&lt;/strong&gt; (características) y &lt;strong&gt;métodos&lt;/strong&gt; (acciones).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo sencillo:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TypeScript (Backend)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Usuario&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;correo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;correo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;correo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;correo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;iniciarSesion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// lógica de autenticación&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// React (Frontend)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;correo&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;nombre&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;correo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Clases e instanciación
&lt;/h3&gt;

&lt;p&gt;Las &lt;strong&gt;clases&lt;/strong&gt; funcionan como plantillas para crear objetos. Por ejemplo, una clase &lt;code&gt;SuperHeroe&lt;/code&gt; puede tener métodos como &lt;code&gt;volar()&lt;/code&gt; y atributos como &lt;code&gt;nombre&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Los 4 pilares de la POO
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abstracción&lt;/strong&gt;: Resumir lo esencial de un objeto y ocultar los detalles innecesarios.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encapsulamiento&lt;/strong&gt;: Proteger los datos internos de un objeto, exponiendo solo lo necesario.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Herencia&lt;/strong&gt;: Permitir que una clase hija herede atributos y métodos de una clase padre.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Polimorfismo&lt;/strong&gt;: Permitir que diferentes clases respondan de manera distinta a un mismo método.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Abstracción
&lt;/h3&gt;

&lt;p&gt;Extraer las características esenciales de un objeto y ocultar los detalles complejos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Solo exponemos lo necesario de la clase&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Vehiculo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nf"&gt;moverse&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Auto&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Vehiculo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;moverse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;El auto avanza sobre ruedas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;miAuto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Auto&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;miAuto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;moverse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "El auto avanza sobre ruedas"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
La clase &lt;code&gt;Vehiculo&lt;/code&gt; es una abstracción. No interesa cómo se mueve, solo que puede moverse. Cada subclase implementa el detalle.&lt;/p&gt;
&lt;h3&gt;
  
  
  Encapsulamiento
&lt;/h3&gt;

&lt;p&gt;Proteger los datos internos de un objeto y exponer solo una interfaz controlada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CuentaBancaria&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;saldo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saldoInicial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saldo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;saldoInicial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;depositar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;monto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saldo&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;monto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;obtenerSaldo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;saldo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cuenta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CuentaBancaria&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cuenta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;depositar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// cuenta.saldo = 99999; // Error: saldo es privado&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cuenta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;obtenerSaldo&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 1500&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
El atributo saldo está protegido y solo puede ser modificado mediante métodos públicos.&lt;/p&gt;
&lt;h3&gt;
  
  
  Herencia
&lt;/h3&gt;

&lt;p&gt;Permitir que una clase hija herede atributos y métodos de una clase padre.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nombre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;hacerSonido&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Algún sonido...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Perro&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;hacerSonido&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Guau!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;miPerro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Perro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Rex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;miPerro&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hacerSonido&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Guau!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;Perro&lt;/code&gt; hereda de &lt;code&gt;Animal&lt;/code&gt; y puede sobreescribir el método hacerSonido.&lt;/p&gt;
&lt;h3&gt;
  
  
  Polimorfismo
&lt;/h3&gt;

&lt;p&gt;Permitir que diferentes clases respondan de manera distinta a un mismo método.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animales&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Perro&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Rex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Gato&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Michi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;animales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animal&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hacerSonido&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="c1"&gt;// "Guau!"&lt;/span&gt;
&lt;span class="c1"&gt;// "Miau!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
Aunque ambos son &lt;code&gt;Animal&lt;/code&gt;, cada subclase implementa su propia versión de &lt;code&gt;hacerSonido&lt;/code&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  2. ¿Qué es SOLID?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SOLID&lt;/strong&gt; es el acrónimo de cinco principios de diseño para la POO, propuestos por Robert C. Martin (“Uncle Bob”).&lt;br&gt;&lt;br&gt;
Su objetivo es ayudarte a escribir código:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Más limpio&lt;/li&gt;
&lt;li&gt;Más mantenible&lt;/li&gt;
&lt;li&gt;Más flexible y escalable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Los cinco principios son:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;S&lt;/strong&gt;ingle Responsibility Principle (SRP) – Responsabilidad Única&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O&lt;/strong&gt;pen/Closed Principle (OCP) – Abierto/Cerrado&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L&lt;/strong&gt;iskov Substitution Principle (LSP) – Sustitución de Liskov&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I&lt;/strong&gt;nterface Segregation Principle (ISP) – Segregación de Interfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;D&lt;/strong&gt;ependency Inversion Principle (DIP) – Inversión de Dependencias&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  3. Los principios SOLID explicados con ejemplos
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Principio de Responsabilidad Única (SRP)
&lt;/h3&gt;

&lt;p&gt;Cada clase o componente debe tener una sola responsabilidad.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mal ejemplo (TypeScript):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Factura&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;calcularTotal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;imprimir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;guardarEnBD&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta clase hace demasiadas cosas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mejor ejemplo (TypeScript):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FacturaCalculo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;calcularTotal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FacturaImpresion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;imprimir&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FacturaPersistencia&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;guardarEnBD&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Frontend con React:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Un componente que muestra y guarda datos al mismo tiempo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Guarda y muestra datos juntos (mala práctica)&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// lógica de guardado&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;saveUser&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Guardar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Separando responsabilidades:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfileView&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UserProfileSave&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onSave&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;onSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Guardar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Uso&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserProfileView&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserProfileSave&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onSave&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;saveUser&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
Cada componente tiene una función clara: uno muestra datos, otro los guarda.&lt;/p&gt;


&lt;h3&gt;
  
  
  2. Principio de Abierto/Cerrado (OCP)
&lt;/h3&gt;

&lt;p&gt;Las clases deben estar &lt;strong&gt;abiertas para extensión pero cerradas para modificación&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mal ejemplo (TypeScript):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;habilidad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;usarHabilidad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;habilidad&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;volar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Si agrego más habilidades, tengo que modificar la clase.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mejor ejemplo (TypeScript):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;usarHabilidad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* implementación base */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroeVolador&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;SuperHeroe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;usarHabilidad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* volar */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;React Frontend:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Mal ejemplo (modificando para cada tipo de botón)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;danger&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Cada vez hay que modificar esta función para agregar un tipo nuevo&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En vez de modificar un componente para cada variante, extiéndelo o compón con props.&lt;/p&gt;

&lt;p&gt;✅ Buen ejemplo (usando composición)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Extender sin modificar:&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;PrimaryButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"blue"&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;DangerButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"red"&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PrimaryButton&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Primario&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Botón Primario
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;PrimaryButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DangerButton&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;¡Cuidado!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Botón de Peligro
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;DangerButton&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
Se pueden crear nuevos tipos de botones sin modificar el componente base.&lt;/p&gt;


&lt;h3&gt;
  
  
  3. Principio de Sustitución de Liskov (LSP)
&lt;/h3&gt;

&lt;p&gt;Las clases hijas deben poder usarse como sus padres, &lt;strong&gt;sin romper la aplicación&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mal ejemplo (TypeScript):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ave&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;volar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pinguino&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Ave&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;volar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No puedo volar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si reemplazo Ave por Pinguino, ¡el código se rompe!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mejor ejemplo:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ave&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AveVoladora&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Ave&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;volar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pinguino&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Ave&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;En React:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Mal ejemplo (hijo rompe comportamiento esperado)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ReadOnlyInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// No acepta onChange, rompe el contrato&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;readOnly&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Mejor ejemplo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Componente base: Input editable&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Variante: Input solo lectura, pero sigue aceptando onChange para cumplir LSP&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ReadOnlyInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;readOnly&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Componente de formulario que puede alternar entre editable y solo lectura&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Formulario&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;readOnly&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;valor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Texto inicial&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Elegimos el componente según la prop readOnly&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;InputComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;readOnly&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;ReadOnlyInput&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Nombre:
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;InputComponent&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;valor&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setValor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Valor actual: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;valor&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Ejemplo de uso en tu app principal&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;soloLectura&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSoloLectura&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSoloLectura&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;soloLectura&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cambiar a editable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cambiar a solo lectura&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formulario&lt;/span&gt; &lt;span class="na"&gt;readOnly&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;soloLectura&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;ReadOnlyInput&lt;/code&gt; sigue aceptando las mismas &lt;code&gt;props&lt;/code&gt;, aunque ignore algunas, no rompe el contrato.&lt;/p&gt;


&lt;h3&gt;
  
  
  4. Principio de Segregación de Interfaces (ISP)
&lt;/h3&gt;

&lt;p&gt;No fuerces a implementar métodos que no se necesitan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mal ejemplo (TypeScript):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;SuperHeroe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;volar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;nadar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ironman&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;SuperHeroe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;volar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;nadar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* Ironman no nada, pero debe implementar igual */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mejor ejemplo:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Volador&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;volar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Nadador&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;nadar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ironman&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Volador&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;volar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;En React:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ Mal ejemplo (props innecesarias)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;swim&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Algunos animales no vuelan ni nadan&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Buen ejemplo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;FlyingAnimal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fly&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Solo para animales que vuelan&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SwimmingAnimal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;swim&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Solo para animales que nadan&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
Cada componente recibe solo las &lt;code&gt;props&lt;/code&gt; que necesita.&lt;/p&gt;


&lt;h3&gt;
  
  
  5. Principio de Inversión de Dependencias (DIP)
&lt;/h3&gt;

&lt;p&gt;Las clases deben depender de &lt;strong&gt;abstracciones&lt;/strong&gt; (interfaces), no de implementaciones concretas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mal ejemplo (TypeScript):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notificador&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;emailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;notificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enviar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mejor ejemplo:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ServicioNotificacion&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;enviar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Notificador&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;servicio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ServicioNotificacion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;notificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;servicio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enviar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;En React:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;❌ Mal ejemplo (componente crea su propia dependencia)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hola!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Notificar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Buen ejemplo (la dependencia se inyecta)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Servicio de notificaciones (puede ser email, SMS, etc.)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Servicio de notificación: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Aquí podrías hacer una llamada a un API, por ejemplo.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Componente que usa el servicio inyectado (DIP)&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Notification&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;notificationService&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;¡Hola usuario!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Notificar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Ejemplo de uso en tu aplicación principal&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Instancia concreta del servicio de notificaciones&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serviceInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotificationService&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Ejemplo de Inversión de Dependencias (DIP) en React&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="na"&gt;notificationService&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;serviceInstance&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explicación&lt;/strong&gt;:&lt;br&gt;
El componente no conoce la implementación concreta, solo usa lo que recibe.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Ventajas y desventajas de aplicar SOLID
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ventajas:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Código más limpio y modular.&lt;/li&gt;
&lt;li&gt;Facilita pruebas (testing) y cambios.&lt;/li&gt;
&lt;li&gt;Escalabilidad y mantenibilidad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Desventajas:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Puede requerir más clases/archivos.&lt;/li&gt;
&lt;li&gt;A veces añade complejidad innecesaria en proyectos pequeños.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Aplicando SOLID en JavaScript y React
&lt;/h2&gt;

&lt;p&gt;Aunque JavaScript no es estrictamente orientado a objetos, &lt;strong&gt;puedes aplicar SOLID&lt;/strong&gt; en frameworks como React:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SRP:&lt;/strong&gt; Crea componentes pequeños y especializados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCP:&lt;/strong&gt; Extiende componentes mediante composición y props.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LSP:&lt;/strong&gt; Evita hacer suposiciones de tipos o estructuras internas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISP:&lt;/strong&gt; Define props claras y separa componentes según su función.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DIP:&lt;/strong&gt; Pasa datos y comportamientos por props/context, no desde dentro del componente.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Los principios SOLID te ayudan a escribir mejor código: más limpio, modular y fácil de mantener.&lt;br&gt;&lt;br&gt;
Si trabajas en backend (TypeScript) o frontend (React), empezar a aplicar SOLID te ayudará a mejorar la calidad de tus proyectos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Listo para dar el salto? ¡Empieza a aplicar SOLID en tu próximo proyecto y verás la diferencia!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi blog, donde encontrarás más contenido sobre JavaScript, React, CSS, IA, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>typescript</category>
      <category>react</category>
    </item>
    <item>
      <title>Capas en CSS: Guía Completa para Dominar la Regla @layer y Controlar la Especificidad</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Tue, 06 May 2025 21:19:46 +0000</pubDate>
      <link>https://forem.com/johnserranodev/capas-en-css-guia-completa-para-dominar-la-regla-layer-y-controlar-la-especificidad-lcg</link>
      <guid>https://forem.com/johnserranodev/capas-en-css-guia-completa-para-dominar-la-regla-layer-y-controlar-la-especificidad-lcg</guid>
      <description>&lt;h2&gt;
  
  
  Introducción: ¿Qué son las Capas de Cascada en CSS?
&lt;/h2&gt;

&lt;p&gt;Las capas de cascada (cascade layers) en CSS han sido introducidas para resolver uno de los problemas más complejos y persistentes en la escritura de estilos: los conflictos de especificidad. En este artículo exploraremos cuál es exactamente ese problema y cómo la regla &lt;code&gt;@layer&lt;/code&gt; nos ofrece una solución eficaz y moderna.&lt;/p&gt;

&lt;p&gt;La regla &lt;code&gt;@layer&lt;/code&gt; permite declarar estas capas de cascada, que funcionan de forma análoga a las capas en editores gráficos como Photoshop o GIMP: cada capa es un grupo independiente, pero en lugar de imágenes, gestionamos reglas CSS.&lt;/p&gt;

&lt;p&gt;El objetivo principal es claro:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Organizar mejor el código.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evitar los problemas clásicos de especificidad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reducir la necesidad de usar !important o sobreescribir selectores complejos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  El problema: La especificidad se vuelve inmanejable
&lt;/h2&gt;

&lt;p&gt;Todo desarrollador que ha trabajado con CSS se ha encontrado con la frustración de querer sobrescribir estilos provenientes de otras partes del código, de librerías o frameworks externos, solo para verse atrapado en una batalla de especificidad. Tradicionalmente, para resolver estos conflictos, se han creado "metodologías" y "buenas prácticas" que, en esencia, intentan evitar que la cascada actúe, en lugar de aprovecharla. Ejemplos de estas prácticas son restringirse a usar sólo clases simples o evitar selectores anidados.&lt;/p&gt;

&lt;p&gt;El manejo de la cascada y la especificidad ha sido durante años una de las partes más confusas de CSS. Esto se debe en parte a que pocos lenguajes basan su comportamiento en una cascada, pero también a que la forma tradicional de resolución de estilos en CSS depende de heurísticas, no de un control explícito por parte del autor.&lt;/p&gt;

&lt;p&gt;Por ejemplo, la especificidad está basada en la suposición de que un selector más detallado (como un ID único) debería tener mayor prioridad que un selector genérico (como una clase). Sin embargo, esto no siempre refleja las verdaderas intenciones del autor, y las soluciones comunes suelen agravar el problema: añadir selectores innecesarios o recurrir al temido &lt;code&gt;!important&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Especificidad forzada y confusa */&lt;/span&gt;
&lt;span class="nc"&gt;.overly&lt;/span&gt;&lt;span class="nf"&gt;#powerful&lt;/span&gt; &lt;span class="nc"&gt;.framework.widget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;maroon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.my-single_class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* ¿Agregar IDs? */&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rebeccapurple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* ¿O usar !important? */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  La solución: Capas de cascada para un control real
&lt;/h2&gt;

&lt;p&gt;Las capas de cascada permiten a los autores de CSS tomar el control total de la cascada, creando sistemas intencionados y ordenados, en lugar de depender de reglas implícitas y suposiciones.&lt;/p&gt;

&lt;p&gt;Mediante la regla &lt;code&gt;@layer&lt;/code&gt; y las importaciones con capa mediante &lt;code&gt;@import&lt;/code&gt;, podemos establecer nuestras propias capas jerárquicas: desde los estilos de bajo nivel como resets y temas base, hasta las capas superiores como componentes, utilidades y sobrescrituras.&lt;/p&gt;

&lt;p&gt;Dentro de cada capa, la especificidad sigue funcionando como siempre. Pero entre capas, los conflictos siempre se resuelven a favor de la capa con mayor prioridad, sin necesidad de escalar especificidad ni usar &lt;code&gt;!important&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;framework&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.overly&lt;/span&gt;&lt;span class="nf"&gt;#powerful&lt;/span&gt; &lt;span class="nc"&gt;.framework.widget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;maroon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;site&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.my-single_class&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rebeccapurple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las capas son ordenadas y no se acumulan como la especificidad de los selectores. Añadir más capas no incrementa su poder. Tampoco son absolutas como &lt;code&gt;!important&lt;/code&gt;, ni arbitrarias como un &lt;code&gt;z-index&lt;/code&gt; inflado. De hecho, por defecto, los estilos dentro de una capa son menos prioritarios que los estilos no agrupados en capas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;defaults&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;any-link&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;maroon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Estilos no encapsulados en capas siempre tienen la máxima prioridad */&lt;/span&gt;
&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;mediumvioletred&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sintaxis y declaración de capas
&lt;/h2&gt;

&lt;p&gt;CSS nos ofrece varias formas para declarar capas utilizando &lt;code&gt;@layer&lt;/code&gt; o mediante &lt;code&gt;@import&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sintaxis&lt;/th&gt;
&lt;th&gt;Descripción&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@layer nombre&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crea una capa CSS con el nombre indicado.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@layer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crea una capa anónima (sin nombre).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@layer nombre.subcapa&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Crea una capa con subcapas anidadas.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@layer nombre1, nombre2, ...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Declara y ordena múltiples capas.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@import url("archivo.css") layer(nombre)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Importa CSS en la capa especificada.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;El orden en que se definen las capas determina su prioridad en la cascada, algo fundamental para evitar conflictos de especificidad. No obstante, como veremos más adelante en esta guía, ese orden también puede ser manipulado para ajustarlo a nuestras necesidades.&lt;/p&gt;

&lt;p&gt;A continuación, exploraremos cada una de estas sintaxis en detalle y aprenderemos a utilizarlas para construir sistemas CSS más robustos, predecibles y sostenibles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo crear y ordenar Capas en CSS
&lt;/h2&gt;

&lt;p&gt;Ahora que entendemos qué son las capas de cascada y por qué resuelven problemas de especificidad, es momento de aprender a utilizarlas de forma práctica en nuestros estilos CSS. La regla &lt;code&gt;@layer&lt;/code&gt; es sencilla en su sintaxis, pero poderosa en sus aplicaciones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Declarando una Capa Simple&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;La forma más básica es declarar una capa con un nombre único y agrupar dentro de ella nuestras reglas CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;system-ui&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta capa llamada &lt;code&gt;base&lt;/code&gt; se comporta como un grupo. Los estilos dentro de ella competirán entre sí usando la especificidad tradicional, pero como bloque completo, &lt;code&gt;base&lt;/code&gt; tendrá una prioridad determinada por su posición frente a otras capas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Declarando Capas Anónimas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si no necesitas un nombre específico, puedes crear una capa anónima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las capas anónimas son útiles para agrupar estilos sin preocuparte por su identificación, pero su uso es menos común en proyectos grandes donde el control del orden es esencial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creando Subcapas Anidadas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CSS permite anidar capas creando jerarquías internas mediante subcapas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;buttons&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.25rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso, buttons es una subcapa dentro de components. La jerarquía te da mayor control para modular tu CSS y ordenar prioridades dentro de sistemas grandes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Declarando y ordenando Múltiples Capas
&lt;/h2&gt;

&lt;p&gt;Una de las grandes ventajas de las cascade layers es que puedes declarar varias capas al mismo tiempo y establecer su orden:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El orden en esta declaración es crucial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;reset tendrá la menor prioridad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;utilities tendrá la mayor prioridad dentro de las capas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Las reglas fuera de cualquier capa siguen siendo las de máxima prioridad (salvo que uses !important).&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplo claro: Controlando el orden con @layer
&lt;/h2&gt;

&lt;p&gt;Observa el siguiente ejemplo. Aquí declaramos un orden específico: primero la capa &lt;code&gt;reset&lt;/code&gt;, luego &lt;code&gt;texts&lt;/code&gt;, y al final &lt;code&gt;theme&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Primer botón&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Segundo botón&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* Declaramos el orden de las capas */&lt;/span&gt;
  &lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;reset&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#3454d1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;outset&lt;/span&gt; &lt;span class="m"&gt;#6381db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Color de texto en theme */&lt;/span&gt;
      &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;texts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Color de texto en texts */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Qué color se aplica?
&lt;/h2&gt;

&lt;p&gt;Aunque en el flujo normal de CSS el color rojo &lt;code&gt;(texts)&lt;/code&gt; viene después y debería prevalecer, gana la capa &lt;code&gt;theme&lt;/code&gt;, porque hemos definido en la primera línea que &lt;code&gt;theme&lt;/code&gt; es la capa con mayor prioridad entre las tres. Por tanto, el texto aparecerá en blanco, como define la capa &lt;code&gt;theme&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fusionando reglas de una misma Capa
&lt;/h2&gt;

&lt;p&gt;Otra característica importante es que, si vuelves a declarar una capa con el mismo nombre más adelante, el navegador fusiona ambas definiciones en la misma capa, sin alterar su posición en la prioridad general.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;gold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Nueva regla dentro de theme */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, como ambas reglas &lt;code&gt;(color: white y color: gold)&lt;/code&gt; están en la misma capa &lt;code&gt;theme&lt;/code&gt;, se aplicará la última que aparezca dentro de esa capa, es decir, el color dorado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regla de Oro: Los estilos fuera de Capa siempre Ganan
&lt;/h2&gt;

&lt;p&gt;Cualquier estilo declarado fuera de cualquier &lt;code&gt;@layer&lt;/code&gt; (es decir, sin pertenecer a ninguna capa) se agrupará automáticamente en la capa anónima. Esta capa siempre tiene la máxima prioridad sobre cualquier capa que definas con &lt;code&gt;@layer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Esta regla gana siempre sobre cualquier capa */&lt;/span&gt;
&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por tanto, si necesitas forzar estilos al margen de tu sistema de capas, simplemente escríbelos fuera de cualquier @layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Importando CSS en una Capa
&lt;/h2&gt;

&lt;p&gt;También puedes importar archivos CSS directamente dentro de una capa, ideal para organizar tu proyecto modularmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url("reset.css")&lt;/span&gt; &lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url("framework.css")&lt;/span&gt; &lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto asegura que todo el contenido de &lt;code&gt;reset.css&lt;/code&gt; estará encapsulado en la capa &lt;code&gt;reset&lt;/code&gt;, evitando que choque en especificidad con otras partes de tu código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Regla Fundamental: El orden define la Prioridad
&lt;/h2&gt;

&lt;p&gt;Las capas se aplican en el orden en que se declaran, no en el orden en que el CSS es escrito dentro de ellas. Es decir, si defines primero &lt;code&gt;@layer base&lt;/code&gt; y luego &lt;code&gt;@layer components&lt;/code&gt;, la capa &lt;code&gt;components&lt;/code&gt; tendrá prioridad, incluso si sus selectores tienen menor especificidad.&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;crimson&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso, el &lt;code&gt;h1&lt;/code&gt; será &lt;code&gt;crimson&lt;/code&gt; porque &lt;code&gt;components&lt;/code&gt; es una capa declarada después de base.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ventajas claras de las Capas en CSS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Evitan la escalada de especificidad.&lt;/li&gt;
&lt;li&gt;Reducen el uso innecesario de &lt;code&gt;!important&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Permiten importar librerías sin perder el control sobre tus estilos personalizados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fomentan un código CSS modular, predecible y mantenible a largo plazo.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Para qué sirven las Capas en CSS?
&lt;/h2&gt;

&lt;p&gt;Las capas &lt;code&gt;(@layer)&lt;/code&gt; en CSS nos permiten organizar y controlar la prioridad de nuestros estilos de forma mucho más flexible que con la especificidad tradicional.&lt;/p&gt;

&lt;p&gt;Cuando tu proyecto crece o incluyes librerías externas, la especificidad empieza a depender de factores difíciles de manejar. Con &lt;code&gt;@layer&lt;/code&gt;, puedes definir de forma explícita qué grupo de estilos tiene prioridad sobre otro, sin necesidad de recurrir a selectores más largos o a &lt;code&gt;!important&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Especificidad: El problema que resuelve @layer
&lt;/h2&gt;

&lt;p&gt;Observa este ejemplo básico. Aquí usamos el mismo selector &lt;code&gt;.primary&lt;/code&gt; varias veces. CSS simplemente aplica la propiedad del último bloque que coincide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#34a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;outset&lt;/span&gt; &lt;span class="m"&gt;#6381db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso, el color de texto será verde (color: green), ya que es el último que aparece para la propiedad color.&lt;/p&gt;

&lt;h2&gt;
  
  
  Especificidad: Cómo afecta cuando cambian los selectores
&lt;/h2&gt;

&lt;p&gt;Ahora, hagamos los selectores un poco más específicos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Especificidad: 0,2,1 */&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Especificidad: 0,1,1 */&lt;/span&gt;
&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#34a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;outset&lt;/span&gt; &lt;span class="m"&gt;#6381db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* Especificidad: 0,1,0 */&lt;/span&gt;
&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aquí ya no importa tanto el orden. El navegador aplicará las propiedades siguiendo la especificidad:&lt;/p&gt;

&lt;p&gt;Primero se aplican los estilos con menos especificidad &lt;code&gt;(.primary con 0,1,0)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Luego los de especificidad media &lt;code&gt;(button.primary con 0,1,1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por último, los más específicos &lt;code&gt;(button[class].primary con 0,2,1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;🔎 Resultado:&lt;/p&gt;

&lt;p&gt;El color rojo prevalecerá, porque el selector &lt;code&gt;button[class].primary&lt;/code&gt; es el más específico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo @layer Cambia las Reglas del Juego
&lt;/h2&gt;

&lt;p&gt;Ahora vamos a agrupar el selector más específico dentro de una capa llamada &lt;code&gt;texts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;texts&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;class&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#34a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;outset&lt;/span&gt; &lt;span class="m"&gt;#6381db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Qué ocurre ahora?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Primero, el navegador procesa la capa &lt;code&gt;texts&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Luego, agrupa y aplica todos los estilos fuera de capa en lo que se llama la capa anónima.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Y por regla general, esta capa anónima siempre tiene mayor prioridad que cualquier capa declarada con &lt;code&gt;@layer&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por tanto, el color verde &lt;code&gt;(color: green)&lt;/code&gt; volverá a ganar, incluso aunque el selector de la capa &lt;code&gt;texts&lt;/code&gt; tenga mayor especificidad. Esto demuestra cómo &lt;code&gt;@layer&lt;/code&gt; permite a los desarrolladores reorganizar la prioridad de estilos de forma más potente que simplemente aumentando la especificidad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uso de @layer con CSS Nesting
&lt;/h2&gt;

&lt;p&gt;Gracias al &lt;strong&gt;CSS Nesting nativo&lt;/strong&gt;, también podemos declarar capas dentro de un selector. Esto permite una estructura de código aún más ordenada y modular.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Hello, John Serrano!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nc"&gt;.primary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@layer&lt;/span&gt; &lt;span class="err"&gt;theme&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;indigo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Cómo funciona aquí?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;En la línea &lt;code&gt;@layer base, theme;&lt;/code&gt; declaramos que la capa base se aplicará antes que la capa &lt;code&gt;theme&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Así, aunque &lt;code&gt;theme&lt;/code&gt; venga antes en el código, sus estilos ganan porque está declarada con mayor prioridad.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si cambias esa primera línea por:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@layer&lt;/span&gt; &lt;span class="n"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, la capa &lt;code&gt;base&lt;/code&gt; tendrá prioridad y el fondo gris sobrescribirá al fondo índigo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;Las capas en CSS &lt;code&gt;(@layer)&lt;/code&gt; nos permiten controlar el orden y la prioridad de los estilos de forma más clara y organizada, sin depender únicamente de la especificidad. Son una herramienta poderosa para mantener el código limpio y predecible, especialmente en proyectos grandes o con estilos externos.&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi blog, donde encontrarás más contenido sobre JavaScript, React, CSS, IA, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>css</category>
    </item>
    <item>
      <title>Zustand: La solución más simple y eficiente para gestión de Estado en React</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sun, 27 Apr 2025 17:24:19 +0000</pubDate>
      <link>https://forem.com/johnserranodev/zustand-la-solucion-mas-simple-y-eficiente-para-gestion-de-estado-en-react-1bn4</link>
      <guid>https://forem.com/johnserranodev/zustand-la-solucion-mas-simple-y-eficiente-para-gestion-de-estado-en-react-1bn4</guid>
      <description>&lt;p&gt;El manejo de estado en aplicaciones React es un desafío recurrente. Librerías como Redux o Redux Toolkit ofrecen soluciones robustas pero, en muchos casos, demasiado complejas para necesidades simples. &lt;strong&gt;Zustand&lt;/strong&gt; emerge como una alternativa moderna, liviana y extremadamente intuitiva.&lt;/p&gt;

&lt;p&gt;En este artículo te guiaré desde qué es Zustand, sus ventajas sobre otras opciones, hasta cómo implementar un contador utilizando middlewares como &lt;code&gt;persist&lt;/code&gt; y &lt;code&gt;devtools&lt;/code&gt;, e incluso integrar validaciones con &lt;strong&gt;Zod&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es Zustand?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Zustand&lt;/strong&gt; ("estado" en alemán) es una librería minimalista de manejo de estado para aplicaciones React. Fue creada por &lt;strong&gt;Poimandres&lt;/strong&gt; (los mismos de &lt;code&gt;jotai&lt;/code&gt; y &lt;code&gt;react-three-fiber&lt;/code&gt;) y ofrece una API pequeña pero extremadamente poderosa.&lt;/p&gt;

&lt;p&gt;Algunas características principales:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No depende del árbol de componentes.&lt;/li&gt;
&lt;li&gt;No requiere boilerplate.&lt;/li&gt;
&lt;li&gt;Trabaja de forma reactiva pero es independiente de React internamente.&lt;/li&gt;
&lt;li&gt;Permite middlewares para persistencia, devtools, entre otros.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparación con Otras Soluciones
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;Redux&lt;/th&gt;
&lt;th&gt;Redux Toolkit&lt;/th&gt;
&lt;th&gt;Zustand&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Boilerplate&lt;/td&gt;
&lt;td&gt;Muy Alto&lt;/td&gt;
&lt;td&gt;Moderado&lt;/td&gt;
&lt;td&gt;Muy Bajo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API&lt;/td&gt;
&lt;td&gt;Verbosa&lt;/td&gt;
&lt;td&gt;Simplificada&lt;/td&gt;
&lt;td&gt;Muy simple&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Curva de Aprendizaje&lt;/td&gt;
&lt;td&gt;Alta&lt;/td&gt;
&lt;td&gt;Media&lt;/td&gt;
&lt;td&gt;Muy Baja&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integración Devtools&lt;/td&gt;
&lt;td&gt;Manual + Configuración extra&lt;/td&gt;
&lt;td&gt;Integración automática&lt;/td&gt;
&lt;td&gt;Sencilla y directa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistencia de Estado&lt;/td&gt;
&lt;td&gt;Requiere configuración manual&lt;/td&gt;
&lt;td&gt;Requiere middlewares adicionales&lt;/td&gt;
&lt;td&gt;Integrado vía middleware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uso fuera de componentes&lt;/td&gt;
&lt;td&gt;Difícil&lt;/td&gt;
&lt;td&gt;Más sencillo pero no nativo&lt;/td&gt;
&lt;td&gt;Muy fácil&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tamaño de la librería&lt;/td&gt;
&lt;td&gt;Grande&lt;/td&gt;
&lt;td&gt;Medio&lt;/td&gt;
&lt;td&gt;Pequeño (~1KB gzipped)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Como puedes observar, &lt;strong&gt;Zustand&lt;/strong&gt; es ideal para quienes buscan una solución directa, moderna y altamente eficiente, mientras que &lt;strong&gt;Redux Toolkit&lt;/strong&gt; representa una mejora significativa sobre Redux clásico, pero aún mantiene cierta complejidad estructural.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creando un Store de Contador con Zustand
&lt;/h2&gt;

&lt;p&gt;Primero, instalemos Zustand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;zustand
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, creamos el store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/stores/counterStore.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCounterStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CounterState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
  &lt;span class="na"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
  &lt;span class="na"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Notas importantes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El nombre &lt;code&gt;useCounterStore&lt;/code&gt; sigue la convención de React Hooks.&lt;/li&gt;
&lt;li&gt;El store &lt;strong&gt;debe estar fuera&lt;/strong&gt; de los componentes para ser compartido globalmente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Usando el Store en un Componente
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/components/Counter.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useCounterStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../stores/counterStore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reset&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCounterStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Incrementar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;decrement&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Decrementar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Resetear&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esto tienes un contador funcional, sin necesidad de reducers, actions ni context providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agregando Persistencia y Devtools
&lt;/h2&gt;

&lt;p&gt;Zustand permite utilizar middlewares para ampliar funcionalidades.&lt;/p&gt;

&lt;p&gt;Lo primero que debemos hacer es instalar la &lt;a href="https://chromewebstore.google.com/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd" rel="noopener noreferrer"&gt;extensión Redux DevTools de Chrome&lt;/a&gt; para utilizar el middleware devtools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;devtools&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand/middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Envolvemos todo nuestro store con devtools&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usePlainStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;devtools&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;...))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modificamos el store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;devtools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;persist&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zustand/middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CounterState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCounterStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CounterState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()(&lt;/span&gt;
  &lt;span class="nf"&gt;devtools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
        &lt;span class="na"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
        &lt;span class="na"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counter-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;¿Qué logramos?:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;persist&lt;/code&gt;&lt;/strong&gt; guarda el estado en &lt;code&gt;localStorage&lt;/code&gt; o &lt;code&gt;sessionStorage&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;devtools&lt;/code&gt;&lt;/strong&gt; permite inspeccionar el estado con Redux DevTools (sin usar Redux).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto facilita el debuggeo y asegura que el contador persista aunque recargues la página.&lt;/p&gt;

&lt;h2&gt;
  
  
  Si deseas ver un ejemplo más completo, incluyendo un carrito de compras, te invito a leer el siguiente artículo 👇
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://johnserrano.co/blog/zustand-aprende-a-gestionar-tu-estado-en-react-una-alternativa-sencilla-a-redux" rel="noopener noreferrer"&gt;Zustand: Aprende a gestionar tu estado en React una alternativa sencilla a Redux&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrando Zod para Validaciones
&lt;/h2&gt;

&lt;p&gt;Aunque Zustand no maneja formularios, en una aplicación real puedes querer validar datos antes de actualizar el estado. Para eso &lt;strong&gt;Zod&lt;/strong&gt; es una excelente opción.&lt;/p&gt;

&lt;p&gt;Instalamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;zod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ejemplo básico para validar antes de setear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CountSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;number&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useCounterStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CounterState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()(&lt;/span&gt;
  &lt;span class="nf"&gt;devtools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;persist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CountSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="na"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CountSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="na"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;counter-storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusión:&lt;/strong&gt; Con Zod evitamos que el contador pase de ciertos límites definidos de manera declarativa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflexión Final
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Zustand&lt;/strong&gt; representa la evolución natural de la gestión de estado en React: simplicidad, flexibilidad y potencia.&lt;/p&gt;

&lt;p&gt;Si estás cansado del exceso de configuración de Redux o simplemente buscas una forma más intuitiva de manejar estados globales, &lt;strong&gt;Zustand es, sin duda, una opción que deberías considerar seriamente&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi blog, donde encontrarás más contenido sobre JavaScript, React, CSS, IA, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>react</category>
      <category>redux</category>
    </item>
    <item>
      <title>HTML avanzado y atajos Emmet en 10 Minutos</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sun, 20 Apr 2025 17:29:54 +0000</pubDate>
      <link>https://forem.com/johnserranodev/html-avanzado-y-atajos-emmet-en-10-minutos-5g4h</link>
      <guid>https://forem.com/johnserranodev/html-avanzado-y-atajos-emmet-en-10-minutos-5g4h</guid>
      <description>&lt;p&gt;Dominar &lt;strong&gt;HTML&lt;/strong&gt; y &lt;strong&gt;Emmet&lt;/strong&gt; no solo mejora la &lt;strong&gt;productividad&lt;/strong&gt;, sino que también garantiza la creación de sitios web accesibles, semánticos y optimizados para motores de búsqueda. En este artículo, exploraremos técnicas avanzadas de HTML y cómo Emmet puede acelerar significativamente tu flujo de trabajo.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. HTML Semántico: Mejora de SEO y Accesibilidad
&lt;/h2&gt;

&lt;p&gt;El HTML semántico utiliza etiquetas que describen claramente el propósito del contenido que encierran, facilitando la comprensión tanto para desarrolladores como para motores de búsqueda y tecnologías de asistencia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplos de elementos semánticos&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;: Encabezado de una sección o página.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;: Contenedor para enlaces de navegación.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;: Contenido principal del documento.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;: Contenido independiente y autocontenible.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;: Agrupación temática de contenido.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;: Contenido complementario o lateral.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;: Pie de página de una sección o documento.​&lt;/p&gt;

&lt;p&gt;Ejemplo Práctico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Noticias Recientes&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Este es un artículo de noticias independiente.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;aside&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Artículos Relacionados&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Explora más sobre este tema.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;© 2025 Mi Sitio Web&lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El uso adecuado de estas etiquetas mejora la estructura del documento, la accesibilidad y el posicionamiento en buscadores.​&lt;/p&gt;

&lt;h2&gt;
  
  
  Aprende los conceptos básicos de HTML y descubre por qué es fundamental para cualquier desarrollador web 👇
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/mI_RDbjMfVQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Atributos personalizados con &lt;code&gt;data-*&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Los atributos personalizados &lt;code&gt;data-*&lt;/code&gt; permiten almacenar información adicional en elementos &lt;strong&gt;HTML&lt;/strong&gt; sin afectar su presentación. Son especialmente útiles para pasar datos entre HTML y &lt;strong&gt;JavaScript&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-product-id=&lt;/span&gt;&lt;span class="s"&gt;"123"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Agregar al Carrito&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;boton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Salida: 123&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Imágenes responsivas con &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; y &lt;code&gt;&amp;lt;source&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;El elemento &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; permite servir diferentes versiones de una imagen según el tamaño de la pantalla o el dispositivo del usuario, mejorando la &lt;strong&gt;experiencia visual&lt;/strong&gt; y el &lt;strong&gt;rendimiento&lt;/strong&gt;.​&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 800px)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"imagen-grande.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 400px)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"imagen-mediana.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"imagen-pequeña.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Descripción de la imagen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Formularios mejorados con HTML5
&lt;/h2&gt;

&lt;p&gt;HTML5 introduce nuevos tipos de entrada que facilitan la validación y mejoran la experiencia del usuario.​&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"correo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Correo Electrónico:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"correo"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"fecha"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Fecha de Nacimiento:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"date"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"fecha"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Enviar&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El uso de atributos como &lt;code&gt;required&lt;/code&gt; y tipos de entrada específicos reduce la necesidad de &lt;strong&gt;validaciones adicionales&lt;/strong&gt; con JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Contenido interactivo con &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; y &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Estas etiquetas permiten crear &lt;strong&gt;secciones desplegables&lt;/strong&gt; sin necesidad de JavaScript, ideales para preguntas frecuentes o contenido adicional.&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;details&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Más Información&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Este contenido se muestra al hacer clic.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/details&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Inclusión de contenido externo con &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;El elemento &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; permite incrustar contenido de otras fuentes, como videos de &lt;strong&gt;YouTube&lt;/strong&gt; o mapas de Google.​&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; 
  &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"560"&lt;/span&gt; 
  &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"315"&lt;/span&gt; 
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.youtube.com/embed/ID_DEL_VIDEO"&lt;/span&gt; 
  &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Reproductor de video de YouTube"&lt;/span&gt; 
  &lt;span class="na"&gt;frameborder=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; 
  &lt;span class="na"&gt;allowfullscreen&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Metadatos para SEO y compartición en Redes Sociales
&lt;/h2&gt;

&lt;p&gt;Las etiquetas &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; proporcionan información sobre la página, mejorando su &lt;strong&gt;visibilidad en buscadores&lt;/strong&gt; y cómo se muestra al compartir en redes sociales.​&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Aprende HTML avanzado en 10 minutos."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Guía de HTML Avanzado"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"miniatura.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Componentes Web: Elementos HTML personalizados
&lt;/h2&gt;

&lt;p&gt;Los &lt;strong&gt;Web Components&lt;/strong&gt; permiten crear elementos personalizados y reutilizables, encapsulando su funcionalidad y estilo.​&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;mi-boton&amp;gt;&amp;lt;/mi-boton&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MiBoton&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;HTMLElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;connectedCallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;button&amp;gt;Haz Clic&amp;lt;/button&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;customElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mi-boton&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MiBoton&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Mejora de Accesibilidad con ARIA
&lt;/h2&gt;

&lt;p&gt;Los atributos &lt;strong&gt;ARIA&lt;/strong&gt; &lt;em&gt;(Accessible Rich Internet Applications)&lt;/em&gt; mejoran la accesibilidad de elementos interactivos para usuarios que utilizan tecnologías de asistencia.​&lt;/p&gt;

&lt;p&gt;Ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Cerrar menú"&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"cerrarMenu()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;X&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Aumenta tu Productividad con Emmet
&lt;/h2&gt;

&lt;p&gt;Emmet es una &lt;strong&gt;herramienta integrada&lt;/strong&gt; en la mayoría de editores modernos (como VS Code) que permite escribir HTML y CSS mucho más rápido gracias a su sistema de abreviaciones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo funciona?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simplemente escribes una abreviación y presionas &lt;code&gt;Tab&lt;/code&gt; para expandirla a código HTML completo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplos útiles de Emmet&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Abreviación: &lt;code&gt;ul&amp;gt;li*3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abreviación: &lt;code&gt;.card&amp;gt;h2+p&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Abreviación: &lt;code&gt;form:post&amp;gt;input:text+input:password+button:submit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Bonus: Multiplicación y atributos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;div.box$*3&lt;/code&gt; ➜&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"box3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;input:email[name=email required]&lt;/code&gt; ➜&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Consejo profesional: Usa Emmet &lt;strong&gt;Wrap with Abbreviation (Cmd/Ctrl + Shift + P)&lt;/strong&gt; para envolver contenido existente con estructura Emmet.&lt;/p&gt;

&lt;p&gt;Emmet &lt;em&gt;Wrap with Abbreviation&lt;/em&gt; es una funcionalidad avanzada que te permite envolver código existente con una estructura HTML nueva, usando abreviaciones de Emmet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Cómo se usa?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Selecciona el contenido que deseas envolver.&lt;/p&gt;

&lt;p&gt;Presiona &lt;code&gt;Cmd/Ctrl + Shift + P&lt;/code&gt; para abrir la paleta de comandos en VS Code.&lt;/p&gt;

&lt;p&gt;Escribe o selecciona: "Emmet: Wrap with Abbreviation".&lt;/p&gt;

&lt;p&gt;Escribe la abreviación, por ejemplo: &lt;code&gt;div.container&amp;gt;ul&amp;gt;li*3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Presiona Enter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo práctico&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Supón que tienes este texto seleccionado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Manzana
Pera
Banana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y aplicas &lt;code&gt;ul&amp;gt;li*3&lt;/code&gt;, Emmet generará:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Manzana&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Pera&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Banana&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es ideal para reorganizar contenido rápidamente con estructuras HTML limpias.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;Dominar HTML moderno no se trata únicamente de &lt;strong&gt;conocer etiquetas básicas&lt;/strong&gt;, sino de entender cómo construir estructuras &lt;strong&gt;semánticas&lt;/strong&gt;, &lt;strong&gt;accesibles&lt;/strong&gt; y optimizadas para buscadores y usuarios. Incorporar etiquetas como &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;figure&amp;gt;&lt;/code&gt; o &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; no solo mejora el SEO, sino también la organización y mantenibilidad del código. Además, aprovechar atributos como &lt;code&gt;loading="lazy"&lt;/code&gt;, &lt;code&gt;autofocus&lt;/code&gt;, &lt;code&gt;required&lt;/code&gt; o &lt;code&gt;pattern&lt;/code&gt; permite crear experiencias más fluidas e inteligentes sin depender siempre de &lt;strong&gt;JavaScript&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Por otro lado, herramientas como &lt;strong&gt;Emmet&lt;/strong&gt; potencian la &lt;strong&gt;productividad&lt;/strong&gt; al automatizar tareas repetitivas y facilitar la creación rápida de estructuras complejas. Funcionalidades como &lt;em&gt;"Wrap with Abbreviation"&lt;/em&gt; permiten transformar contenido existente en HTML estructurado con solo unos atajos de teclado, lo que marca una gran diferencia en el flujo de trabajo diario.&lt;/p&gt;

&lt;p&gt;En definitiva, aprender &lt;strong&gt;HTML avanzado&lt;/strong&gt; y dominar atajos como los de &lt;strong&gt;Emmet&lt;/strong&gt; es una inversión que mejora tu velocidad, tu calidad de desarrollo y tu claridad mental al enfrentar proyectos web de cualquier escala. La eficiencia no está reñida con la profesionalidad; al contrario, la potencia.&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi blog, donde encontrarás más contenido sobre JavaScript, React, CSS, IA, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>html</category>
    </item>
    <item>
      <title>Lazy Loading en HTML: cómo cargar imágenes de forma eficiente sin usar JavaScript</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Mon, 07 Apr 2025 17:01:19 +0000</pubDate>
      <link>https://forem.com/johnserranodev/lazy-loading-en-html-como-cargar-imagenes-de-forma-eficiente-sin-usar-javascript-48e7</link>
      <guid>https://forem.com/johnserranodev/lazy-loading-en-html-como-cargar-imagenes-de-forma-eficiente-sin-usar-javascript-48e7</guid>
      <description>&lt;p&gt;Descubre cómo implementar el lazy loading de imágenes utilizando solo HTML. Aprende a mejorar la velocidad de carga de tu sitio web y el SEO sin escribir una sola línea de JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es el lazy loading y cómo funciona?
&lt;/h2&gt;

&lt;p&gt;Cuando visitas un sitio web, el navegador descarga todos los recursos necesarios para mostrar la página correctamente: &lt;strong&gt;imágenes&lt;/strong&gt;, scripts, hojas de estilo, &lt;strong&gt;iframes&lt;/strong&gt;, etc. Por defecto, estos recursos se cargan incluso si están &lt;strong&gt;fuera del área visible del usuario&lt;/strong&gt;, es decir, en la parte de la página que todavía no se ha desplazado &lt;strong&gt;(lo que se conoce como below the fold)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Este comportamiento puede &lt;strong&gt;ralentizar la carga inicial del sitio&lt;/strong&gt; y afectar negativamente la experiencia del usuario, especialmente en conexiones lentas o dispositivos móviles. Para solucionar este problema, los desarrolladores aplican una técnica llamada &lt;strong&gt;lazy loading&lt;/strong&gt; o carga diferida.&lt;/p&gt;

&lt;p&gt;El lazy loading &lt;strong&gt;retrasa la carga de ciertos recursos&lt;/strong&gt; (como imágenes o iframes) hasta que están a punto de aparecer en la pantalla del usuario. Esto reduce el tiempo de carga inicial, &lt;strong&gt;mejora el rendimiento&lt;/strong&gt; y optimiza el uso del ancho de banda.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy loading con JavaScript (enfoque tradicional)
&lt;/h2&gt;

&lt;p&gt;Antes de que existiera soporte nativo en HTML, se usaban bibliotecas como &lt;code&gt;LazyLoad&lt;/code&gt; que requerían modificar el marcado HTML. En lugar de usar el atributo &lt;code&gt;src&lt;/code&gt; en la etiqueta &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, se utilizaba un atributo &lt;code&gt;data-src&lt;/code&gt;. Luego, un script detectaba cuándo la imagen entraba en el viewport y reemplazaba dinámicamente &lt;code&gt;data-src&lt;/code&gt; por src, haciendo que la imagen se cargara justo en ese momento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Ejemplo tradicional con JavaScript --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-src=&lt;/span&gt;&lt;span class="s"&gt;"imagen.jpg"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lazyload"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Ejemplo de carga diferida"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esta técnica también era común añadir efectos visuales como desvanecimientos o transiciones suaves para mejorar la percepción visual de carga.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lazy loading nativo (Recomendado y mejor opción)
&lt;/h2&gt;

&lt;p&gt;El &lt;strong&gt;lazy loading&lt;/strong&gt; o carga diferida es una técnica que mejora significativamente el rendimiento de los sitios web al posponer la carga de imágenes y otros recursos no esenciales hasta que realmente se necesiten, es decir, cuando están a punto de entrar en el área visible del usuario.&lt;/p&gt;

&lt;p&gt;Desde HTML5, esta funcionalidad se puede aplicar de &lt;strong&gt;forma nativa mediante el atributo loading&lt;/strong&gt;, sin necesidad de escribir &lt;strong&gt;JavaScript&lt;/strong&gt; ni utilizar bibliotecas externas. Este atributo puede usarse en las etiquetas &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; y &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;, y permite a los navegadores modernos gestionar de forma automática y eficiente cuándo cargar estos elementos.&lt;/p&gt;

&lt;p&gt;Internamente, los navegadores utilizan mecanismos como &lt;code&gt;Intersection Observer&lt;/code&gt; para detectar cuándo un elemento se aproxima al &lt;code&gt;viewport&lt;/code&gt;. Sin embargo, tú como desarrollador no necesitas preocuparte por ello: basta con añadir &lt;code&gt;loading="lazy"&lt;/code&gt; a tus imágenes o iframes, y el navegador se encarga del resto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"imagen.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Descripción de la imagen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"video.html"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Valores disponibles para &lt;code&gt;loading&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;lazy&lt;/code&gt;: Carga diferida del recurso.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;eager&lt;/code&gt;: Carga inmediata del recurso.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;auto&lt;/code&gt;: El navegador decide cuándo cargarlo, según su criterio.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Si no se especifica el atributo, el valor por defecto será &lt;code&gt;auto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esta mejora nativa es &lt;strong&gt;compatible con la mayoría de los navegadores modernos&lt;/strong&gt; y representa un paso importante hacia un desarrollo web más rápido, eficiente y centrado en el usuario, además de tener un impacto positivo en el &lt;strong&gt;SEO&lt;/strong&gt; y en los &lt;strong&gt;Core Web Vitals&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo impacta el Lazy Loading en el SEO?
&lt;/h2&gt;

&lt;p&gt;Más allá de los beneficios en términos de &lt;strong&gt;rendimiento&lt;/strong&gt; y &lt;strong&gt;experiencia de usuario&lt;/strong&gt;, el lazy loading también puede tener un impacto directo en el posicionamiento &lt;strong&gt;SEO de un sitio web&lt;/strong&gt;. Por eso, si estás trabajando en una estrategia de Marketing de Contenidos, vale la pena entender cómo esta técnica puede marcar la diferencia.&lt;/p&gt;

&lt;p&gt;Ahora bien, es fundamental tener en cuenta que el uso de la carga diferida debe ser cuidadoso y &lt;strong&gt;bien planificado&lt;/strong&gt;. Una implementación incorrecta podría afectar la visibilidad del contenido ante los motores de búsqueda, especialmente si las imágenes o iframes no se cargan correctamente o si el bot de Google no puede acceder a ellos.&lt;/p&gt;

&lt;p&gt;Dicho esto, veamos los principales beneficios (y precauciones) que el lazy loading puede generar en el SEO de tu sitio web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optimización de la caché&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aprovecha contenido precargado para acelerar la carga.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;⚠️ Precaución: un uso excesivo puede provocar errores y afectar la indexación en Google.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Reducción del peso total de la página&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Disminuye el tamaño inicial de carga.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mejora el rendimiento en conexiones lentas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Favorece el posicionamiento, ya que a Google le gustan los sitios ligeros.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mejora del tiempo de permanencia&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aumenta la velocidad de carga.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reduce el abandono por frustración del usuario.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Impacta positivamente en la tasa de conversión y el tiempo promedio de visita.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Cómo implementar lazy loading nativo en imágenes e iframes?
&lt;/h2&gt;

&lt;p&gt;A continuación te muestro cómo utilizarlo correctamente, incluyendo ejemplos prácticos con imágenes simples, imágenes responsivas y elementos &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lazy loading en imágenes &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Carga diferida: la imagen se cargará cuando entre en el viewport --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"lazy-image.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Descripción de la imagen"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Carga inmediata: ideal para imágenes críticas (como banners o logotipos) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"hero-banner.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"eager"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Banner principal"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Modo automático: el navegador decide cuándo cargarla --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"auto-image.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Imagen automática"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lazy loading en &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuando usas la etiqueta , solo necesitas aplicar loading="lazy" en la etiqueta &lt;a href="" class="article-body-image-wrapper"&gt;&lt;img&gt;&lt;/a&gt; que actúa como fallback. Todos los  heredan este comportamiento.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;media=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 42em)"&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"normal.jpg 1x, retina.jpg 2x"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"optimized.jpg 1x, optimized-retina.jpg 2x"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"fallback.jpg"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Imagen optimizada"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Lazy loading con &lt;code&gt;srcset&lt;/code&gt; y &lt;code&gt;sizes&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El atributo &lt;code&gt;loading="lazy"&lt;/code&gt; también funciona correctamente en imágenes responsivas con &lt;code&gt;srcset&lt;/code&gt; y &lt;code&gt;sizes&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"imagen-s.jpg"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"imagen-l.jpg 1024w, imagen-m.jpg 640w, imagen-s.jpg 320w"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(min-width: 36em) 33.3vw, 100vw"&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"El lanzamiento más esperado"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Lazy loading en iframes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Puedes aplicar lazy loading también en iframes, tanto para contenido local como embebido desde plataformas externas &lt;strong&gt;(como YouTube)&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Iframe local --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"video-player.html"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- Iframe externo (YouTube, Vimeo, etc.) --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://www.youtube.com/embed/Hw3VqZxFnGI"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Qué soporte tiene el lazy loading nativo en los navegadores?
&lt;/h2&gt;

&lt;p&gt;Actualmente, más del 95% de los navegadores modernos soportan de forma nativa la carga diferida de imágenes e iframes mediante el atributo &lt;code&gt;loading&lt;/code&gt;. Esto significa que puedes utilizarlo con total confianza en la mayoría de los entornos de navegación, sin necesidad de bibliotecas externas ni código JavaScript adicional.&lt;/p&gt;

&lt;p&gt;Puedes ver el soporte completo a día de hoy en la siguiente tabla:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjbtoyy7b7w2k2m3bygw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjbtoyy7b7w2k2m3bygw.png" alt="Soporte loading nativo" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo saber si mi navegador soporta el lazy loading nativo?
&lt;/h2&gt;

&lt;p&gt;Puedes verificar si tu navegador es compatible con &lt;code&gt;loading="lazy"&lt;/code&gt; utilizando una simple comprobación en JavaScript. Basta con verificar si la propiedad &lt;code&gt;loading&lt;/code&gt; existe en el prototipo de los elementos &lt;code&gt;HTMLImageElement&lt;/code&gt; o &lt;code&gt;HTMLIFrameElement&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasNativeLazyLoadSupport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;HTMLImageElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hasNativeLazyLoadSupport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// El navegador no soporta lazy loading nativo.&lt;/span&gt;
  &lt;span class="c1"&gt;// Aquí podrías cargar una librería como lazysizes para aplicar una solución alternativa.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aunque ha día de hoy no creo que valga la pena validar esto ya que el soporte esta por un 95% según caniuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué ocurre si uso loading="lazy" en un navegador no compatible?
&lt;/h2&gt;

&lt;p&gt;Nada grave. Si el navegador no reconoce el atributo &lt;code&gt;loading&lt;/code&gt;, simplemente lo ignorará y cargará las imágenes o iframes como lo haría normalmente. Esto no genera errores ni afecta negativamente al comportamiento del sitio.&lt;/p&gt;

&lt;p&gt;De hecho, esta técnica se considera una mejora progresiva:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Los navegadores modernos aprovecharán los beneficios de una carga más eficiente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Los navegadores más antiguos seguirán funcionando correctamente, aunque sin la optimización de &lt;strong&gt;lazy loading&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Debería usar siempre el atributo loading="lazy"?
&lt;/h2&gt;

&lt;p&gt;No. Aunque el atributo &lt;code&gt;loading="lazy"&lt;/code&gt; es una excelente herramienta para optimizar el rendimiento de un sitio web, no debe aplicarse indiscriminadamente a todas las imágenes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;¿Por qué?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aplicar &lt;code&gt;loading="lazy"&lt;/code&gt; a imágenes que son visibles inmediatamente al cargar la página (por ejemplo, logotipos, banners principales o imágenes del above the fold) puede perjudicar la experiencia de usuario, ya que introduce una ligera demora en su visualización. &lt;/p&gt;

&lt;p&gt;Esto sucede porque el navegador, en lugar de cargarlas de inmediato, realiza cálculos adicionales (usando Intersection Observer) para determinar cuándo cargarlas, lo cual es innecesario en este caso.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recomendación&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usa &lt;code&gt;loading="lazy"&lt;/code&gt; únicamente en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Imágenes que aparecen más abajo en la página (fuera del viewport inicial).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Iframes incrustados que no forman parte del contenido principal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Elementos multimedia que se cargan bajo demanda conforme el usuario se desplaza.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Evita usarlo en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Imágenes críticas que forman parte del contenido inicial visible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Elementos visuales claves para el diseño o funcionalidad inmediata.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Cómo saber si necesitas implementar Lazy Loading?
&lt;/h2&gt;

&lt;p&gt;Si has llegado hasta este punto y aún tienes dudas sobre si tu sitio realmente necesita aplicar la estrategia de &lt;strong&gt;Lazy Loading&lt;/strong&gt;, no te preocupes. Aquí te comparto algunas señales claras que pueden ayudarte a tomar una decisión fundamentada:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔍 1. Tu sitio es lento&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Utiliza herramientas como &lt;strong&gt;Google PageSpeed Insights&lt;/strong&gt;, Lighthouse, **GTmetrix **o WebPageTest. Si los informes muestran que el tiempo de carga es elevado, especialmente por la cantidad de imágenes o iframes, el Lazy Loading puede ayudarte a reducir el peso inicial de la página y mejorar los tiempos de respuesta.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛠️ 2. Tienes problemas de optimización general&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si tu sitio presenta problemas de compresión &lt;strong&gt;(Gzip o Brotli)&lt;/strong&gt;, uso excesivo de JavaScript, CSS sin minificar o HTML pesado, estas son señales de que necesitas optimizar la carga de recursos. Aplicar carga diferida en imágenes e iframes puede ser un paso clave dentro de un enfoque integral de optimización.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔁 3. Exceso de redireccionamientos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Un número elevado de redireccionamientos en tu sitio puede aumentar el tiempo hasta la carga completa. Esto, combinado con recursos que se cargan innecesariamente desde el inicio, &lt;strong&gt;impacta negativamente en el rendimiento general&lt;/strong&gt;. Lazy Loading ayuda a aliviar esta carga inicial.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🖼️ 4. Las herramientas de análisis te recomiendan diferir imágenes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuando PageSpeed Insights o Lighthouse te muestran advertencias como "Defer offscreen images", es una señal directa de que &lt;strong&gt;implementar Lazy Loading&lt;/strong&gt; puede tener un impacto positivo. Estas sugerencias son indicadores técnicos concretos de que estás cargando contenido visual antes de que sea necesario.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;El atributo &lt;code&gt;loading="lazy"&lt;/code&gt; es una herramienta poderosa, sencilla y ampliamente soportada para &lt;strong&gt;mejorar el rendimiento web&lt;/strong&gt;. No hay razones técnicas de peso para no comenzar a utilizarlo de inmediato en todas aquellas &lt;strong&gt;imágenes&lt;/strong&gt; e &lt;strong&gt;iframes&lt;/strong&gt; que no se encuentren visibles al momento de cargar la página.&lt;/p&gt;

&lt;p&gt;✅ Si el navegador soporta Lazy Loading nativo, obtendrás mejoras significativas en la velocidad de carga y en la experiencia del usuario.&lt;/p&gt;

&lt;p&gt;❎ Si el navegador no lo soporta, el contenido se cargará normalmente, sin efectos adversos, manteniendo la retrocompatibilidad.&lt;/p&gt;

&lt;p&gt;En resumen: implementarlo es &lt;strong&gt;una mejora progresiva segura&lt;/strong&gt;, con un excelente balance entre simplicidad de aplicación y beneficios en rendimiento, SEO y usabilidad.&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi &lt;strong&gt;blog&lt;/strong&gt;, donde encontrarás más contenido sobre &lt;strong&gt;JavaScript&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt;, &lt;strong&gt;IA&lt;/strong&gt;, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>html</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Buenas prácticas para escribir commits en Git con Conventional Commits</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sat, 22 Mar 2025 20:44:50 +0000</pubDate>
      <link>https://forem.com/johnserranodev/buenas-practicas-para-escribir-commits-en-git-con-conventional-commits-44jm</link>
      <guid>https://forem.com/johnserranodev/buenas-practicas-para-escribir-commits-en-git-con-conventional-commits-44jm</guid>
      <description>&lt;p&gt;Escribir buenos mensajes de commit es fundamental para mantener un &lt;strong&gt;historial de cambios claro&lt;/strong&gt;, legible y fácil de entender. Un buen commit no solo documenta qué se cambió en el código, sino también el motivo detrás de ese cambio, lo que facilita la &lt;strong&gt;colaboración&lt;/strong&gt; y el &lt;strong&gt;mantenimiento del proyecto&lt;/strong&gt; a largo plazo.&lt;/p&gt;

&lt;p&gt;Sin embargo, es común &lt;strong&gt;encontrar problemas&lt;/strong&gt; cuando los commits se hacen sin una estructura definida. Algunos de estos problemas incluyen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mensajes ambiguos&lt;/strong&gt; o &lt;strong&gt;genéricos&lt;/strong&gt;, como &lt;em&gt;"cambios en el código"&lt;/em&gt; o &lt;em&gt;"arreglado bug"&lt;/em&gt;, que no explican qué se modificó ni por qué.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Historial difícil de leer&lt;/strong&gt;, con commits inconsistentes que dificultan rastrear la evolución del proyecto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dificultad para trabajar en equipo&lt;/strong&gt;, ya que otros desarrolladores no pueden entender rápidamente qué cambios se han hecho y cuál fue su propósito.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para solucionar estos problemas, surge &lt;strong&gt;Conventional Commits&lt;/strong&gt;, una especificación que define una estructura clara y consistente para escribir mensajes de commit. &lt;/p&gt;

&lt;p&gt;Con este estándar, cada commit sigue un &lt;strong&gt;formato predefinido&lt;/strong&gt;, lo que mejora la comprensión del historial de cambios y facilita tareas como la generación automática de versiones y changelogs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Buenas prácticas al escribir un commit en Git
&lt;/h2&gt;

&lt;p&gt;Para que un commit sea útil, debe ser &lt;strong&gt;claro&lt;/strong&gt;, &lt;strong&gt;conciso&lt;/strong&gt; y seguir un &lt;strong&gt;formato consistente&lt;/strong&gt;. A continuación, algunas buenas prácticas para escribir commits efectivos en Git:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Usa el verbo en imperativo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Los mensajes de commit deben expresarse como instrucciones, no como descripciones en pasado. En lugar de &lt;em&gt;&lt;strong&gt;"Added login validation"&lt;/strong&gt;&lt;/em&gt;, usa &lt;strong&gt;&lt;em&gt;"Add login validation"&lt;/em&gt;&lt;/strong&gt;. Esto ayuda a mantener consistencia y claridad en el historial de cambios.&lt;/p&gt;

&lt;p&gt;✅ Ejemplo correcto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Fix login validation issue"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;❌ Ejemplo incorrecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Fixed login validation issue"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. No uses punto final ni puntos suspensivos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El mensaje del commit actúa como un título, por lo que no debe llevar puntuación al final. Los &lt;strong&gt;puntos suspensivos&lt;/strong&gt; generan incertidumbre y pueden hacer que el mensaje pierda claridad.&lt;/p&gt;

&lt;p&gt;✅ Ejemplo correcto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Improve UI responsiveness"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;❌ Ejemplo incorrecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Improve UI responsiveness..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Sé breve&lt;/strong&gt;: usa un máximo de &lt;strong&gt;50 caracteres&lt;/strong&gt; en el mensaje principal&lt;/p&gt;

&lt;p&gt;Si un commit necesita más contexto, agrégalo en la descripción, pero el título debe ser corto y preciso. Un mensaje largo suele indicar que el commit agrupa demasiados cambios.&lt;/p&gt;

&lt;p&gt;✅ Ejemplo correcto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Optimize database queries"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;❌ Ejemplo incorrecto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Optimize database queries and refactor caching system to improve performance"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Agrega contexto en el cuerpo del commit si es necesario&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cuando un cambio es complejo o necesita más explicación, es mejor dividir el commit en dos partes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El título (máximo 50 caracteres, como vimos antes).&lt;/li&gt;
&lt;li&gt;El cuerpo con una descripción más detallada del cambio y su motivo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Ejemplo correcto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Refactor authentication logic"&lt;/span&gt;

Improves the security of the authentication module by replacing
deprecated methods and adding token expiration checks.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto facilita que otros desarrolladores entiendan el &lt;strong&gt;"por qué"&lt;/strong&gt; del cambio.&lt;/p&gt;

&lt;p&gt;Estas prácticas mejoran la legibilidad y organización del historial de cambios, facilitando el mantenimiento y la colaboración en el proyecto. Siguiendo estas reglas, escribir commits efectivos será mucho más fácil.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es Conventional Commits?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Conventional Commits&lt;/strong&gt; es una especificación que establece una convención clara y estructurada para escribir mensajes de commit en Git. Su objetivo es hacer que el historial del repositorio &lt;strong&gt;sea más legible&lt;/strong&gt;, tanto para los desarrolladores como para herramientas automatizadas.&lt;/p&gt;

&lt;p&gt;Esta convención define un &lt;strong&gt;conjunto de reglas que facilitan la comprensión de los cambios&lt;/strong&gt; en el código y permiten automatizar procesos como el versionado del proyecto, la generación de changelogs y la integración continua.&lt;/p&gt;

&lt;p&gt;Conventional Commits está estrechamente relacionado con &lt;strong&gt;Semantic Versioning (SemVer)&lt;/strong&gt;, un sistema que asigna versiones en función del impacto de los cambios en el código. &lt;/p&gt;

&lt;p&gt;Siguiendo esta convención, los commits pueden indicar si una modificación es una &lt;strong&gt;nueva funcionalidad&lt;/strong&gt;, una corrección de errores o un cambio que rompe la compatibilidad con versiones anteriores.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En resumen, adoptar &lt;strong&gt;Conventional Commits&lt;/strong&gt; ayuda a mejorar la colaboración en equipos de desarrollo, optimiza la trazabilidad de cambios y permite que herramientas automatizadas gestionen mejor el ciclo de vida del software.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ¿Qué es Semantic Versioning (SemVer)?
&lt;/h2&gt;

&lt;p&gt;Semantic Versioning (SemVer) es un estándar utilizado para &lt;strong&gt;asignar versiones a proyectos&lt;/strong&gt; de software de manera clara y predecible. Se basa en tres números separados por puntos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MAJOR.MINOR.PATCH

1.4.2
// 1 -&amp;gt; MAJOR
// 4 -&amp;gt; MINOR
// 2 -&amp;gt; PATCH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por ejemplo, en la versión &lt;code&gt;2.12.7&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MAJOR (2)&lt;/strong&gt;: Se incrementa cuando hay cambios que rompen la compatibilidad con versiones anteriores.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MINOR (12)&lt;/strong&gt;: Se incrementa cuando se agregan nuevas funcionalidades sin romper compatibilidad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PATCH (7)&lt;/strong&gt;: Se incrementa cuando se corrigen errores sin afectar funcionalidades existentes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;También es común agregar etiquetas como alpha, beta, rc o next para indicar versiones en desarrollo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo&lt;/strong&gt;:&lt;br&gt;
Si una librería pasa de &lt;code&gt;1.4.2&lt;/code&gt; a &lt;code&gt;2.0.0&lt;/code&gt;, significa que ha habido un cambio importante que rompe compatibilidad.&lt;/p&gt;
&lt;h2&gt;
  
  
  Estructura de un commit con Conventional Commits
&lt;/h2&gt;

&lt;p&gt;Conventional Commits es un estándar que define cómo escribir mensajes de commit de forma estructurada. Su formato es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;tipo&amp;gt;(&amp;lt;scope opcional&amp;gt;): &amp;lt;descripción&amp;gt;

[cuerpo opcional]

[footer opcional]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tipos de commit más comunes:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;feat&lt;/strong&gt;: Se ha agregado una nueva funcionalidad (correlaciona con MINOR en SemVer).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;fix&lt;/strong&gt;: Se ha corregido un error (correlaciona con PATCH en SemVer).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BREAKING CHANGE&lt;/strong&gt;: Indica un cambio que rompe compatibilidad (correlaciona con MAJOR en SemVer).&lt;/p&gt;

&lt;p&gt;Otros tipos incluyen:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docs&lt;/strong&gt;: Cambios en la documentación.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;style&lt;/strong&gt;: Cambios de formato o legibilidad sin afectar el código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;refactor&lt;/strong&gt;: Modificaciones sin cambios en la funcionalidad.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;test&lt;/strong&gt;: Agrega o corrige pruebas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;chore&lt;/strong&gt;: Tareas de mantenimiento sin cambios en la funcionalidad.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;build&lt;/strong&gt;: Cambios en la configuración de compilación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scope en Conventional Commits
&lt;/h2&gt;

&lt;p&gt;El scope es un campo opcional dentro del mensaje de commit que permite &lt;strong&gt;indicar el área específica del proyecto&lt;/strong&gt; donde se realizaron los cambios. Su propósito es dar mayor claridad sobre el alcance de la modificación.&lt;/p&gt;

&lt;p&gt;Este es especialmente útil en &lt;strong&gt;monorepositorios&lt;/strong&gt; o en proyectos con múltiples módulos, ya que facilita la identificación rápida de qué parte del código se ha visto afectada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(backend): Add filter payments
fix(web): Fix space between element nav
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Descripción, cuerpo y nota al pie en Conventional Commits
&lt;/h2&gt;

&lt;p&gt;La descripción debe ser breve, en imperativo y en tiempo presente, &lt;strong&gt;sin mayúscula inicial&lt;/strong&gt; ni punto final.&lt;/p&gt;

&lt;p&gt;El cuerpo es opcional y se usa para &lt;strong&gt;agregar detalles adicionales&lt;/strong&gt; sobre el cambio. Debe seguir el mismo tono imperativo.&lt;/p&gt;

&lt;p&gt;La nota al pie también es opcional y se usa principalmente para indicar &lt;strong&gt;Breaking Changes&lt;/strong&gt;, aunque puede incluir otra información relevante.&lt;/p&gt;

&lt;p&gt;Ejemplos en un monorepositorio multipaquete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api): add endpoint to get statistics
fix(ui): fix margin in navigation button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si bien lo mínimo recomendable es diferenciar entre &lt;strong&gt;fix&lt;/strong&gt; y &lt;strong&gt;feat&lt;/strong&gt;, seguir convenciones como las de Angular ayuda a estandarizar los commits y mejorar la colaboración dentro de los equipos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplo de commits con Conventional Commits:
&lt;/h2&gt;

&lt;p&gt;Agregar una nueva funcionalidad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(auth): Add auth with JWT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Corregir un error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(login): Fix error valid user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cambio que rompe compatibilidad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api)!: change the response payload structure

BREAKING CHANGE: The API now returns a JSON object with a new format.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ruptura de compatibilidad con &lt;code&gt;!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Commit con cuerpo y notas al pie:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(api): correct minor typos in code

see the issue for details

on typos fixed.

Reviewed-by: John Serrano
Fixes #215
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Por qué usar Conventional Commits?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Establece un estándar en el formato de los commits para todo el equipo, facilitando la colaboración.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mantiene un historial del repositorio claro y estructurado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Permite la generación automática del CHANGELOG.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Facilita el versionado automático del proyecto según SemVer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mejora la comunicación de los cambios dentro del equipo y con colaboradores externos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatiza procesos de build, despliegue y publicación.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Facilita la contribución de nuevos desarrolladores al proporcionar un historial de commits organizado.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Herramientas para utilizar Conventional Commits
&lt;/h2&gt;

&lt;p&gt;Existen diversas herramientas que facilitan la adopción de Conventional Commits en los proyectos, desde linters hasta automatización del versionado. A continuación, te presento algunas de las más útiles y populares:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Commitlint + Husky&lt;/strong&gt;&lt;br&gt;
Commitlint permite validar los mensajes de commit asegurando que sigan una convención establecida.&lt;/p&gt;

&lt;p&gt;Husky ejecuta scripts antes de realizar ciertas acciones en el repositorio, como &lt;strong&gt;verificar el formato del commit&lt;/strong&gt; o ejecutar pruebas antes de un push.&lt;/p&gt;

&lt;p&gt;Instalación y configuración básica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; husky @commitlint/&lt;span class="o"&gt;{&lt;/span&gt;config-conventional,cli&lt;span class="o"&gt;}&lt;/span&gt;
npx husky &lt;span class="nb"&gt;install
&lt;/span&gt;npm set-script prepare &lt;span class="s2"&gt;"husky install"&lt;/span&gt;
npm run prepare
npx husky add .husky/commit-msg &lt;span class="s1"&gt;'npx --no-install commitlint --edit "$1"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Puedes leer más detalles en &lt;a href="https://johnserrano.co/blog/husky-y-lint-staged-como-configurar-y-automatizar-pre-commit-hooks" rel="noopener noreferrer"&gt;mi artículo sobre Husky&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Ver todos los detalles en mi Blog 🔥
&lt;/h2&gt;

&lt;p&gt;Si quieres aprender más sobre &lt;strong&gt;Conventional Commits&lt;/strong&gt;, puedes leer el artículo completo aquí 👉 &lt;strong&gt;&lt;a href="https://johnserrano.co/blog/buenas-practicas-para-escribir-commits-en-git-con-conventional-commits" rel="noopener noreferrer"&gt;Buenas prácticas para escribir commits en Git con Conventional Commits&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;Adoptar Conventional Commits mejora la claridad y consistencia del &lt;strong&gt;historial del repositorio&lt;/strong&gt;, facilita la &lt;strong&gt;automatización del versionado&lt;/strong&gt; y la generación de &lt;strong&gt;changelogs&lt;/strong&gt;, y optimiza la colaboración en equipos de desarrollo. &lt;/p&gt;

&lt;p&gt;Con herramientas como &lt;strong&gt;Commitlint&lt;/strong&gt;, &lt;strong&gt;Husky&lt;/strong&gt;, Semantic Release y Conventional Changelog, es posible integrar esta convención de manera eficiente en cualquier proyecto. &lt;/p&gt;

&lt;p&gt;Implementarlas no solo mejora la documentación del código, sino que también agiliza los procesos de despliegue y mantenimiento. &lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>git</category>
      <category>beginners</category>
    </item>
    <item>
      <title>CSS FlexBox: Diseño avanzado desde cero</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sun, 09 Mar 2025 21:11:59 +0000</pubDate>
      <link>https://forem.com/johnserranodev/css-flexbox-diseno-avanzado-desde-cero-5ckm</link>
      <guid>https://forem.com/johnserranodev/css-flexbox-diseno-avanzado-desde-cero-5ckm</guid>
      <description>&lt;p&gt;En el diseño web moderno, la necesidad de crear &lt;strong&gt;interfaces flexibles&lt;/strong&gt; y adaptables a &lt;strong&gt;distintos dispositivos&lt;/strong&gt; es fundamental. &lt;strong&gt;CSS Flexbox (Flexible Box)&lt;/strong&gt; es un módulo diseñado para proporcionar una manera eficiente de distribuir espacio y &lt;strong&gt;alinear elementos&lt;/strong&gt; dentro de un contenedor, incluso cuando sus dimensiones son dinámicas o desconocidas.&lt;/p&gt;

&lt;p&gt;A diferencia de los modelos de &lt;strong&gt;diseño tradicionales&lt;/strong&gt; como el modelo de caja en &lt;strong&gt;bloque (block)&lt;/strong&gt; o en línea (inline), &lt;strong&gt;Flexbox&lt;/strong&gt; permite modificar el tamaño, orden y alineación de los elementos de manera flexible, adaptándose a diferentes pantallas y orientaciones. &lt;/p&gt;

&lt;p&gt;Su principal ventaja es que no está restringido a una &lt;strong&gt;sola dirección&lt;/strong&gt;, lo que lo hace ideal para diseños complejos y aplicaciones con necesidades dinámicas.&lt;/p&gt;

&lt;p&gt;Aunque &lt;strong&gt;Flexbox&lt;/strong&gt; es una herramienta poderosa para diseños a pequeña escala, como la distribución de elementos dentro de un componente, es &lt;strong&gt;importante mencionar&lt;/strong&gt; que para diseños de mayor escala, &lt;a href="https://johnserrano.co/blog/css-grid-la-guia-completa-para-principiantes-y-avanzados" rel="noopener noreferrer"&gt;CSS Grid&lt;/a&gt; suele ser una mejor opción.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Quieres dominar CSS Grid y mejorar tus diseños?
&lt;/h2&gt;

&lt;p&gt;Si aún te cuesta organizar elementos en CSS, &lt;strong&gt;Grid&lt;/strong&gt; es la clave para crear estructuras flexibles y ordenadas sin complicaciones. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://johnserrano.co/blog/css-grid-la-guia-completa-para-principiantes-y-avanzados" rel="noopener noreferrer"&gt;CSS Grid: La guía completa para principiantes y avanzados&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es Flexbox?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Flexbox&lt;/strong&gt; es un módulo de diseño en CSS que &lt;strong&gt;permite distribuir&lt;/strong&gt; el espacio entre los elementos de un contenedor de manera eficiente, permitiendo que estos se expandan o contraigan según sea necesario. &lt;/p&gt;

&lt;p&gt;Su funcionamiento se basa en la definición de un &lt;strong&gt;"contenedor flexible"&lt;/strong&gt; que administra la colocación y el tamaño de los elementos hijos.&lt;/p&gt;

&lt;p&gt;El modelo de Flexbox &lt;strong&gt;facilita tareas comunes&lt;/strong&gt; en diseño web, como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Centrando elementos vertical y horizontalmente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creando diseños responsivos sin necesidad de utilizar float o position.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ajustando el orden de los elementos sin modificar el código HTML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Distribuyendo espacio de manera equitativa o priorizando ciertos elementos dentro de un contenedor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este módulo introduce &lt;strong&gt;conceptos clave&lt;/strong&gt; como el eje principal y el eje transversal, que definen la &lt;strong&gt;dirección&lt;/strong&gt; en la que los elementos se distribuyen dentro del contenedor, permitiendo una &lt;strong&gt;mayor flexibilidad&lt;/strong&gt; en el diseño.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xMdTBbXwAzY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conceptos básicos y terminología
&lt;/h2&gt;

&lt;p&gt;Flexbox no es solo una propiedad, sino un módulo completo con múltiples &lt;strong&gt;características&lt;/strong&gt; y &lt;strong&gt;propiedades&lt;/strong&gt;. Algunas de estas propiedades se aplican al &lt;strong&gt;contenedor principal&lt;/strong&gt; (llamado "contenedor flexible"), mientras que otras afectan a los &lt;strong&gt;elementos hijos&lt;/strong&gt; (llamados "elementos flexibles").&lt;/p&gt;

&lt;p&gt;A diferencia de los &lt;strong&gt;diseños tradicionales&lt;/strong&gt; basados en los flujos de bloque y en línea, &lt;strong&gt;Flexbox introduce&lt;/strong&gt; un sistema basado en "direcciones de flujo flexible" &lt;strong&gt;(flex-flow directions)&lt;/strong&gt;, lo que permite una disposición más versátil de los elementos dentro del contenedor. &lt;/p&gt;

&lt;p&gt;Para comprender cómo funciona, es clave conocer los siguientes conceptos:&lt;/p&gt;

&lt;h3&gt;
  
  
  Eje principal y eje transversal
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eje principal (main axis)&lt;/strong&gt;: Es la dirección en la que los elementos flexibles se distribuyen dentro del contenedor. Su orientación depende de la propiedad &lt;code&gt;flex-direction&lt;/code&gt;, por lo que puede ser horizontal o vertical.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inicio y fin del eje principal (main-start | main-end)&lt;/strong&gt;: Los elementos se posicionan en el contenedor comenzando desde el &lt;code&gt;main-start&lt;/code&gt; y extendiéndose hacia &lt;code&gt;main-end&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tamaño principal (main size)&lt;/strong&gt;: Hace referencia al ancho o alto de un elemento, dependiendo de la orientación del eje principal. Este tamaño es determinado por las propiedades &lt;code&gt;width&lt;/code&gt; o &lt;code&gt;height&lt;/code&gt; según corresponda.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Eje transversal
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Eje transversal (cross axis)&lt;/strong&gt;: Es el eje perpendicular al eje principal y su dirección se define según la orientación del eje principal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inicio y fin del eje transversal (cross-start | cross-end)&lt;/strong&gt;: Los elementos se organizan en líneas dentro del contenedor comenzando en cross-start y extendiéndose hacia cross-end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tamaño transversal (cross size)&lt;/strong&gt;: Hace referencia al ancho o alto de un elemento en la dimensión transversal. Se determina por las propiedades &lt;code&gt;width&lt;/code&gt; o &lt;code&gt;height&lt;/code&gt; según la orientación del eje.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para ilustrar mejor estos conceptos, aquí tienes una imagen explicativa:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55bh6njbem94ttsnfwzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55bh6njbem94ttsnfwzp.png" alt="Conceptos básicos y terminología FlexBox" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Imagen tomada de css-tricks.com.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Comprender estos conceptos es clave para &lt;strong&gt;dominar Flexbox&lt;/strong&gt;, ya que permiten una mejor organización y control del diseño adaptable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Propiedades del contenedor Flexible (Flex Container)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnvajika0jadysh74k0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnvajika0jadysh74k0g.png" alt="Flex container" width="566" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagen tomada de css-tricks.com&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En Flexbox, el contenedor flexible es &lt;strong&gt;el elemento padre&lt;/strong&gt; que define el contexto en el que los &lt;strong&gt;elementos hijos&lt;/strong&gt; se distribuyen y alinean. &lt;/p&gt;

&lt;p&gt;A continuación, te explico las principales propiedades aplicables al contenedor:&lt;/p&gt;

&lt;h3&gt;
  
  
  display
&lt;/h3&gt;

&lt;p&gt;Define un contenedor flexible, permitiendo que todos sus elementos directos se conviertan en elementos flexibles. Puede adoptar los valores:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Contenedor de bloque flexible */&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Contenedor de línea flexible */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es importante destacar que las columnas de CSS (column-count, column-width) no afectan a un contenedor flexible.&lt;/p&gt;

&lt;h3&gt;
  
  
  flex-direction
&lt;/h3&gt;

&lt;p&gt;Establece el eje principal y la dirección en la que se organizan los elementos flexibles dentro del &lt;strong&gt;contenedor&lt;/strong&gt;. Flexbox es un modelo de diseño unidireccional, por lo que los elementos pueden distribuirse en &lt;strong&gt;filas&lt;/strong&gt; o &lt;strong&gt;columnas&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;row-reverse&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;column-reverse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los valores posibles son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;row (por defecto)&lt;/strong&gt;: Organiza los elementos de izquierda a derecha en idiomas con escritura de izquierda a derecha (ltr) y de derecha a izquierda en idiomas con escritura de derecha a izquierda (rtl).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;row-reverse&lt;/strong&gt;: Invierte la dirección de row.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;column&lt;/strong&gt;: Organiza los elementos en una columna de arriba hacia abajo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;column-reverse&lt;/strong&gt;: Invierte la dirección de column, de abajo hacia arriba.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://codepen.io/johnserranodev/pen/JojyJOg" rel="noopener noreferrer"&gt;https://codepen.io/johnserranodev/pen/JojyJOg&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  flex-wrap
&lt;/h3&gt;

&lt;p&gt;Determina si los elementos flexibles deben ajustarse dentro del contenedor o si pueden desbordarse a una nueva línea.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;wrap-reverse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;nowrap (por defecto)&lt;/strong&gt;: Todos los elementos se mantienen en una sola línea.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;wrap&lt;/strong&gt;: Los elementos se ajustan a múltiples líneas si es necesario.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;wrap-reverse&lt;/strong&gt;: Similar a wrap, pero invierte el orden de las líneas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://codepen.io/johnserranodev/pen/XJWaaYd" rel="noopener noreferrer"&gt;https://codepen.io/johnserranodev/pen/XJWaaYd&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  flex-flow
&lt;/h3&gt;

&lt;p&gt;Es una propiedad abreviada para flex-direction y flex-wrap, que define el eje principal y el ajuste de los elementos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  justify-content
&lt;/h3&gt;

&lt;p&gt;Controla la alineación de los elementos a lo largo del eje principal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;flex-end&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;space-between&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;space-around&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;space-evenly&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;flex-start (por defecto)&lt;/strong&gt;: Alinea los elementos al inicio del contenedor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;flex-end&lt;/strong&gt;: Alinea los elementos al final del contenedor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;center&lt;/strong&gt;: Centra los elementos dentro del contenedor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;space-between&lt;/strong&gt;: Distribuye los elementos con espacio igual entre ellos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;space-around&lt;/strong&gt;: Agrega espacio antes y después de cada elemento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;space-evenly&lt;/strong&gt;: Distribuye el espacio de manera uniforme entre los elementos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://codepen.io/johnserranodev/pen/xbxLLaq?editors=1100" rel="noopener noreferrer"&gt;https://codepen.io/johnserranodev/pen/xbxLLaq?editors=1100&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  align-items
&lt;/h3&gt;

&lt;p&gt;Define cómo se alinean los elementos en el eje transversal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;flex-end&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;baseline&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stretch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;flex-start&lt;/strong&gt;: Alinea los elementos al inicio del eje transversal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;flex-end&lt;/strong&gt;: Alinea los elementos al final del eje transversal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;center&lt;/strong&gt;: Centra los elementos en el eje transversal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;baseline&lt;/strong&gt;: Alinea los elementos según su línea base de texto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;stretch (por defecto)&lt;/strong&gt;: Hace que los elementos ocupen todo el espacio disponible en el eje transversal.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://codepen.io/johnserranodev/pen/WbNEEYq?editors=1100" rel="noopener noreferrer"&gt;https://codepen.io/johnserranodev/pen/WbNEEYq?editors=1100&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  gap, row-gap, column-gap
&lt;/h3&gt;

&lt;p&gt;Define el espacio entre los elementos flexibles dentro del contenedor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* row-gap column gap */&lt;/span&gt;
  &lt;span class="py"&gt;row-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;column-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Funciona como un margen mínimo entre elementos, sin afectar los bordes externos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://codepen.io/johnserranodev/pen/bNGrrZy?editors=1100" rel="noopener noreferrer"&gt;https://codepen.io/johnserranodev/pen/bNGrrZy?editors=1100&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Te invito a leer este otro artículo donde te enseño las últimas novedades de Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://johnserrano.co/blog/tailwind-css-4-novedades-y-configuracion" rel="noopener noreferrer"&gt;Tailwind CSS 4: Todas las novedades y cómo configurarlo paso a paso&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Propiedades de los elementos Flexibles (Flex Items)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5jp13le8sw1v70xo9ly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5jp13le8sw1v70xo9ly.png" alt="Flex items" width="566" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagen tomada de css-tricks.com&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  order
&lt;/h3&gt;

&lt;p&gt;De forma predeterminada, los elementos flexibles se disponen en el orden de origen. Sin embargo, la propiedad de &lt;code&gt;order&lt;/code&gt; controla el orden en el que aparecen en el contenedor flexible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* valor por defecto es 0 */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  flex-grow
&lt;/h3&gt;

&lt;p&gt;Esta propiedad define la capacidad de un elemento flexible para &lt;strong&gt;expandirse dentro del contenedor&lt;/strong&gt; cuando hay espacio disponible. Se expresa con un valor numérico sin unidad, que funciona como un factor de proporción.&lt;/p&gt;

&lt;p&gt;El valor indica qué parte del espacio libre debe ocupar el elemento en relación con los demás. Si todos los elementos tienen &lt;code&gt;flex-grow: 1;&lt;/code&gt;, el espacio sobrante se distribuirá de manera equitativa entre ellos. Sin embargo, si un elemento tiene &lt;code&gt;flex-grow: 2;&lt;/code&gt;, intentará ocupar el doble de espacio en comparación con los demás.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex-grow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Valor por defecto: 0 */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es importante destacar que los valores negativos no son válidos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ejemplo, order y flex-grow&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://codepen.io/johnserranodev/pen/VYwzzNX?editors=1100" rel="noopener noreferrer"&gt;https://codepen.io/johnserranodev/pen/VYwzzNX?editors=1100&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  flex-shrink
&lt;/h3&gt;

&lt;p&gt;Esta propiedad determina la capacidad de un elemento flexible para &lt;strong&gt;reducir su tamaño&lt;/strong&gt; si es necesario. Funciona con un valor numérico sin unidad que indica la proporción en la que el elemento puede encogerse en comparación con los demás.&lt;/p&gt;

&lt;p&gt;Si todos los elementos tienen &lt;code&gt;flex-shrink: 1;&lt;/code&gt;, se reducirán de manera uniforme cuando el espacio sea insuficiente. Si un elemento tiene un valor mayor, se encogerá más rápido que los demás.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex-shrink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Valor por defecto: 1 */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es importante destacar que los valores negativos no son válidos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ver todos los detalles y ejemplos 🔥
&lt;/h2&gt;

&lt;p&gt;Si quieres aprender más sobre &lt;strong&gt;CSS Grid con ejemplos prácticos&lt;/strong&gt;, puedes leer el artículo completo aquí 👉 &lt;strong&gt;&lt;a href="https://johnserrano.co/blog/css-flexbox-diseno-avanzado-desde-cero" rel="noopener noreferrer"&gt;CSS FlexBox: Diseño avanzado desde cero&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Puedes ver todos los ejemplos completos acá:&lt;br&gt;
&lt;a href="https://codepen.io/collection/kkkdGZ" rel="noopener noreferrer"&gt;https://codepen.io/collection/kkkdGZ&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;Flexbox es una herramienta poderosa y esencial en el &lt;strong&gt;diseño web moderno&lt;/strong&gt;, ya que permite distribuir y alinear elementos de manera eficiente dentro de un &lt;strong&gt;contenedor flexible&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Su versatilidad lo convierte en una excelente opción para crear &lt;strong&gt;interfaces responsivas&lt;/strong&gt; sin necesidad de recurrir a técnicas más complejas como float o position.&lt;/p&gt;

&lt;p&gt;Algunos puntos clave que podemos destacar sobre Flexbox son:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control total sobre el diseño&lt;/strong&gt;: Permite organizar los elementos en una dirección específica (horizontal o vertical), definir el tamaño de cada uno y ajustar su alineación con facilidad.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distribución eficiente del espacio&lt;/strong&gt;: Gracias a propiedades como justify-content, align-items y gap, es posible lograr diseños equilibrados y bien estructurados sin necesidad de hacks o márgenes negativos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Orden dinámico de los elementos&lt;/strong&gt;: Con la propiedad order, podemos cambiar la posición visual de los elementos sin modificar el HTML, lo que facilita la flexibilidad en la disposición de los componentes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adaptabilidad y responsividad&lt;/strong&gt;: Al permitir que los elementos crezcan (flex-grow), se encojan (flex-shrink) o tengan un tamaño base (flex-basis), Flexbox ayuda a crear interfaces que se ajustan a distintos tamaños de pantalla de forma fluida.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Combinación con otras herramientas&lt;/strong&gt;: Aunque Flexbox es ideal para la disposición de elementos en una dimensión (fila o columna), en diseños más complejos puede complementarse con CSS Grid para obtener un control total sobre la disposición del contenido.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;En conclusión, Flexbox es una técnica fundamental para cualquier desarrollador web, ya que simplifica la creación de diseños flexibles, adaptables y modernos con menos código y mayor eficiencia.&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi &lt;strong&gt;blog&lt;/strong&gt;, donde encontrarás más contenido sobre &lt;strong&gt;JavaScript&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt;, &lt;strong&gt;IA&lt;/strong&gt;, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>css</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>CSS Grid: La guía completa para principiantes y avanzados</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sat, 01 Mar 2025 14:51:34 +0000</pubDate>
      <link>https://forem.com/johnserranodev/css-grid-la-guia-completa-para-principiantes-y-avanzados-51f8</link>
      <guid>https://forem.com/johnserranodev/css-grid-la-guia-completa-para-principiantes-y-avanzados-51f8</guid>
      <description>&lt;p&gt;CSS Grid Layout &lt;strong&gt;(o simplemente CSS Grid)&lt;/strong&gt; es un sistema de diseño bidimensional que ha cambiado por completo la forma en que creamos interfaces web. &lt;/p&gt;

&lt;p&gt;Durante años, CSS nos ha permitido maquetar páginas, pero siempre con soluciones improvisadas: primero con tablas, luego con flotados (floats), posicionamiento y inline-block. Ninguno de estos métodos fue diseñado específicamente para la maquetación y, por eso, tenían muchas limitaciones &lt;strong&gt;(como la falta de alineación vertical)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexbox&lt;/strong&gt; es un gran avance en diseño web, pero su enfoque unidimensional hace que no siempre sea la mejor opción. Aquí es donde &lt;strong&gt;CSS Grid brilla&lt;/strong&gt;: es el primer módulo creado con el propósito exclusivo de resolver los problemas de diseño web, permitiéndonos estructurar nuestras interfaces de manera más intuitiva y eficiente.&lt;/p&gt;

&lt;p&gt;En esta guía, exploraremos los conceptos &lt;strong&gt;clave de Grid&lt;/strong&gt; según la versión más reciente de la especificación. No abordaremos la sintaxis obsoleta de Internet Explorer, aunque Grid sigue siendo compatible con IE 11.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conceptos básicos de CSS Grid
&lt;/h2&gt;

&lt;p&gt;Desde marzo de 2017, la mayoría de los navegadores incorporaron soporte nativo y &lt;strong&gt;sin prefijos para CSS Grid&lt;/strong&gt;, incluyendo &lt;strong&gt;Chrome&lt;/strong&gt;, &lt;strong&gt;Firefox&lt;/strong&gt;, &lt;strong&gt;Safari&lt;/strong&gt; (también en iOS) y &lt;strong&gt;Opera&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Por otro lado, Internet Explorer 10 y 11 lo admiten, pero con una implementación antigua y una sintaxis obsoleta. ¡El momento de empezar a usar Grid es ahora!&lt;/p&gt;

&lt;p&gt;Para comenzar, lo primero es definir un contenedor como una cuadrícula con &lt;code&gt;display: grid&lt;/code&gt;. Luego, se establecen las dimensiones de las filas y columnas con &lt;code&gt;grid-template-columns&lt;/code&gt; y &lt;code&gt;grid-template-rows&lt;/code&gt;. Finalmente, se ubican los elementos hijos dentro de la cuadrícula con &lt;code&gt;grid-column&lt;/code&gt; y &lt;code&gt;grid-row&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Al igual que &lt;strong&gt;Flexbox&lt;/strong&gt;, el orden en el código fuente no afecta la posición de los elementos en la cuadrícula. &lt;/p&gt;

&lt;p&gt;Esto significa que puedes reordenar tu diseño fácilmente con &lt;strong&gt;media queries&lt;/strong&gt;, adaptándolo a distintos tamaños de pantalla con solo unas pocas líneas de CSS. &lt;/p&gt;

&lt;p&gt;Imagina definir toda la estructura de una página y luego reorganizarla completamente para dispositivos móviles sin modificar el HTML.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS Grid es uno de los módulos más potentes&lt;/strong&gt; que se han incorporado a CSS, brindando flexibilidad y control total sobre el diseño de nuestras interfaces.&lt;/p&gt;

&lt;p&gt;Te dejo una gráfica para que sea más visual:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftds9aq7ur8wf1ew4zhut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftds9aq7ur8wf1ew4zhut.png" alt="Conceptos css grid" width="800" height="547"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Imagen tomada de platzi.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Términos clave en CSS Grid
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Contenedor&lt;/strong&gt;: El elemento padre que define la cuadrícula.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ítem&lt;/strong&gt;: Cada elemento hijo dentro de la cuadrícula.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Línea (grid line)&lt;/strong&gt;: Las líneas horizontales y verticales que separan las celdas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Celda (grid cell)&lt;/strong&gt;: La unidad mínima de la cuadrícula, equivalente a un solo "cuadro".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Banda (grid track)&lt;/strong&gt;: Una fila o columna completa dentro de la cuadrícula.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Área (grid area)&lt;/strong&gt;: Un conjunto de celdas que forman una región dentro de la cuadrícula.&lt;/p&gt;
&lt;h2&gt;
  
  
  Grid Container
&lt;/h2&gt;

&lt;p&gt;Es el elemento al que se le aplica &lt;code&gt;display: grid;&lt;/code&gt; y actúa como el contenedor principal de todos los elementos de la cuadrícula. En este ejemplo, el contenedor es el grid container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"contenedor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item item-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item item-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item item-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Grid Item
&lt;/h2&gt;

&lt;p&gt;Son los elementos hijos directos del contenedor de la cuadrícula. En este ejemplo, los elementos item son &lt;code&gt;grid items&lt;/code&gt;, pero sub-item no lo es.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"contenedor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"sub-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Grid Line
&lt;/h2&gt;

&lt;p&gt;Son las líneas divisorias que conforman la estructura de la cuadrícula. Pueden ser &lt;strong&gt;verticales (líneas de columna)&lt;/strong&gt; o &lt;strong&gt;horizontales (líneas de fila)&lt;/strong&gt; y se encuentran a ambos lados de una fila o columna. En este ejemplo, la línea amarilla representa una línea de columna.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fic2bqqdp4mlrpjz8ss9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fic2bqqdp4mlrpjz8ss9n.png" alt="Grid línea" width="641" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Grid Cell
&lt;/h2&gt;

&lt;p&gt;Es el espacio comprendido entre dos líneas de fila y dos líneas de columna adyacentes. Representa la unidad más pequeña dentro de la cuadrícula. En este ejemplo, la &lt;code&gt;grid cell&lt;/code&gt; está ubicada entre las líneas de fila 1 y 2 y las líneas de columna 2 y 3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk48xsgs0hl2iz3s0ofw5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk48xsgs0hl2iz3s0ofw5.png" alt="Grid celda" width="635" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Grid Track
&lt;/h2&gt;

&lt;p&gt;Es el espacio comprendido entre dos líneas de la cuadrícula adyacentes. Puede representar una fila o una columna dentro de la cuadrícula. En este ejemplo, el &lt;code&gt;grid track&lt;/code&gt; se encuentra entre la segunda y tercera línea de fila.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ek04bu3o7rc41jilezc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ek04bu3o7rc41jilezc.png" alt="Grid track" width="645" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Grid Area
&lt;/h2&gt;

&lt;p&gt;Es el espacio total delimitado por cuatro líneas de la cuadrícula. Puede estar compuesto por una o varias &lt;code&gt;grid cells&lt;/code&gt;. En este ejemplo, el grid area se encuentra entre las líneas de fila 1 y 3 y las líneas de columna 1 y 3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3670g4zqpozbo9lvq49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3670g4zqpozbo9lvq49.png" alt="Grid area" width="643" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Propiedades de CSS Grid
&lt;/h2&gt;

&lt;p&gt;CSS Grid se compone de una serie de propiedades que se aplican tanto al contenedor de la cuadrícula &lt;strong&gt;(grid container)&lt;/strong&gt; como a los elementos de la cuadrícula &lt;strong&gt;(grid items)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Propiedades del Grid Container&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Estas propiedades se aplican al elemento padre que define la cuadrícula:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;display: grid / display: inline-grid&lt;/code&gt;&lt;br&gt;
Define el contenedor como una cuadrícula.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-template-columns&lt;/code&gt;&lt;br&gt;
Especifica el tamaño y número de columnas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-template-rows&lt;/code&gt;&lt;br&gt;
Define el tamaño y número de filas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-template-areas&lt;/code&gt;&lt;br&gt;
Permite nombrar áreas dentro de la cuadrícula.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-column-gap / column-gap&lt;/code&gt;&lt;br&gt;
Espacio entre columnas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-row-gap / row-gap&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Espacio entre filas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-gap / gap&lt;/code&gt;&lt;br&gt;
Espacio entre filas y columnas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;justify-items&lt;/code&gt;&lt;br&gt;
Alinea los elementos dentro de sus celdas en el eje horizontal.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;align-items&lt;/code&gt;&lt;br&gt;
Alinea los elementos dentro de sus celdas en el eje vertical.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;place-items&lt;/code&gt;&lt;br&gt;
Combinación de align-items y justify-items.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;justify-content&lt;/code&gt;&lt;br&gt;
Alinea la cuadrícula dentro del contenedor en el eje horizontal.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;align-content&lt;/code&gt;&lt;br&gt;
Alinea la cuadrícula dentro del contenedor en el eje vertical.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;place-content&lt;/code&gt;&lt;br&gt;
Combinación de align-content y justify-content.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-auto-columns&lt;/code&gt;&lt;br&gt;
Define el tamaño de las columnas generadas automáticamente.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-auto-rows&lt;/code&gt;&lt;br&gt;
Define el tamaño de las filas generadas automáticamente.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-auto-flow&lt;/code&gt;&lt;br&gt;
Controla cómo se colocan los elementos automáticamente en la cuadrícula.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Propiedades del Grid Item&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Estas propiedades se aplican a los elementos hijos dentro de la cuadrícula:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-column-start&lt;/code&gt;&lt;br&gt;
Define en qué línea de columna comienza el elemento.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-column-end&lt;/code&gt;&lt;br&gt;
Define en qué línea de columna termina el elemento.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-column&lt;/code&gt;&lt;br&gt;
Atajo para grid-column-start y grid-column-end.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-row-start&lt;/code&gt;&lt;br&gt;
Define en qué línea de fila comienza el elemento.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-row-end&lt;/code&gt;&lt;br&gt;
Define en qué línea de fila termina el elemento.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-row&lt;/code&gt;&lt;br&gt;
Atajo para grid-row-start y grid-row-end.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;grid-area&lt;/code&gt;&lt;br&gt;
Asigna un elemento a un área de la cuadrícula nombrada con grid-template-areas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;justify-self&lt;/code&gt;&lt;br&gt;
Alinea un elemento dentro de su celda en el eje horizontal.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;align-self&lt;/code&gt;&lt;br&gt;
Alinea un elemento dentro de su celda en el eje vertical.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;place-self&lt;/code&gt;&lt;br&gt;
Combinación de align-self y justify-self.&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Quieres ir un paso más allá?
&lt;/h2&gt;

&lt;p&gt;Si estás interesado en potenciar tu carrera como &lt;strong&gt;desarrollador frontend&lt;/strong&gt; o desarrollador Web, te recomiendo leer este artículo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://johnserrano.co/blog/como-iniciar-y-crecer-como-desarrollador-frontend-en-2025" rel="noopener noreferrer"&gt;Cómo iniciar y crecer como desarrollador frontend en 2025&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En él encontrarás &lt;strong&gt;consejos prácticos&lt;/strong&gt;, &lt;strong&gt;recursos&lt;/strong&gt; y estrategias para comenzar y avanzar en el mundo del desarrollo frontend.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ejemplos prácticos
&lt;/h2&gt;

&lt;p&gt;Crear una cuadrícula de 3 columnas y 2 filas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con la propiedad &lt;code&gt;display: grid&lt;/code&gt;, indicamos que el elemento será un contenedor de cuadrícula. Luego, con &lt;code&gt;grid-template-columns&lt;/code&gt; y &lt;code&gt;grid-template-rows&lt;/code&gt;, establecemos el tamaño y la cantidad de columnas y filas que compondrán la cuadrícula.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0u27byo9191174vh0z9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0u27byo9191174vh0z9.png" alt="Crear columnas y filas" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Es importante asegurarnos de que el número de elementos hijos dentro del grid sea el adecuado para &lt;strong&gt;la estructura que definimos&lt;/strong&gt;. La cantidad de filas y columnas que configuremos con &lt;code&gt;grid-template-columns&lt;/code&gt; y &lt;code&gt;grid-template-rows&lt;/code&gt; determinará cómo se distribuyen los elementos.&lt;/p&gt;

&lt;p&gt;Por ejemplo, si definimos una &lt;strong&gt;cuadrícula de 2x2&lt;/strong&gt;, tendremos espacio para &lt;strong&gt;4 elementos&lt;/strong&gt;; una 2x3 podrá contener 6 elementos, una 2x4 albergará 8 elementos, y así sucesivamente.&lt;/p&gt;

&lt;p&gt;Si el número de &lt;strong&gt;elementos no coincide con la cantidad de celdas&lt;/strong&gt; disponibles, pueden ocurrir dos situaciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Si hay más elementos de los esperados, los adicionales se colocarán automáticamente en &lt;strong&gt;nuevas filas sin un formato definido&lt;/strong&gt;, a menos que establezcamos reglas específicas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Si hay menos elementos, solo se ocuparán las celdas necesarias, y las &lt;strong&gt;restantes quedarán vacías&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A medida que añadimos más elementos al grid, podemos ajustar las propiedades &lt;code&gt;grid-template-columns&lt;/code&gt; y &lt;code&gt;grid-template-rows&lt;/code&gt; para expandir la estructura y acomodar el nuevo contenido de manera organizada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ver todos los detalles y ejemplos 🔥
&lt;/h2&gt;

&lt;p&gt;Si quieres aprender más sobre &lt;strong&gt;CSS Grid con ejemplos prácticos&lt;/strong&gt;, puedes leer el artículo completo aquí 👉 &lt;strong&gt;&lt;a href="https://johnserrano.co/blog/css-grid-la-guia-completa-para-principiantes-y-avanzados" rel="noopener noreferrer"&gt;CSS Grid: La Guía Completa para Principiantes y Avanzados&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Te dejo el ejemplo final, &lt;a href="https://codepen.io/johnserranodev/pen/yyLgXma" rel="noopener noreferrer"&gt;ver ejemplo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones sobre CSS Grid
&lt;/h2&gt;

&lt;p&gt;CSS Grid es una poderosa herramienta para &lt;strong&gt;diseñar layouts complejos de manera flexible&lt;/strong&gt; y eficiente. A lo largo de este tema, hemos visto cómo estructurar cuadrículas utilizando &lt;code&gt;display: grid&lt;/code&gt; y definir filas y columnas con &lt;code&gt;grid-template-columns&lt;/code&gt; y &lt;code&gt;grid-template-rows&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;También exploramos conceptos clave como celdas, áreas, líneas y tracks, que nos permiten organizar mejor los elementos dentro del grid.&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi &lt;strong&gt;blog&lt;/strong&gt;, donde encontrarás más contenido sobre &lt;strong&gt;JavaScript&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt;, &lt;strong&gt;IA&lt;/strong&gt;, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>css</category>
      <category>beginners</category>
    </item>
    <item>
      <title>HTML: ¿Para qué sirve y qué son sus etiquetas?</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sat, 22 Feb 2025 20:58:42 +0000</pubDate>
      <link>https://forem.com/johnserranodev/html-para-que-sirve-y-que-son-sus-etiquetas-228d</link>
      <guid>https://forem.com/johnserranodev/html-para-que-sirve-y-que-son-sus-etiquetas-228d</guid>
      <description>&lt;p&gt;Aprende HTML: Descubre cómo funciona y las etiquetas clave para estructurar sitios web. Conocer HTML es fundamental para el desarrollo web moderno, ya que permite crear páginas atractivas y bien organizadas.&lt;/p&gt;

&lt;p&gt;En este artículo, exploraremos las funciones principales de HTML y cómo sus etiquetas te ayudan a diseñar contenido eficazmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es HTML?
&lt;/h2&gt;

&lt;p&gt;HTML, siglas de &lt;strong&gt;HyperText Markup Language (Lenguaje de Marcado de Hipertexto)&lt;/strong&gt;, es el lenguaje utilizado para estructurar y organizar el contenido de las páginas web. A través de una serie de elementos y etiquetas, &lt;strong&gt;HTML define la estructura básica de una página&lt;/strong&gt;, permitiendo la inclusión de textos, imágenes, enlaces, videos y otros elementos multimedia.&lt;/p&gt;

&lt;p&gt;Aunque no es un lenguaje de programación propiamente dicho, HTML es &lt;strong&gt;fundamental para el desarrollo web&lt;/strong&gt;, ya que establece la base sobre la cual se aplican estilos con CSS y se agrega interactividad con JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Para qué sirve HTML?
&lt;/h2&gt;

&lt;p&gt;La principal función de HTML es proporcionar la estructura de una página web. Gracias a HTML, los desarrolladores pueden:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Definir encabezados y párrafos&lt;/strong&gt;: Organizar el texto en secciones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Incorporar imágenes y videos&lt;/strong&gt;: Enriquecer el contenido con elementos multimedia.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Crear enlaces&lt;/strong&gt;: Conectar diferentes páginas o recursos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Construir listas y tablas&lt;/strong&gt;: Presentar información de manera ordenada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Formularios y botones&lt;/strong&gt;: Permitir la interacción con los usuarios.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Además, HTML se integra con CSS para mejorar el diseño y con JavaScript para agregar funcionalidades dinámicas.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es una etiqueta HTML?
&lt;/h2&gt;

&lt;p&gt;Las etiquetas HTML son fragmentos de código que se utilizan para estructurar y definir el contenido en un documento web. Estas etiquetas, también conocidas como &lt;strong&gt;"tags"&lt;/strong&gt;, proporcionan instrucciones al navegador sobre cómo mostrar el texto y otros elementos en una página web, permitiendo dar formato, funcionalidad y estructura al contenido visual&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomía de un elemento HTML
&lt;/h2&gt;

&lt;p&gt;Un elemento HTML se compone de varias partes importantes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Etiqueta de apertura&lt;/strong&gt;: Es el nombre del elemento, encerrado entre corchetes angulares &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt; (por ejemplo, &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; para un párrafo).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contenido&lt;/strong&gt;: El texto o los datos que aparecerán en la página.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Etiqueta de cierre&lt;/strong&gt;: Indica el final del elemento y se parece a la etiqueta de apertura, pero con una barra &lt;code&gt;/&lt;/code&gt; (por ejemplo, &lt;code&gt;&amp;lt;/p&amp;gt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atributos (opcional)&lt;/strong&gt;: Proporcionan información adicional sobre el elemento y se colocan dentro de la etiqueta de apertura, como &lt;strong&gt;class&lt;/strong&gt; o &lt;strong&gt;id&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ejemplo con un atributo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"important"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Este es un párrafo importante.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso, &lt;code&gt;class="important"&lt;/code&gt; es un atributo que puede utilizarse para aplicar estilos específicos a este párrafo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Etiquetas principales de HTML
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/code&gt;: Declara el tipo de documento y es indispensable en HTML5, garantizando que el navegador interprete correctamente el código.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;: Elemento raíz que contiene todo el contenido de la página web.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;: Sección que incluye metadatos, como el conjunto de caracteres y el título de la página.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;meta charset="UTF-8"&amp;gt;&lt;/code&gt;: Establece la codificación de caracteres utilizada en el documento, siendo &lt;code&gt;UTF-8&lt;/code&gt; la opción más común para soportar una amplia gama de caracteres.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;: Define el título que aparecerá en la pestaña del navegador, proporcionando una referencia clara sobre el contenido de la página.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;: Contiene todos los elementos y contenido visible que se presentará al usuario en la página web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estructura básica de un documento HTML
&lt;/h2&gt;

&lt;p&gt;Un documento HTML sigue una estructura jerárquica que facilita su interpretación por parte de los navegadores web. A continuación, se presenta un ejemplo básico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Mi Primera Página Web&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;¡Bienvenido a mi sitio web!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Este es un párrafo de ejemplo.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ¿Cuáles son las etiquetas y elementos de HTML más usados?
&lt;/h2&gt;

&lt;p&gt;Existen diversas etiquetas en HTML, pero algunas de las más utilizadas incluyen:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; a &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt;: Encabezados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Título Principal&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Subtítulo&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;: Párrafos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Este es un párrafo de ejemplo.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;: Enlaces.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;: Imágenes, se insertan con la etiqueta &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;, utilizando el atributo &lt;code&gt;src&lt;/code&gt; para especificar la ruta de la imagen y &lt;code&gt;alt&lt;/code&gt; para proporcionar un texto alternativo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"ruta/imagen.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Descripción de la imagen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;: Listas no ordenadas y ordenadas.&lt;/p&gt;

&lt;p&gt;No ordenadas: Utilizan &amp;lt;&lt;code&gt;ul&amp;gt;&lt;/code&gt; para la lista y &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; para cada elemento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Elemento 1&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Elemento 2&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Elemento 3&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ordenadas: Emplean &lt;code&gt;&amp;lt;ol&amp;gt;&lt;/code&gt; para la lista y &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; para cada elemento.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ol&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Primer elemento&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Segundo elemento&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;Tercer elemento&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ol&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;tr&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt;: Tablas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; y &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;: Contenedores genéricos.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;: Formularios y entradas de datos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;"/procesar_formulario"&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"nombre"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Nombre:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"nombre"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"nombre"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Correo electrónico:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"mensaje"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Mensaje:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mensaje"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"mensaje"&lt;/span&gt; &lt;span class="na"&gt;rows=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt; &lt;span class="na"&gt;cols=&lt;/span&gt;&lt;span class="s"&gt;"50"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Enviar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estas etiquetas son esenciales para construir la estructura y el contenido de una página web de manera efectiva.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML Semántico
&lt;/h2&gt;

&lt;p&gt;El HTML semántico mejora la accesibilidad y optimización para motores de búsqueda al utilizar etiquetas que describen su contenido, como:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt;: Encabezado de la página o sección.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt;: Contenido independiente y reutilizable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt;: Secciones temáticas.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;footer&amp;gt;&lt;/code&gt;: Pie de página.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;: Contenido relacionado o complementario.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Descubre el resto de los detalles y puntos clave en mi blog&lt;/strong&gt;:&lt;br&gt;
👉 &lt;a href="https://johnserrano.co/blog/html-para-que-sirve-y-que-son-sus-etiquetas" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;HTML es el pilar fundamental para la creación y estructuración de contenido en la web. Su simplicidad y accesibilidad lo convierten en una herramienta esencial tanto para principiantes como para desarrolladores experimentados. &lt;/p&gt;

&lt;p&gt;Aunque por sí solo genera &lt;strong&gt;páginas estáticas&lt;/strong&gt;, su verdadero potencial se manifiesta al combinarse con &lt;strong&gt;CSS&lt;/strong&gt; y &lt;strong&gt;JavaScript&lt;/strong&gt;, permitiendo el desarrollo de sitios web &lt;strong&gt;dinámicos e interactivos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Dominar HTML no solo es el primer paso en el camino del desarrollo web, sino que también sienta &lt;strong&gt;las bases para comprender&lt;/strong&gt; y manejar tecnologías web más avanzadas.&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi &lt;strong&gt;blog&lt;/strong&gt;, donde encontrarás más contenido sobre &lt;strong&gt;JavaScript&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt;, &lt;strong&gt;IA&lt;/strong&gt;, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;
&lt;h2&gt;
  
  
  🎥 Aprende con ejemplos prácticos
&lt;/h2&gt;

&lt;p&gt;Si quieres ver &lt;strong&gt;HTML&lt;/strong&gt; en acción, te dejo este video donde explico paso a paso cómo usar sus etiquetas y aplicar buenas prácticas. ¡No te lo pierdas! 👇&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/mI_RDbjMfVQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>programming</category>
      <category>html</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Husky y Lint-Staged: Cómo configurar y automatizar pre-commit hooks para test, lint y formateo</title>
      <dc:creator>John Serrano (DEV)</dc:creator>
      <pubDate>Sat, 08 Feb 2025 15:14:03 +0000</pubDate>
      <link>https://forem.com/johnserranodev/husky-y-lint-staged-como-configurar-y-automatizar-pre-commit-hooks-para-test-lint-y-formateo-4553</link>
      <guid>https://forem.com/johnserranodev/husky-y-lint-staged-como-configurar-y-automatizar-pre-commit-hooks-para-test-lint-y-formateo-4553</guid>
      <description>&lt;p&gt;En el desarrollo de proyectos JavaScript, &lt;strong&gt;mantener la consistencia del código y garantizar altos estándares&lt;/strong&gt; de calidad puede resultar un reto, especialmente en equipos con múltiples colaboradores. &lt;/p&gt;

&lt;p&gt;La integración de &lt;strong&gt;herramientas de automatización&lt;/strong&gt; en el flujo de trabajo permite ejecutar de forma automática tareas esenciales como el &lt;strong&gt;formateo&lt;/strong&gt;, el análisis de código &lt;strong&gt;(lint)&lt;/strong&gt; y la ejecución de test antes de que se realicen &lt;strong&gt;commits&lt;/strong&gt; o &lt;strong&gt;push&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Este artículo explora en detalle cómo configurar &lt;strong&gt;Husky&lt;/strong&gt; y &lt;strong&gt;Lint-Staged&lt;/strong&gt; para reforzar la calidad del código en tus proyectos JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué es Husky y Lint-Staged?
&lt;/h2&gt;

&lt;p&gt;Husky es una solución nativa para gestionar &lt;strong&gt;Git hooks&lt;/strong&gt;, es decir, scripts que se ejecutan automáticamente en determinados eventos de Git &lt;strong&gt;(como antes de un commit o un push)&lt;/strong&gt;. Gracias a &lt;strong&gt;Husky&lt;/strong&gt;, es posible asegurarse de que se cumplan una serie de comprobaciones y tareas esenciales antes de que los cambios se integren al repositorio.&lt;/p&gt;

&lt;p&gt;Por otro lado, &lt;strong&gt;Lint-Staged&lt;/strong&gt; es una herramienta que permite ejecutar comandos únicamente &lt;strong&gt;sobre los archivos que han sido modificados&lt;/strong&gt; y se encuentran en estado &lt;strong&gt;“staged”&lt;/strong&gt;. Esto resulta en un proceso mucho más eficiente, ya que se aplican los formateos y las validaciones únicamente en el conjunto reducido de archivos afectados, en lugar de analizar toda la base de código.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Por qué usar Husky y Lint-Staged?
&lt;/h2&gt;

&lt;p&gt;Utilizar Husky y Lint-Staged aporta múltiples beneficios en el desarrollo de aplicaciones JavaScript:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Aseguramiento de la calidad&lt;/strong&gt;: Garantizan que el código cumpla con las normas de estilo y calidad mediante la ejecución automática de &lt;strong&gt;linters&lt;/strong&gt;, &lt;strong&gt;formateadores&lt;/strong&gt; y &lt;strong&gt;pruebas unitarias&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prevención de errores&lt;/strong&gt;: Al interceptar el proceso de &lt;strong&gt;commit&lt;/strong&gt; o &lt;strong&gt;push&lt;/strong&gt;, se detectan y corrigen errores antes de que estos se integren a la base de código, evitando problemas en producción.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimización del flujo de trabajo&lt;/strong&gt;: Lint-Staged analiza únicamente los &lt;strong&gt;archivos modificados&lt;/strong&gt;, lo que reduce considerablemente el tiempo de ejecución de las tareas de validación.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Uniformidad en el equipo&lt;/strong&gt;: Permiten que todos los colaboradores &lt;strong&gt;sigan los mismos estándares&lt;/strong&gt;, asegurando la coherencia y mantenibilidad del código.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configurando Husky y Lint-Staged
&lt;/h2&gt;

&lt;p&gt;A continuación, se detalla el proceso de configuración de &lt;strong&gt;Husky&lt;/strong&gt; y &lt;strong&gt;Lint-Staged&lt;/strong&gt; en un entorno &lt;strong&gt;JavaScript&lt;/strong&gt;, integrando herramientas fundamentales como &lt;strong&gt;Prettier&lt;/strong&gt;, &lt;strong&gt;ESLint&lt;/strong&gt; y &lt;strong&gt;Vitest&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configurando el entorno
&lt;/h3&gt;

&lt;p&gt;Imaginemos que estamos trabajando en un proyecto JavaScript en el que es imprescindible mantener un código limpio y sin errores. Para ello, configuraremos los siguientes scripts en el archivo &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prettier como formateador&lt;/strong&gt;:&lt;br&gt;
Se encargará de aplicar un formato consistente en todo el código.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run format&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ESLint como linter&lt;/strong&gt;:&lt;br&gt;
Detecta errores y aplica buenas prácticas de codificación.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run lint&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vitest como framework de pruebas&lt;/strong&gt;:&lt;br&gt;
Valida que el código funcione según lo esperado mediante pruebas unitarias.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Estos comandos se integrarán en nuestros &lt;strong&gt;Git hooks&lt;/strong&gt; para que, antes de cada commit, se asegure que el código se formatea, se analiza y se prueba.&lt;/p&gt;
&lt;h2&gt;
  
  
  Instalar Husky y configuración
&lt;/h2&gt;

&lt;p&gt;Ejecuta el siguiente comando para instalar Husky como dependencia de desarrollo:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install --save-dev husky&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Inicializa Husky en tu repositorio (recuerda que debes haber inicializado previamente Git en el proyecto):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx husky init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Este comando añade automáticamente un script de preparación en el &lt;code&gt;package.json&lt;/code&gt; y crea una carpeta &lt;code&gt;.husky&lt;/code&gt; en la raíz del proyecto que contendrá, entre otros, el hook pre-commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuración del hook pre-commit&lt;/strong&gt;:&lt;br&gt;
Edita el archivo &lt;code&gt;.husky/pre-commit&lt;/code&gt; para incluir los comandos necesarios. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run format
npm run lint
npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esta configuración, cada vez que realices un &lt;strong&gt;commit&lt;/strong&gt;, Husky ejecutará estos comandos. Si alguno de ellos falla, se detendrá el proceso de commit, permitiéndote corregir los errores antes de proceder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Instalar Lint-Staged y configuración
&lt;/h2&gt;

&lt;p&gt;Añade Lint-Staged como dependencia de desarrollo:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install --save-dev lint-staged&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Agrega el siguiente script en tu archivo &lt;code&gt;package.json&lt;/code&gt; para facilitar la ejecución de Lint-Staged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lint-staged"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lint-staged"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crea un archivo llamado &lt;code&gt;.lintstagedrc.json&lt;/code&gt; en la raíz del proyecto y define los comandos a ejecutar para los archivos modificados. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"*.{css,scss}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"npx prettier . --write"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"*.{js,jsx,ts,tsx}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"npx prettier . --write"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"eslint --fix"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"vitest run --environment=jsdom"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esta configuración, &lt;strong&gt;Lint-Staged&lt;/strong&gt; aplicará &lt;strong&gt;Prettier&lt;/strong&gt;, &lt;strong&gt;ESLint&lt;/strong&gt; y &lt;strong&gt;Vitest&lt;/strong&gt; únicamente en los archivos JavaScript (y sus variantes) que hayan sido modificados y añadidos al &lt;strong&gt;área de staging&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Para aprovechar Lint-Staged en el &lt;strong&gt;hook pre-commit&lt;/strong&gt;, modifica el archivo &lt;code&gt;.husky/pre-commit&lt;/code&gt; para que ejecute el script de Lint-Staged en lugar de correr los comandos de forma individual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run lint-staged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De esta forma, el proceso de validación se optimiza al centrarse únicamente en los cambios realizados, ahorrando tiempo y recursos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Descubre el resto de los detalles y puntos clave en mi blog&lt;/strong&gt;:&lt;br&gt;
👉 &lt;a href="https://johnserrano.co/blog/husky-y-lint-staged-como-configurar-y-automatizar-pre-commit-hooks" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;La integración de &lt;strong&gt;Husky&lt;/strong&gt; y &lt;strong&gt;Lint-Staged&lt;/strong&gt; en un proyecto JavaScript es una estrategia altamente eficaz para garantizar la calidad y consistencia del código. &lt;/p&gt;

&lt;p&gt;Al automatizar tareas fundamentales como el &lt;strong&gt;formateo&lt;/strong&gt;, el &lt;strong&gt;análisis estático&lt;/strong&gt; y la ejecución de &lt;strong&gt;pruebas&lt;/strong&gt;, estas herramientas permiten detectar errores de manera temprana y aseguran que el código que se integra al repositorio &lt;strong&gt;cumpla con los estándares&lt;/strong&gt; establecidos.&lt;/p&gt;

&lt;p&gt;Aunque la configuración inicial pueda parecer compleja, los beneficios a largo plazo como &lt;strong&gt;la reducción de errores&lt;/strong&gt;, un proceso de desarrollo &lt;strong&gt;más ágil&lt;/strong&gt; y una &lt;strong&gt;mayor uniformidad&lt;/strong&gt; en el equipo justifican ampliamente la inversión de tiempo y esfuerzo. &lt;/p&gt;

&lt;p&gt;La implementación de Husky y Lint-Staged no solo &lt;strong&gt;mejora la calidad del producto final&lt;/strong&gt;, sino que también fomenta las &lt;strong&gt;buenas prácticas&lt;/strong&gt; y &lt;strong&gt;optimiza el flujo de trabajo&lt;/strong&gt;, permitiéndote concentrar esfuerzos en la creación de soluciones robustas y escalables en JavaScript.&lt;/p&gt;

&lt;p&gt;Espero que esta guía te resulte de utilidad y te anime a incorporar estas prácticas en tus proyectos. ¡Éxito en tus desarrollos!&lt;/p&gt;

&lt;p&gt;Te invito a visitar mi &lt;strong&gt;blog&lt;/strong&gt;, donde encontrarás más contenido sobre &lt;strong&gt;JavaScript&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt;, &lt;strong&gt;IA&lt;/strong&gt;, buenas prácticas y mucho más. 👉 &lt;a href="https://johnserrano.co/blog" rel="noopener noreferrer"&gt;johnserrano.co/blog&lt;/a&gt; ¡No te lo pierdas!&lt;/p&gt;

&lt;p&gt;Gracias por leer. ❤️&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>husky</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
