Jorge Baumann

Senior Full Stack Developer · @baumannzone

Ingeniero de software y divulgador de contenido. Speaker. Apasionado del desarrollo web y del fitness.

Últimos artículos del blog

Aquí tienes mis artículos más recientes y uno aleatorio de regalo

🌶️ New

Beneficios de dar charlas como developer

Descubre cómo dar charlas técnicas puede transformar tu carrera como desarrollador, mejorando tus habilidades de comunicación, ampliando tu red profesional y posicionándote como líder de opinión en la comunidad tech.

RSL: el nuevo estándar que quiere que la IA pague por tu contenido

Reddit, Yahoo y Medium se suman a RSL (Really Simple Licensing), el nuevo estándar que busca que las empresas de IA paguen por entrenar con el contenido de creadores y medios.

Enlaces de afiliados bien etiquetados con 'sponsored'

Mejora tu SEO marcando enlaces de afiliados como patrocinados. Google te lo agradecerá.

See More

Aquí irían las fotos...\n\n```\n\n```css\nsummary::marker {\n content: \"📸\" / \"Ver\";\n}\n```\n\n**Resultado visual:** 📸 Galería de fotos \n**Lo que lee el screen reader:** _\"Ver Galería de fotos\"_\n\nDe esta forma puedes decorar visualmente el summary sin añadir ruido innecesario a usuarios de tecnologías asistivas.\n\n## Compatibilidad de navegadores\n\nLa sintaxis con texto alternativo (content: \"icono\" / \"texto\";) todavía no tiene un soporte uniforme en todos los entornos.\n\n- ✅ Chrome, Firefox y Edge (Windows + NVDA/JAWS): soportan tanto el icono como el texto alternativo.\n- ⚠️ Chrome y Firefox en macOS con VoiceOver: muestran el emoji visual, pero el lector de pantalla ignora el texto alternativo.\n- ❌ Safari + VoiceOver en macOS: directamente roto → no se ve ni el emoji ni se lee el texto.\n\nTraducido para la gen Z: úsalo para decoración, pero no confíes en `::marker` como única fuente de información importante.\n\n## Casos de uso comunes\n\n- **Iconos decorativos**:\n\n ```css\n summary::marker {\n content: \"✨\" / \"\";\n }\n ```\n\n- **Iconos informativos**:\n\n ```css\n summary::marker {\n content: \"⚠️\" / \"Advertencia\";\n }\n ```\n\n- **Estados**:\n\n ```css\n summary::marker {\n content: \"🔽\" / \"Expandir\"; /* o \"🔼\" / \"Contraer\" */\n }\n ```\n\n## Conclusión\n\nUn detalle minúsculo, pero que marca la diferencia entre un acordeón bonito y uno realmente inclusivo.\nAsí que ya sabes: si juegas con `::marker`, no olvides también jugar con la accesibilidad.\n\n## ℹ️ Extra: lectores de pantalla en Windows\n\n**NVDA** (_NonVisual Desktop Access_) → Lector de pantalla gratuito y open source, muy popular en Windows.\nLo usan tanto personas con discapacidad visual como desarrolladores para testear accesibilidad.\n\n**JAWS** (_Job Access With Speech_) → Lector de pantalla comercial (de pago, bastante caro).\nEs muy potente y está muy extendido en entornos corporativos.\n","collection":"blog","data":{"title":"Haz accesible el contenido de los pseudo-elementos ::marker en CSS","description":"Cómo personalizar ::marker en

sin romper la accesibilidad. Descubre cómo usar content con texto alternativo o incluso ocultarlo a los lectores de pantalla.","pubDate":"2025-08-20T00:00:00.000Z","published":true,"tags":["CSS","a11y"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Haz%20accesible%20el%20contenido%20de%20los%20pseudo-elementos%20::marker&tags=CSS,a11y","relatedPosts":["acordeones-nativos-en-html-sin-una-linea-de-javascript"]}},{"id":"acordeones-nativos-en-html-sin-una-linea-de-javascript.mdx","slug":"acordeones-nativos-en-html-sin-una-linea-de-javascript","body":"\nimport Demo1 from \"../../components/demos-blog/acordeones-nativos-en-html-sin-una-linea-de-javascript/1.astro\";\nimport Demo2 from \"../../components/demos-blog/acordeones-nativos-en-html-sin-una-linea-de-javascript/2.astro\";\nimport Demo3 from \"../../components/demos-blog/acordeones-nativos-en-html-sin-una-linea-de-javascript/3.astro\";\nimport Demo4 from \"../../components/demos-blog/acordeones-nativos-en-html-sin-una-linea-de-javascript/4.astro\";\n\nLos elementos `
` y `` de HTML son una joya oculta para crear interfaces tipo acordeón o \"ver más / ver menos\", de forma nativa, accesible y sin dependencias externas.\n\nNada de instalar otro paquete de npm que te rompa el proyecto en dos meses.\n\n## Uso básico\n\nPor defecto, cada `
` se puede abrir de forma independiente. Esto es genial si quieres permitir que se expandan múltiples secciones a la vez:\n\n```html\n
\n HTML\n

Es el lenguaje de marcado base para cualquier página web.\n\n

\n CSS\n

\n Sirve para dar estilo a los elementos, desde colores hasta layouts\n complejos.\n \n\n

\n JavaScript\n

Permite añadir interactividad, lógica y manipulación del DOM.\n\n```\n\nEste código genera un acordeón con tres secciones y cada una se despliga de forma independiente, sin afectar a las demás.\n\n\n\nEsto funciona genial y es la mejor manera de hacer un componente de acordeón con HTML nativo. Pero en algunos casos, vas a necesitar que solo una sección esté abierta a la vez.\n\n## Comportamiento exclusivo\n\nSi quieres que solo una sección esté abierta a la vez, tenemos dos opciones:\n\n1. **Usar JavaScript** (meh): Puedes usar JavaScript para cerrar otros `

` cuando uno se abre.\n2. **Usar HTML** (opción nativa): Puedes usar un atributo HTML para controlar el estado de los acordeones. 🏆\n\n### Opción JavaScript\n\nSi necesitas un control más granular (animaciones, persistencia en `localStorage`, etc.), puedes usar JavaScript. Aquí tienes un ejemplo sencillo:\n\n```js\ndocument.querySelectorAll(\"details\").forEach((targetDetail) => {\n targetDetail.addEventListener(\"click\", () => {\n document.querySelectorAll(\"details\").forEach((detail) => {\n if (detail !== targetDetail) detail.removeAttribute(\"open\");\n });\n });\n});\n```\n\n### Opción HTML\n\nLa solución nativa (y poco conocida) es usar el atributo `name`. Si todos los `
` tienen el mismo `name`, solo uno puede estar abierto a la vez.\n\nEste comportamiento recuerda al de los ``, que solo uno puede estar activo a la vez.\n\nEl ejemplo anterior se puede reescribir así:\n\n```html\n
\n ¿Cómo reinicio mi contraseña?\n

Haz clic en “olvidé mi contraseña” como todo el mundo.\n\n\n

\n ¿Puedo usar mi cuenta en varios dispositivos?\n

Sí, aunque tu gato probablemente también lo está usando sin que sepas.\n\n\n

\n ¿Qué pasa si borro mi cuenta?\n

Pasas al siguiente plano existencial digital. No hay vuelta atrás.\n\n```\n\n\n\n> 🧭 Safari solo permite cambiar color y tamaño del `::marker`, no su contenido. ~~Otro ejemplo más de Safari convirtiéndose en el nuevo IE~~.\n\n## Dale estilo a tus `

`\n\nAhora que tus `
` se comportan como tu quieres, puedes ir un paso más allá y darles un toque visual simpático.\n\nCSS te permite modificar los íconos que aparecen al lado de `` usando el pseudo-elemento `::marker`.\n\nPor defecto, el ícono es un triángulo (⏵), pero puedes cambiarlo a cualquier cosa que te guste.\n\n```css\nsummary::marker {\n content: \"🙈\";\n}\n\n[open] summary::marker {\n content: \"🙉\";\n}\n```\n\n¿No te parece gracioso? Mira este ejemplo:\n\n\n\nY ahora, una muestra de lo que pasa cuando le das a los acordeones una pizca de humor y personalidad con emojis. Todo lo aprendido, en acción. Ábrelos y verás.\n\n\n\n## Accesibilidad\n\nLos elementos `
` y `` son semánticamente accesibles por defecto. No necesitas hacer nada especial con JavaScript.\n\nEl elemento `` es focusable y se puede activar con `Enter` o `Space`.\n\nComo siempre: **testea**. Con teclado, con lectores de pantalla, y si tienes amigos, con alguien que no tenga tus mismos privilegios visuales o de motricidad. El HTML hace mucho por ti, pero tú tienes que poner algo también.\n\n## Conclusión\n\nLos elementos `
` y `` son herramientas potentes, accesibles y que muchas veces pasamos por alto. Para acordeones simples, no necesitas JavaScript, ni React, ni MUI, ni librerías de 20 KB. Solo HTML y un poco de CSS.\n\nY si quieres limitar su comportamiento a uno abierto a la vez, puedes usar el atributo name para conseguirlo de forma elegante.\n\nNo subestimes el poder de lo nativo. La próxima vez que necesites un acordeón o un panel desplegable, ya sabes: empieza por lo simple. Lo demás, si hace falta, ya vendrá.\n\n**P.D.**: Si acabas usando esto en producción, mándame un pantallazo o un enlace. Me hace ilusión ver estos detallitos sueltos por la web salvaje.\n","collection":"blog","data":{"title":"Acordeones nativos en HTML sin una línea de JavaScript","description":"Aprende a crear acordeones accesibles y funcionales utilizando solo HTML, sin necesidad de JavaScript","pubDate":"2025-05-09T00:00:00.000Z","updatedDate":"2025-06-03T00:00:00.000Z","published":true,"tags":["HTML","a11y"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Acordeones%20nativos%20en%20HTML%20sin%20una%20línea%20de%20JavaScript&tags=HTML,A11y","relatedPosts":["haz-accesible-el-contenido-de-los-pseudo-elementos-marker-en-css"]}},{"id":"personaliza-marker-en-css-sin-romper-la-accesibilidad.md","slug":"personaliza-marker-en-css-sin-romper-la-accesibilidad","body":"\nAñadir un emoji o un icono a una lista puede parecer una mejora visual menor, hasta que se prueba con un lector de pantalla. ¿Sabías que el contenido definido en `::marker` también se lee en voz alta?\n\nUn elemento decorativo puede convertirse en ruido para personas que navegan con tecnologías de asistencia.\n\nEjemplo básico:\n\n```css\nsummary::marker {\n content: \"🎵\";\n}\n```\n\n```html\nPlaylist\n```\n\nVisualmente, el resultado puede parecer correcto. Sin embargo, un lector de pantalla podría anunciar \"_Nota musical Playlist_\", algo que no siempre coincide con la intención del contenido.\n\nPor suerte, CSS permite separar el contenido visual del texto que se expone a tecnologías de asistencia mediante un segundo valor en `content`.\n\n## Opción 1: Definir el texto anunciado\n\n```css\nsummary::marker {\n content: \"🎵\" / \"Música\";\n}\n```\n\nCon esta configuración, el lector anunciará \"_Música Playlist_\" en lugar de intentar interpretar el emoji.\n\n## Opción 2: Omitir el anuncio del marcador\n\n```css\nsummary::marker {\n content: \"🎵\" / \"\";\n}\n```\n\nEn este caso, el lector de pantalla anunciará únicamente \"_Playlist_\", ignorando el emoji. El cambio visual es nulo y la experiencia auditiva resulta más limpia.\n\n> Nota: el comportamiento puede variar según la combinación de navegador y lector de pantalla, así que conviene validar en tu entorno objetivo. Así que haz pruebas cross-browser y con diferentes tecnologías de asistencia para asegurarte de que la experiencia es óptima para todos los usuarios.\n\n---\n\n![Ejemplo de personalización de markers en CSS](../../assets/blog/personaliza-marker-en-css-sin-romper-la-accesibilidad/image.png)\n\nSi usas macOS, puedes validarlo rápidamente con **VoiceOver**.\n","collection":"blog","data":{"title":"Personaliza ::marker en CSS sin romper la accesibilidad","description":"Aprende a personalizar ::marker en CSS sin romper la accesibilidad, separando el contenido visual de lo que leen los lectores de pantalla.","pubDate":"2025-05-08T00:00:00.000Z","published":true,"tags":["CSS","a11y"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Personaliza%20%3A%3Amarker%20en%20CSS%20sin%20romper%20la%20accesibilidad&tags=CSS,a11y"}},{"id":"la-sintaxis-secreta-de-of-s-en-nth-child-que-probablemente-estas-ignorando.mdx","slug":"la-sintaxis-secreta-de-of-s-en-nth-child-que-probablemente-estas-ignorando","body":"\nimport Demo1 from \"../../components/demos-blog/la-sintaxis-secreta-de-of-s-en-nth-child-que-probablemente-estas-ignorando/1.astro\";\nimport Demo2 from \"../../components/demos-blog/la-sintaxis-secreta-de-of-s-en-nth-child-que-probablemente-estas-ignorando/2.astro\";\n\nUna de las joyas escondidas en la caja de herramientas de CSS es la sintaxis matemática de `:nth-child()`. Mucha gente la usa con números simples como `:nth-child(2n)` y se queda ahí, sin saber que la fórmula acepta mucho más.\n\nHoy vamos a diseccionar la famosa fórmula `An+B` de CSS. Hoy vas a aprender a usar el selector `:nth-child()` con su nueva y mejorada sintaxis `of S`.\n\n## TL;DR (para ir al grano)\n\n```css\n:nth-child(2 of .active) {\n color: red;\n}\n```\n\n## Lo básico: `:nth-child(An+B)`\n\nYa conoces la sintaxis clásica de `:nth-child()`:\n\n- `:nth-child(2)`: Selecciona el segundo elemento.\n- `:nth-child(2n)`: Selecciona todos los elementos pares (2º, 4º, 6º, 8º, ...).\n- `:nth-child(2n+1)`: Selecciona todos los elementos impares (1º, 3º, 5º, 7º, ...).\n\nPero, ¿sabías que también puedes usar la sintaxis `of S` para hacer un prefiltro?\n\n## ¿Qué es `of S`?\n\nCuando se especifica `of S`, la lógica `An+B` se aplica solo a los elementos que coinciden con la lista de selectores `S`.\nBásicamente, esto significa que puedes prefiltrar los elementos hijos antes de que `An+B` entre en acción.\n\n```css\ntr:nth-child(2 of .active) {\n /* ... */\n}\n```\n\nEn este ejemplo, selecciona el segundo elemento que tenga la clase `.active`.\nDicho de otro modo, de entre todos los hijos con la clase `.active`, selecciona el segundo.\n\n## Caso práctico: lista con elementos ocultos\n\nImagina que tienes seis elementos en una lista, pero dos están ocultos con el atributo `hidden`.\n\n```html\n
  • Elemento 1\n
  • Elemento 3\n
  • Elemento 4\n
  • Elemento 6\n```\n\nSi usas el clásico `:nth-child(even)`:\n\n```css\nli:nth-child(even) {\n background-color: violet;\n}\n```\n\n\n\nSe resaltarán los elementos en las posiciones **3** y **4** de la lista, es decir, los elementos **4** y **6** del HTML.\nEsto ocurre porque incluso los elementos ocultos se tienen en cuenta al contar.\n\nNo es el resultado que esperarías si lo que quieres es **resaltar cada segundo elemento visible**.\n\n## Entra en escena `of S`\n\nDesde el 2023, la sintaxis `of S` de `:nth-child()` está disponible en todos los navegadores modernos.\n\nPara solucionar este problema, puedes usar `of :not([hidden])`:\n\n```css\nli:nth-child(even of :not([hidden])) {\n background-color: violet;\n}\n```\n\n\n\nCronología:\n\n1. Crea una lista de todos los elementos `
  • ` que están visibles.\n2. Aplica la regla `li:nth-child(even)` a los elementos de esta nueva lista.\n\nBoom. Ahora sí: se resaltan solo los elementos visibles **1**, **3**, **4**, **6**, y se ignoran los `hidden`.\n\n---\n\n## Curiosidades\n\n- Safari fue el primero en implementar esta sintaxis con el nombre `of S` en el 2015 (iOS y macOS).\n- Esta sintaxis también es compatible con `:nth-last-child()`.\n\n![Meme de CSS](../../assets/blog/la-sintaxis-secreta-de-of-s-en-nth-child-que-probablemente-estas-ignorando/image.png)\n","collection":"blog","data":{"title":"La sintaxis secreta de `of S` en `:nth-child()` que probablemente estás ignorando","description":"Descubre cómo usar `:nth-child(of S)` para seleccionar elementos con una precisión quirúrgica digna de CSS moderno y evita errores comunes que ni sabías que estabas cometiendo.","pubDate":"2025-05-02T00:00:00.000Z","published":true,"tags":["CSS","TIL"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=La%20sintaxis%20secreta%20de%20`of%20S`%20en%20`:nth-child()`%20que%20probablemente%20est%C3%A1s%20ignorando&tags=CSS,TIL"}},{"id":"si-solo-escribes-codigo-no-estas-haciendo-suficiente-segun-esta-metrica.md","slug":"si-solo-escribes-codigo-no-estas-haciendo-suficiente-segun-esta-metrica","body":"\nCuando trabajamos en repositorios compartidos, siempre llega ese momento obligatorio: revisar código ajeno antes de aprobar una **pull request** (PR).\n\nEn esos momentos se nota mucho cómo reaccionamos cada uno. Algunos revisan el código rápidamente, otros se detienen más. No suele haber alguien específico encargado de mejorar continuamente el código, así que cada persona decide cómo actuar.\n\nSegún mi experiencia, podemos distinguir cuatro tipos de personas según cómo gestionan esta situación:\n\n## Grupo 1 🙄\n\nLa mayoría revisa la PR superficialmente, aprueba el código si cumple con los requisitos más básicos y pasa a otra tarea, ignorando pequeños problemas o posibles mejoras. Es decir, cumplen sus objetivos pero dejan deuda técnica acumulada que en el futuro alguien tendrá que resolver.\n\n## Grupo 2 🫥\n\nRevisan el código, aprueban la PR y de vez en cuando realizan pequeños ajustes o sugerencias para evitar que el código empeore. Van un paso más allá para garantizar que el sistema no quede peor de lo que lo encontraron.\n\n## Grupo 3 🙃\n\nUn grupo más pequeño aprovecha la PR para arreglar problemas técnicos, pero solo cuando estos bloquean o afectan directamente su propio trabajo o futuras tareas inmediatas.\n\n## Grupo 4 🤩\n\nUn reducido grupo de developers utiliza activamente cada PR para mejorar proactivamente la calidad global del código, refactorizando o sugiriendo mejoras incluso cuando no son estrictamente necesarias para su trabajo a corto plazo o cuando no les afectan directamente.\n\n## ¿Qué impacto tienes como desarrollador?\n\n![Métrica de la PR](../../assets/blog/si-solo-escribes-codigo-no-estas-haciendo-suficiente-segun-esta-metrica/image.png)\n\nLa calidad de nuestro trabajo no solo se mide en el código que escribimos, sino en nuestra capacidad de ver más allá de las tareas inmediatas. La \"**métrica de la PR**\" es una herramienta útil para autoevaluar nuestro impacto real en el equipo y el proyecto:\n\n### ¿En qué grupo estás?\n\n- **Grupo 1**: (por debajo de las expectativas): cumple únicamente con sus tareas inmediatas, dejando deuda técnica acumulada.\n\n- **Grupo 2**: (cumple expectativas): realiza sus tareas asegurándose de no empeorar el código existente.\n\n- **Grupo 3**: (cumple expectativas): mejora el código, pero solo cuando le afecta directamente.\n\n- **Grupo 4**: (supera expectativas): busca activamente mejorar el sistema para beneficio colectivo, incluso cuando no es directamente su responsabilidad o beneficio inmediato.\n\n---\n\nAhora pregúntate con sinceridad:\n\n> ¿En qué grupo encajo yo?\n\n👇 Déjame un comentario y cuéntame con qué grupo te identificas.\n","collection":"blog","data":{"title":"Si solo escribes código, no estás haciendo suficiente (según esta métrica)","description":"¿Estás aportando o solo 'pasando la bola'? Una reflexión práctica sobre cómo pequeñas acciones proactivas pueden marcar la diferencia en la calidad del código y en la eficiencia de tu equipo.","pubDate":"2025-04-25T00:00:00.000Z","published":true,"tags":["Career","Git"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Si%20solo%20escribes%20c%C3%B3digo%2C%20no%20est%C3%A1s%20haciendo%20suficiente%20(seg%C3%BAn%20esta%20m%C3%A9trica)&tags=Career,Git"}},{"id":"doble-igual-vs-triple-igual-en-javascript.md","slug":"doble-igual-vs-triple-igual-en-javascript","body":"\nCuando trabajamos con JavaScript, una de las decisiones más importantes que debemos tomar es qué operador de igualdad usar: `==` o `===`. Aunque ambos sirven para comparar valores, tienen comportamientos muy diferentes que pueden afectar significativamente a nuestro código. En este artículo, te voy a explicar la diferencia entre ambos y cuándo usar cada uno.\n\n## TL;DR dogmático\n\nUsa siempre `===` y olvídate de `==`.\n\n## El operador de igualdad estricta (`===`)\n\nCuando usas el triple igual `===`, hay dos reglas que debes recordar:\n\n- **Igualdad estricta**: cuando comparas valores primitivos.\n- **Igualdad por referencia**: cuando comparas valores por referencia.\n\nSí, suena simple... hasta que comparas dos arrays vacíos y te preguntas por qué JavaScript te odia.\n\nEl operador `===` (triple igual) es conocido como el **operador de igualdad estricta**. Este operador compara tanto el valor como el tipo de dato de los operandos. Solo devuelve `true` si ambos son exactamente iguales.\n\n### Igualdad estricta\n\nLa igualdad estricta verifica que tanto el tipo (`number`, `string`, `boolean`, etc.) como el valor sean iguales.\n\n- Si el **tipo** es el mismo pero el **valor** no, obtendrás `false`.\n- Si el **valor** es el mismo pero el **tipo** no, también obtendrás `false`.\n- Solo si el **tipo** y el **valor** son exactamente iguales, obtendrás `true`.\n\n```javascript\n10 === 10; // true. Mismo tipo, mismo valor.\n10 === 20; // false. Mismo tipo, valor diferente.\n10 === \"10\"; // false. Distinto tipo, mismo valor.\n\nfalse === false; // true. Mismo tipo, mismo valor.\nfalse === true; // false. Mismo tipo, distinto valor.\nfalse === \"false\"; // false. Distinto tipo, mismo valor.\n```\n\nParece lo bastante simple, pero como mencionamos antes, esta regla se rompe cuando empezamos a comparar valores por referencia (o sea, valores que no son primitivos).\n\n### Igualdad por referencia\n\nComo vimos en el ejemplo anterior, los primitivos se comparan por su valor. Sin embargo, si usas el triple igual con valores por referencia, lo que se compara son las referencias (es decir, las ubicaciones en memoria).\n\n```javascript\n{} === {} // false. Mismo tipo, valor similar, diferente referencia. ❌\n[] === [] // false. Mismo tipo, valor similar, diferente referencia. ❌\n{ age: 1 } === { age: 1 } // false. Mismo tipo, valor similar, diferente referencia. ❌\n```\n\nAunque cada uno de los ejemplos anteriores tiene el mismo tipo y lo que parece ser el mismo valor, como son valores por referencia, JavaScript compara las referencias en memoria, no el valor en sí.\nEn todos los casos, las referencias (o ubicaciones en memoria) son distintas, por eso siempre obtenemos `false`.\n\nPodemos ver esto más claramente si asignamos dos variables a la misma referencia en memoria y luego usamos el operador de identidad entre ellas.\n\n```javascript\nconst obj1 = {\n dog: \"Rambo\",\n};\nconst obj2 = obj1;\n\nobj1 === obj2; // true. Mismo tipo, valor similar, misma referencia. ✅\n```\n\nEn el ejemplo, tanto `obj1` como `obj2` están haciendo referencia al mismo lugar en memoria, por eso obtenemos `true`.\n\nEn resumen, cuando usas el operador de identidad (`===`), suponiendo que ya entendiste esto de la igualdad por referencia, todo funciona como esperarías.\n\nAquí tienes una tabla de igualdad triple igual para que parezca que todo en JavaScript tiene sentido:\n\n![Tabla de igualdad triple igual](../../assets/blog/doble-igual-vs-triple-igual-en-javascript/triple-equal.png)\n\n---\n\n## El operador de igualdad abstracta (`==`)\n\nLo más probable es que el operador de igualdad (doble igual, `==`) no se comporte como esperas, a diferencia del operador de identidad (triple igual, `===`).\n\nAquí tienes solo algunos ejemplos para que empieces a desconfiar de todo:\n\n```javascript\n\"1\" == 1; // true\ntrue == 0; // true\nnull == undefined; // true\n0 == \"\"; // true\n\"0\" == false; // true\n[1] == true; // true\n```\n\n**¿Qué? ¿Por qué? ¿Cómo? ¿Por qué JavaScript es tan raro?** 🤔\n\nFíjate que cada comparación se hace entre tipos diferentes.\nComo vimos antes con el operador de identidad (`===`), todas estas comparaciones devolverían `false`, ya que los tipos no coinciden.\n\nSin embargo, el operador `==` (doble igual) tiene sus propias ideas sobre cómo deberían funcionar las cosas: ignora el sentido común y realiza una conversión de tipo (_type coercion_) antes de comparar.\n\nEsto puede dar lugar a resultados inesperados, especialmente si no entiendes bien cómo y cuándo hace esa conversión.\n\nPor lo tanto, en el ejemplo anterior (\"1\" == 1) el motor de JavaScript convierte la cadena `\"1\"` al número `1`, lo que luego se evalúa como `1 == 1`, y eso da `true`. Lo mismo pasa si uno es booleano, convierte el booleano a número (true = 1, false = 0).\n\nEs esa etapa de coerción de tipos la que hace que el operador de igualdad (`==`) sea tan impredecible como tus decisiones de UX.\n\nAquí tienes la misma tabla de igualdad que vimos antes, pero ahora bajo el operador de igualdad (`==`):\n\n![Tabla de igualdad doble igual](../../assets/blog/doble-igual-vs-triple-igual-en-javascript/doble-equal.png)\n\n## Conclusión\n\nEn el universo de JavaScript, donde todo puede ser un número, una cadena o una mentira disfrazada de `true`, hay dos caminos: el del doble igual (`==`) y el del triple igual (`===`).\n\nSi valoras tu tiempo y el respeto de tus compañeros de equipo, usa siempre el triple igual (`===`).\n\n¿Y tú? ¿Qué operador prefieres usar en tu código? ¿Tienes algún caso de uso específico donde prefieras usar `==`? ¡Déjame tu opinión en los comentarios! 👇\n","collection":"blog","data":{"title":"Doble igual (==) vs triple igual (===) en JavaScript","description":"¿Usas == y === como si fueran lo mismo? ¡Alto ahí, developer! ⚠️ Aprende la diferencia entre el operador de igualdad y el operador de identidad en JavaScript.","pubDate":"2025-04-16T00:00:00.000Z","published":true,"tags":["JavaScript","Fundamentals"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Doble%20igual%20(%3D%3D)%20vs%20triple%20igual%20(%3D%3D%3D)%20en%20JavaScript&tags=JavaScript,Fundamentals"}},{"id":"rip-styled-components-2016-2025.md","slug":"rip-styled-components-2016-2025","body":"\n**Styled-components**, esa pequeña gran herramienta que alguna vez se sintió como magia en React, ha sido oficialmente enviada al _modo maintenance_ (el 17 de marzo de 2025).\n\nFin del soporte. No del todo inesperado. Algunos lo usaron, otros lo amaron. Yo solo lo toleré.\n\nSin anuncios rimbombantes ni despedidas grandilocuentes. Solo una [nota](https://opencollective.com/styled-components/updates/thank-you) y la desaparición del botón de donaciones.\n\n## ¿Por qué murió?\n\n- React cambió las reglas del juego y dejó a styled-components sin terreno donde jugar.\n- La moda `CSS-in-JS` se fue con la misma velocidad con la que llegó. Tailwind, PostCSS y los CSS modules dijeron \"hola\" con gran acogida.\n- El maintainer principal (Evan Jacobs) lleva años sin usarlo en producción: sin uso activo, no hay contexto real, ni urgencia, ni ganas. Y eso se nota.\n\nNo hay odio aquí. Tal vez fue útil en su momento, pero ese momento ya pasó.\n\n## La verdad\n\nSinceramente, nunca me convenció. Siempre me pareció un poco forzado, una solución elegante a un problema creado por el propio ecosistema.\n\n```javascript\nconst FancyButton = styled.button`\n background-color: ${(props) => (props.primary ? \"blue\" : \"red\")};\n color: white;\n padding: 10px 20px;\n border-radius: 5px;\n`;\n```\n\n```jsx\nClick me\n```\n\n✨ Eso sí, fue el uso más creativo de las `template literals` que existió en el momento. Convirtieron un simple `string` multi-línea en un pequeño motor de estilos dinámicos, donde podías interpolar props, condiciones y CSS (y estaba lleno de ternarios).\n\n## Cuando mantener deja de tener sentido\n\nPor otro lado, pobre _quantizor_. Mantener un proyecto open source grande, con miles de usuarios y expectativas constantes, sin usarlo ya en tu día a día... es una receta para el agotamiento.\n\nLo sorprendente no es que haya entrado en maintenance mode, lo sorprendente es que haya aguantado tanto. Hacer esto sin motivación ni contexto real de uso es simplemente abrumador.\n\n### RIP styled-components\n\nDescansa tranquilo en `node_modules`. Te lo mereces (creo).\n\n## ¿Y ahora qué?\n\nSi vas a empezar un proyecto nuevo, ni se te ocurra considerar styled-components. No está dormido, está fuera de combate.\n\nY si ya lo tienes en tu proyecto... es hora de ir planeando esa migración que llevas postergando desde 2017.\n","collection":"blog","data":{"title":"RIP styled-components: 2016–2025 💅","description":"Una despedida breve para una herramienta que nunca terminó de convencerme. No habrá más features y tampoco lágrimas.","pubDate":"2025-04-14T00:00:00.000Z","published":true,"tags":["JavaScript","Tools"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=RIP%20styled-components%3A%202016%E2%80%932025%20%F0%9F%92%85&tags=JavaScript,Tools"}},{"id":"personaliza-como-se-ven-los-objetos-en-las-devtools.md","slug":"personaliza-como-se-ven-los-objetos-en-las-devtools","body":"\nLos objetos aparecen en muchos lugares en las **Developer Tools**. Más comúnmente en la herramienta **Console**, pero también aparecen cuando estás en modo detective dentro de **Sources** (o Debugger) cuando depuras código JavaScript.\n\nLas DevTools de cada navegador son las que deciden cómo aparecen estos objetos en la interfaz de usuario. Por ejemplo, las cadenas de texto y los números tienen diferentes colores, los arrays tienen una pequeña vista previa de los elementos y un icono que te permite expandirlos para ver la lista completa de elementos, etc.\n\nVeamos algunos ejemplos de cómo se ven diferentes tipos de datos en la consola:\n\n![Ejemplo de cómo se ven diferentes tipos de datos en la consola](../../assets/blog/personaliza-como-se-ven-los-objetos-en-las-devtools/console.png)\n\nPero... ¿y si tú quieres algo más? Algo que diga: \"_este objeto es el MVP de mi aplicación_\"\n![Ejemplo de cómo se ven diferentes tipos de datos en la consola](../../assets/blog/personaliza-como-se-ven-los-objetos-en-las-devtools/mvp.png)\n\nBienvenido a los `Custom Object Formatters`, una función no tan conocida que te deja customizar cómo se muestran tus objetos en las DevTools. Puedes hacer que tus objetos aparezcan con estilos personalizados, colores, e incluso con emojis.\n\nPara poder hacer esto, primero necesitas activar el soporte para esta característica en el navegador.\n\n![Activar soporte para Custom Object Formatters en Chrome](../../assets/blog/personaliza-como-se-ven-los-objetos-en-las-devtools/settings.png)\n\n## ¿Cómo se hace la magia?\n\nLos `Custom Object Formatters` no es algo que configures en las DevTools. DevTools no tiene un panel de \"personalización de objetos\". En lugar de eso, tú defines el formato en el código de tu página, y DevTools lo detecta automáticamente.\n\n### El formato base tiene tres propiedades\n\n```javascript\n{\n header: function(obj) { /* Vista previa del objeto */ },\n hasBody: function(obj) { /* ¿Tiene más info para expandir? */ },\n body: function(obj) { /* Lo que se ve al expandirlo */ }\n}\n```\n\nTodo esto se basa en `JsonML` (una forma muy extraña de escribir HTML en arrays). [Link](http://www.jsonml.org/).\n\n### ¿Qué hace cada una?\n\n- `header`: Devuelve una vista previa del objeto, en formato `JsonML`.\n- `hasBody`: Devuelve un booleano que indica a DevTools si el objeto se puede expandir para mostrar más información.\n- `body`: Devuelve la vista previa del objeto cuando está expandido, también en formato `JsonML`.\n\n## Ejemplo práctico\n\nDigamos que tienes una clase `UserBadge` que representa a un usuario con su nombre y nivel:\n\n```javascript\nclass UserBadge {\n constructor(name, level) {\n this.name = name;\n this.level = level;\n }\n}\n```\n\nY quieres crear un nuevo usuario:\n\n```javascript\nconst admin = new UserBadge(\"Baumannzone\", \"Admin\");\n```\n\nSi lo imprimimos en la consola, se verá así _(de triste)_:\n\n![Ejemplo de cómo se ven diferentes tipos de datos en la consola](../../assets/blog/personaliza-como-se-ven-los-objetos-en-las-devtools/no-format.png)\n\nAhora quieres que al hacer `console.log(admin)` en las DevTools, no salga esa cosa gris y roja deprimente, sino algo que tenga estilo. Entonces haces tu custom formatter:\n\n```javascript\nconst userBadgeFormatter = {\n header: function (object) {\n if (!(object instanceof UserBadge)) return null;\n\n return [\n \"div\",\n {\n style: `\n background-color: #f0f0f0;\n color: #333;\n border-left: 4px solid ${\n object.level === \"Admin\" ? \"#7c3aed\" : \"#ffeb00\"\n };\n padding: 0.25rem 0.5rem;\n font-weight: bold;\n font-family: sans-serif;\n `,\n },\n `${object.level === \"Admin\" ? \"👑\" : \"👤\"} ${object.name} (${\n object.level\n })`,\n ];\n },\n\n hasBody: function (object) {\n return object instanceof UserBadge;\n },\n\n body: function (object) {\n return [\n \"div\",\n {\n style:\n \"margin-top: 0.5rem; font-family: sans-serif; font-size: 0.9rem;\",\n },\n [\n \"div\",\n {},\n [\"span\", { style: \"font-weight: bold; color: #333;\" }, \"Nombre: \"],\n [\"span\", {}, object.name],\n ],\n [\n \"div\",\n {},\n [\"span\", { style: \"font-weight: bold; color: #333;\" }, \"Nivel: \"],\n [\"span\", {}, object.level],\n ],\n [\n \"div\",\n { style: \"margin-top: 0.5rem;\" },\n [\n \"span\",\n { style: \"opacity: 0.9;\" },\n \"🚀 Mira este log. Bien chido. Copado. Estéticamente inmejorable.\",\n ],\n ],\n ];\n },\n};\n```\n\nAñade tu objeto formateador al array global `window.devtoolsFormatters`:\n\n```javascript\nwindow.devtoolsFormatters = [userBadgeFormatter];\n```\n\nEso es todo, no necesitas hacer nada más. Ahora, cada vez que los objetos `UserBadge` se muestren en las DevTools (por ejemplo, cuando uses `console.log(object)`), se mostrarán usando el formateador personalizado que has definido.\n\n## Resultado\n\nEn esta imagen puedes ver el resultado de usar el formateador personalizado, primero sin expandir el objeto y luego expandido:\n\n![Resultado de usar el formateador personalizado](../../assets/blog/personaliza-como-se-ven-los-objetos-en-las-devtools/log-1.png)\n![Resultado de usar el formateador personalizado](../../assets/blog/personaliza-como-se-ven-los-objetos-en-las-devtools/log-2.png)\n\n## Conclusión\n\nPersonalizar cómo se muestran tus objetos en las DevTools no va a resolver todos tus bugs, pero al menos lo harás con algo de dignidad visual.\n\nLos **Custom Object Formatters** no son solo una curiosidad, son una herramienta para mejorar tu productividad, tu comprensión de la aplicación, y por qué no, tu autoestima como developer.\n","collection":"blog","data":{"title":"Personaliza cómo se ven los objetos en las DevTools","description":"Aprende a usar Custom Object Formatters para hacer que tus objetos en la consola de DevTools se vean más bonitos, útiles y fáciles de entender.","pubDate":"2025-04-07T00:00:00.000Z","published":true,"tags":["DevTools","JavaScript","TIL"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Personaliza%20c%C3%B3mo%20se%20ven%20los%20objetos%20en%20las%20DevTools&tags=DevTools,JavaScript,TIL"}},{"id":"una-decada-con-javascript-y-no-sabia-esto-sobre-los-bucles.md","slug":"una-decada-con-javascript-y-no-sabia-esto-sobre-los-bucles","body":"\nLas etiquetas en JavaScript son identificadores seguidos de dos puntos (`:`) que se pueden asociar a bucles o bloques de código.\n\n## TL;DR\n\n![TL;DR](../../assets/blog/una-decada-con-javascript-y-no-sabia-esto-sobre-los-bucles/code.png)\n\nSu principal función es proporcionar un punto de referencia para las instrucciones `break` y `continue`, permitiendo un control más preciso sobre el flujo de ejecución en estructuras anidadas.\n\n## Ejemplo con bucles anidados\n\nEn JavaScript, las etiquetas (`label`) son especialmente útiles en bucles anidados cuando quieres controlar exactamente desde qué nivel quieres salir (`break`) o continuar (`continue`). Aquí tienes un ejemplo claro:\n\n```javascript\nexterno: for (let i = 1; i <= 3; i++) {\n interno: for (let j = 1; j <= 3; j++) {\n if (i * j > 5) {\n break externo; // => Sale completamente de ambos bucles\n }\n console.log(`${i} x ${j} = ${i * j}`);\n }\n}\n```\n\nEn este ejemplo, la etiqueta `externo` permite salir de ambos bucles cuando la multiplicación de `i` y `j` supera el valor `5`. Sin la etiqueta, solo abandonaría el bucle `interno`.\n\n## Ejemplo con bloques de código\n\nTambién funcionan con bloques de código (pero no lo hagas):\n\n```javascript\n// Esto no es una variable, ni una función, ni tu salvación.\n// Es una etiqueta.\nbloque: {\n console.log(\"Inicio del bloque\");\n if (true) {\n break bloque; // => Sale del bloque\n }\n console.log(\"Este mensaje no se mostrará nunca\");\n}\n```\n\nSí, has leído bien. Puedes ponerle un `label` a un bloque de código y romperlo con `break`. Técnicamente es válido, pero la legibilidad empeora bastante.\n\nEste mecanismo recuerda inevitablemente a estructuras de control antiguas, como el famoso `GOTO` de **BASIC**:\n\n```basic\n10 INPUT \"Introduce un número\"; N\n20 IF N < 10 THEN GOTO 10\n30 PRINT \"Has introducido un número mayor o igual a 10\"\n```\n\n![Resultado del ejemplo de BASIC ejecutado en un emulador](../../assets/blog/una-decada-con-javascript-y-no-sabia-esto-sobre-los-bucles/image.png)\n\n
    Resultado del ejemplo de BASIC ejecutado en un emulador.\n\nEsto funcionaba perfectamente en BASIC por la naturaleza del lenguaje, pero hacerlo hoy en JavaScript sería volver absurdamente 30 años atrás.\n\n## ¿Por qué no usar etiquetas?\n\nAunque es posible y legal usar etiquetas en JavaScript, jamás me he encontrado con la necesidad de usarlas y espero seguir así.\n\nPara eso existen los `if`, `else`, `switch` y otras estructuras de control que son mucho más legibles y mantenibles.\n\n## Conclusión\n\nSí, JavaScript tiene su propia versión ligera del _GOTO_: las **sentencias etiquetadas** o labeled statements.\n\n¿Las necesitas? Lo más probable es que no. ¿Vas a usarlas? Espero que tampoco. ¿Mola saber que existen? Sin duda 🤘.\n\nEs una de esas features que te hacen levantar una ceja, sonreír y pensar: \"_vale, JavaScript... me encanta tu caos_\".\n\n![Vegeta disfrutando del caos de JavaScript](../../assets/blog/una-decada-con-javascript-y-no-sabia-esto-sobre-los-bucles/vegeta.png)\n\n**Recuerda**: úsalas solo si puedes dormir tranquilo sabiendo que alguien tendrá que mantener ese código después. Puede que seas tú.\n","collection":"blog","data":{"title":"Una década con JavaScript y no sabía esto sobre los bucles","description":"Aprende a usar break y continue de manera más efectiva con Vegeta 😏. Descubre cómo las etiquetas (labels) te permiten mejorar el flujo de tus bucles en JavaScript.","pubDate":"2025-04-03T00:00:00.000Z","published":true,"tags":["JavaScript","TIL"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Una%20d%C3%A9cada%20con%20JavaScript%20y%20no%20sab%C3%ADa%20esto%20sobre%20los%20bucles&tags=JavaScript,TIL"}},{"id":"20-mejores-fuentes-para-videojuegos-en-2025.md","slug":"20-mejores-fuentes-para-videojuegos-en-2025","body":"\nElegir la fuente o tipografía adecuada en un videojuego es super importante para definir su estética y mejorar la experiencia del jugador.\n\nEn este artículo, encontrarás 20 fuentes épicas, desde estilos retro pixelados hasta diseños futuristas, que harán que tu juego o tu aplicación luzca increíble.\n\n## 1. Gore\n\n![Gore Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/gore.jpg)\n\nTipografía para juegos oscuros y de terror, con letras gruesas sin curvas. \nhttps://www.tugcu.co/fonts/p/gore\n\n## 2. CageWorld\n\n![CageWorld Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/cageworld.jpg)\n\nFuente vintage artesanal ideal para logotipos, etiquetas, camisetas, empaques, invitaciones y diseños clásicos. \nhttps://ifonts.xyz/cageworld-font.html\n\n## 3. Caveman\n\n![Caveman Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/caveman.png)\n\nDiseñada para parecer tallada en piedra, perfecta para juegos de supervivencia y aventuras prehistóricas. \nhttps://elements.envato.com/caveman-gaming-font-W3R2EAM\n\n## 4. Dankosaurus\n\n![Dankosaurus Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/dankosaurus.avif)\n\nTipografía inspirada en dinosaurios para juegos infantiles, disponible en estilos _regular_ y _redondeado_. \nhttps://www.1001fonts.com/dankosaurus-font.html\n\n## 5. Fun Blob\n\n![Fun Blob Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/fun-blob.avif)\n\nTipografía divertida y juguetona, ideal para juegos infantiles y diseños creativos. \nhttps://www.dafont.com/fun-blob.font\n\n## 6. Game Over Brush SVG Font\n\n![Game Over Brush Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/gameover-brush.webp)\n\nFuente tipo pincel, ideal para juegos de terror y proyectos artísticos. \nhttps://www.youworkforthem.com/font/T19474/game-over-brush-svg\n\n## 7. Arcadia\n\n![Arcadia Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/arcadia-font.jpg)\n\nTipografía moderna de ciencia ficción con diseño deportivo para logos de esports.\n\nhttps://www.creativefabrica.com/es/product/arcadia/\n\n## 8. Grind Demolished\n\n![Grind Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/grind.png)\n\nGrind es un tipo de letra grande y atrevida que transmite fuerza y dureza. \nhttps://elements.envato.com/grind-demolished-Q6W5BGA\n\n## 9. GUMDROP\n\n![GUMDROP Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/gumdrop.png)\n\nTipografía divertida y juguetona, ideal para juegos infantiles y diseños creativos. \nhttps://justtheskills.com/product/gaming-font-gumdrop/\n\n## 10. Hermes\n\n![Hermes Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/hermes.webp)\n\nTipografía moderna. Estilo Cyberpunk que combina estilo retro y futurista. \nhttps://befonts.com/hermes-typeface.html\n\n## 11. Monstarize\n\n![Monstarize Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/monstarize.jpg)\n\nTipografía de terror con letras que parecen gotear. \nhttps://www.dafont.com/monstarize.font\n\n## 12. Nordic Light\n\n![Nordic Light Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/nordic-light.jpg)\n\nFuente moderna con mezcla de esquinas cuadradas, ideal para títulos o posters. \nhttps://fontesk.com/nordic-light-font/\n\n## 13. Pixel Rand\n\n![Pixel Rand Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/pixel-rand.webp)\n\nPíxeles en posiciones aleatorias: estilo moderno perfecto para videojuegos pixelados, videos y proyectos retro. \nhttps://elements.envato.com/pixel-rand-B3AFEYM\n\n## 14. River Adventurer\n\n![River Adventurer Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/river-adventurer.avif)\n\nFuente sans-serif en mayúsculas que evoca aventuras en la jungla. \nhttps://www.1001fonts.com/river-adventurer-font.html\n\n## 15. Rockgan Space Game\n\n![Rockgan Space Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/rockgan.png)\n\nFuente espacial con diseño juguetón para juegos móviles temáticos. \nhttps://elements.envato.com/rockgan-space-game-display-font-HQ558Y6\n\n## 16. Royal Kingdom\n\n![Royal Kingdom Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/royal-kingdom.webp)\n\nFuente estilizada tipo cartoon, perfecta para interfaces de juegos y productos de merchandising. \nhttps://fontbundles.net/sensatype/2533167-royal-kingdom-cartoon-game-font\n\n## 17. Scrubland\n\n![Scrubland Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/scrubland.jpg)\nTipografía moderna con un toque de naturaleza, ideal para juegos de aventura y exploración. \nhttps://fontesk.com/scrubland-font/\n\n## 18. Victorius\n\n![Victorius Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/victorius.jpg)\n\nDiseño inspirado en textos griegos antiguos, ideal para juegos de gladiadores. \nhttps://fontesk.com/victorious-font/\n\n## 19. Tsuki\n\n![Tsuki Fuente](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/tsuki.png)\nTsuki es una fuente sans-serif inspirada en el concepto y tema de los mangas y videojuegos japoneses. \nhttps://www.creativefabrica.com/product/tsuki/\n\n## 20. Guava Candy\n\n![Guava Candy Fuente para Videojuegos](../../assets/blog/20-mejores-fuentes-para-videojuegos-en-2025/guava.webp)\n\nGuava Candy es una fuente en mayúsculas que inspira una sensación de diversión y felicidad. \nhttps://www.1001fonts.com/guava-candy-font.html\n\n---\n\nElegir la fuente adecuada puede marcar la diferencia en la experiencia del jugador. Las fuentes mencionadas son solo algunas de las muchas opciones disponibles, pero cada una tiene su propio estilo y personalidad.\n\nRecuerda que la tipografía es una parte fundamental del diseño de videojuegos y puede influir en la percepción del jugador sobre el juego. Así que elige sabiamente y diviértete creando tu próximo proyecto.\n\n¿Cuál es tu fuente favorita? ¿Cuál de estas te gusta más? Si tienes alguna tipografía gaming favorita que falta en esta lista, ¡deja un comentario! Me encantaría saber qué piensas y qué fuentes utilizas en tus proyectos de videojuegos.\n","collection":"blog","data":{"title":"Las 20 mejores fuentes para videojuegos en 2025","description":"Descubre las 20 fuentes más épicas para videojuegos en 2025. Desde estilos retro pixelados hasta tipografías futuristas, estas fuentes llevarán tu diseño al siguiente nivel.","pubDate":"2025-03-29T00:00:00.000Z","published":true,"tags":["UX/UI","Design"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Las%2020%20mejores%20fuentes%20para%20videojuegos%20en%202025&tags=UX/UI,Design"}},{"id":"como-obtener-la-url-actual-con-javascript-y-sacarle-provecho.md","slug":"como-obtener-la-url-actual-con-javascript-y-sacarle-provecho","body":"\nCuando estás construyendo una app frontend, ya sea con React, Vue, o vanilla JS, es bastante común necesitar acceder a la URL actual. Quizás para:\n\n- **Leer parámetros** (`?id=123`)\n- **Validar rutas** (`/user` vs `/admin`)\n- **Detectar entornos** (_local_ vs _producción_)\n- **Navegar programáticamente** (sin ``)\n\n## TL;DR\n\n```js\nconst url = window.location.href;\nconsole.log(url);\n\n// https://www.baumannzone.dev/blog/como-obtener-la-url-actual-con-javascript-y-sacarle-provecho\n```\n\n## Desglose: todas las partes de la URL\n\nSupongamos que estás en esta URL:\n\n```\nhttps://www.baumannzone.dev:8080/blog/post?tag=js#comments\n```\n\nPuedes extraer sus partes así:\n\n```js\nconst {\n host, // \"www.baumannzone.dev:8080\"\n hostname, // \"www.baumannzone.dev\"\n href, // (URL completa)\n origin, // \"https://www.baumannzone.dev:8080\"\n pathname, // \"/blog/post\"\n port, // \"8080\"\n protocol, // \"https:\"\n search // \"?tag=js\"\n hash, // \"#comments\"\n} = window.location;\n```\n\n⚠️ **Ojo**: `host` incluye el puerto, `hostname` no. ¡Detalles como este pueden causar bugs!\n\n![Cómo obtener la URL actual con JavaScript en imagen](../../assets/blog/como-obtener-la-url-actual-con-javascript-y-sacarle-provecho/main.png)\n\n## Ejemplos útiles y reales\n\nDada esta URL, `https://www.baumannzone.dev:8080/blog/post?tag=js#comments`, aquí van algunos ejemplos:\n\n1. Obtener un parámetro de búsqueda\n\n```js\nconst params = new URLSearchParams(window.location.search);\nconst tag = params.get(\"tag\");\n\nconsole.log(tag); // => \"js\"\n```\n\n### Pro Tip\n\n```js\n// Obtener un parámetro\nconst urlParams = new URLSearchParams(window.location.search);\nconst id = urlParams.get(\"id\"); // => Devuelve `null` si no existe\n\n// Comprobar si el parámetro existe\nconst hasId = urlParams.has(\"id\"); // => Devuelve `true` o `false`\n```\n\n2. Redirigir a otro dominio\n\n```js\nif (window.location.hostname !== \"www.baumannzone.dev\") {\n window.location.href = \"https://www.baumannzone.dev\";\n}\n\n// 🛡️ Por seguridad, siempre sanitiza\nconst safeRedirect = (path) => {\n const allowedPaths = [\"/home\", \"/blog\"];\n if (allowedPaths.includes(path)) {\n window.location.href = path;\n }\n};\n```\n\n3. Navegar a otra ruta\n\n```js\nwindow.location.href = \"/uses\";\n// redirige a https://www.baumannzone.dev/uses\n```\n\n4. Detectar si estás en localhost\n\n```js\nconst isLocalhost =\n window.location.hostname === \"localhost\" ||\n window.location.hostname === \"127.0.0.1\";\n```\n\n5. Construir y modificar una URL\n\n```js\nconst url = new URL(window.location.href);\n\nurl.pathname = \"/patrocinio\";\nurl.searchParams.set(\"from\", \"blog\");\n\nconsole.log(url.toString());\n// => https://www.baumannzone.dev/patrocinio?from=blog\n```\n\n### Extra para frameworks modernos:\n\n- En React puedes usar `useLocation()` de React Router\n- En Vue puedes usar `useRoute()` de Vue Router\n- Recuerda, `window.location` funciona siempre en todos\n\n## Conclusión\n\n`window.location` es una de esas APIs nativas que suelen pasarse por alto, pero resuelve muchos casos comunes en apps web:\n\n- Obtener la URL actual\n- Leer parámetros\n- Detectar el entorno\n- Navegar dinámicamente\n- Generar URLs desde cero\n\nSin dependencias, sin magia. Solo JavaScript.\n\n---\n\n¿Qué otro método nativo de JavaScript te gustaría que explique? Deja un comentario y lo agregaré a la lista. 👇\n","collection":"blog","data":{"title":"Cómo obtener la URL actual con JavaScript (y sacarle provecho)","description":"Aprende a usar window.location para leer, descomponer y manipular URLs en el navegador sin dependencias externas.","pubDate":"2025-03-25T00:00:00.000Z","published":true,"tags":["JavaScript"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=C%C3%B3mo%20obtener%20la%20URL%20actual%20con%20JavaScript%20(y%20sacarle%20provecho)&tags=JavaScript"}},{"id":"que-es-la-funcion-round-en-css-redondeo-dinamico-en-css.md","slug":"que-es-la-funcion-round-en-css-redondeo-dinamico-en-css","body":"\nDesde mayo de 2024, podemos utilizar la función `round()` para redondear valores en CSS. Esta función se une a otras funciones matemáticas como `calc()` o `min()`, permitiendo cálculos más precisos sin hacks de JavaScript.\n\n## Sintaxis\n\n```css\nwidth: round(120px, var(--rounding-interval));\n```\n\n## Cómo funciona la función round() en CSS\n\nLa función `round()` permite redondear un número al múltiplo más cercano de un valor específico. Se compone de 3 parámetros:\n\n- **Estrategia de redondeo** (opcional): Puede ser `nearest` (por defecto), `up`, `down` o `to-zero`.\n- **Valor a redondear**: Puede ser una variable CSS, un valor numérico o el resultado de otra operación matemática.\n- **Múltiplo al que redondear**: Define el valor base al que se ajustará el resultado.\n\n## Ejemplos de uso de la función round() en CSS\n\n```css\n--customProp: 123;\n\n/* Redondea al múltiplo más cercano de 50px */\nwidth: round(var(--customProp), 50px); /* ==> 150px */\n\n/* Redondea hacia abajo al múltiplo de 50px más cercano */\nwidth: round(down, var(--customProp), 50px); /* ==> 100px */\n\n/* Redondea hacia arriba */\nwidth: round(up, var(--customProp), 50px); /* ==> 150px */\n\n/* Redondea acercándose a cero */\nwidth: round(to-zero, var(--customProp), 50px); /* ==> 100px */\n```\n\n## Estrategias de redondeo explicadas\n\nEn esta tabla puedes ver los resultados de ejecutar `round(strategy, 123, 50px)` con diferentes estrategias de redondeo:\n\n| Estrategia | Descripción | Ejemplo |\n| :------------------------ | :------------------------------- | :------ |\n| `nearest` _(por defecto)_ | Redondea al múltiplo más cercano | `150px` |\n| `up` | Siempre redondea hacia arriba | `150px` |\n| `down` | Siempre redondea hacia abajo | `100px` |\n| `to-zero` | Redondea acercándose a cero | `100px` |\n\n`to-zero` es interesante porque, a diferencia de `down`, también afecta a valores negativos.\n\nEjemplo:\n\n```css\nwidth: round(to-zero, -123px, 50px); /* ==> -100px */\n```\n\n## Compatibilidad\n\nLa función `round()` es parte del estándar CSS [Values and Units Level 4](https://www.w3.org/TR/css-values-4/) y es compatible con la mayoría de los navegadores modernos desde mayo de 2024.\n\n## ¿Por qué usar round() en CSS?\n\n- **Precisión**: Permite cálculos más precisos y consistentes en el diseño.\n- **Menos dependencia de JavaScript**: Se puede hacer redondeo directamente en CSS.\n- **Compatibilidad creciente**: Soporte en navegadores modernos sin necesidad de hacks.\n- **Manejo de intervalos personalizados**: Puedes definir intervalos de redondeo personalizados (`20px` o `13%`), lo que te permite ajustar el redondeo según el contexto.\n- **Simplificación del código**: round() evita cálculos manuales o combinaciones de calc() y condicionales, haciendo tu código más limpio y mantenible.\n\n## Cuándo round() es realmente útil en CSS\n\nSi usas `round()` con un número fijo (por ejemplo, `round(123px, 50px)`), entonces podrías simplemente escribir `150px` directamente en tu CSS. La verdadera utilidad de `round()` está en los valores dinámicos, como:\n\n1. Variables CSS\n\n```css\n--dynamic-width: 127px;\nwidth: round(var(--dynamic-width), 50px); /* Se adapta dinámicamente */\n```\n\n2. Resultados de `calc()`\n\n```css\nwidth: round(calc(100% / 3), 10px); /* Redondea el resultado de una división */\n```\n\n3. Ajuste dinámico con `clamp()`\n\n```css\nwidth: round(clamp(120px, 50vw, 300px), 25px);\n```\n\n4. Diseños responsive (evitando píxeles fraccionados)\n\n```css\nfont-size: round(1.3rem, 0.25rem);\n```\n\n5. Redondeo en valores negativos con `to-zero`\n\n```css\nwidth: round(to-zero, -137px, 50px); /* ==> -100px */\n```\n\n### ✍️ TL;DR:\n\n- Si el valor es estático, redondéalo manualmente.\n- Si el valor es dinámico (variables, `calc()`, `clamp()`), `round()` ayuda a mantener el código limpio y predecible.\n\n---\n\n🚀 Ahora que ya conoces `round()`, ¿cómo lo aplicarías en tu CSS? Deja tu comentario abajo 👇.\n","collection":"blog","data":{"title":"Qué es la función round() en CSS: redondeo dinámico","description":"Descubre qué es y cómo utilizar la función round() en CSS para manejar valores de manera dinámica. Aprende a redondear hacia arriba, hacia abajo (o hacia cero). ¡Potencia tu CSS con esta nueva función matemática!","pubDate":"2025-02-12T00:00:00.000Z","published":true,"tags":["CSS"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Qu%C3%A9%20es%20la%20funci%C3%B3n%20round()%20en%20CSS%3A%20redondeo%20din%C3%A1mico&tags=CSS"}},{"id":"creando-un-clon-de-hacker-news-con-alpinejs-y-tailwind-css.md","slug":"creando-un-clon-de-hacker-news-con-alpinejs-y-tailwind-css","body":"\nEn este artículo, te contaré cómo creé un clon de **Hacker News** utilizando **Alpine.js** y **Tailwind CSS**. ¡Vamos a ello!\n\n## Introducción\n\nHace unos meses decidí crear un clon de Hacker News, la famosa plataforma de noticias y discusión sobre tecnología. Mi objetivo era hacerlo simple, minimalista y funcional, utilizando herramientas modernas pero ligeras. Para ello, elegí dos tecnologías que me encantan: Alpine.js y Tailwind CSS.\n\n## ¿Qué es Hacker News?\n\nHacker News es una página web de noticias y discusión de tecnología. Fue creada por Paul Graham en 2007 y es una de las páginas web más populares de la red. En ella se publican noticias sobre tecnología, programación, ciencia, etc. y se pueden comentar y votar.\n\n🔗 https://news.ycombinator.com/\n\n![Hacker News](../../assets/blog/creando-un-clon-de-hacker-news-con-alpinejs-y-tailwind-css/hn.png)\n\n## Alpine.js\n\nAlpine.js es un framework JavaScript ligero y de bajo nivel que te permite crear componentes reactivos sin necesidad de escribir código JavaScript. Es una alternativa a frameworks como React, Vue o Angular.\n\nSu principal ventaja es que es muy fácil de aprender y de utilizar. Su sintaxis es muy similar a la de Vue.js o Angular, por lo que si ya conoces alguno de estos frameworks, aprenderás Alpine.js en muy poco tiempo.\n\n🔗 https://alpinejs.dev/\n\n![Alpine.js](../../assets/blog/creando-un-clon-de-hacker-news-con-alpinejs-y-tailwind-css/alpine.png)\n\n## Tailwind CSS\n\nTailwind CSS es un framework de CSS _utility-first_ que te permite construir interfaces directamente en tu HTML, solo con clases de CSS. Con Tailwind, puedes crear diseños complejos sin escribir CSS personalizado, lo que acelera mucho el desarrollo.\n\n🔗 https://tailwindcss.com/\n\n## El proyecto: Un clon de Hacker News\n\nEl proyecto está alojado en GitHub y es completamente open source. Puedes ver el código aquí: [baumannzone/hacker-news-alpine](https://github.com/baumannzone/hacker-news-alpine).\n\n![Hacker News Clone](../../assets/blog/creando-un-clon-de-hacker-news-con-alpinejs-y-tailwind-css/hn-clone.png)\n\nEn este proyecto, estoy utilizando una **API real** para obtener los datos de Hacker News. Aunque no es la API oficial (es demasiado compleja para este proyecto), la que estoy usando es una alternativa más sencilla y práctica: la API proporcionada por [tastejs/hacker-news-pwas](https://github.com/tastejs/hacker-news-pwas/blob/master/docs/api.md). Esta API es fácil de integrar y ofrece toda la funcionalidad necesaria para mostrar las noticias más populares y sus detalles.\n\n### Características principales\n\n- Interfaz minimalista y moderna: El sitio web original de Hacker News se ve bastante anticuado, así que decidí darle un toque más moderno y minimalista.\n- Responsive: Funciona perfectamente en dispositivos móviles y en desktop.\n- Paginación: Muestra las noticias en páginas de 30 en 30.\n\n### Tecnologías utilizadas\n\n- Alpine.js\n- Tailwind CSS\n- Vercel: Despliegue y [hosting](https://hacker-news-alpine.vercel.app/).\n- [API](https://github.com/tastejs/hacker-news-pwas/blob/master/docs/api.md) no oficial: Para obtener las noticias.\n\n### Cómo funciona\n\nEl proyecto consume la API pública de Hacker News para obtener las noticias más recientes y mostrarlas en una interfaz sencilla. Alpine.js se encarga de manejar el estado y la interactividad, mientras que Tailwind CSS se utiliza para darle estilo a la aplicación.\n\nSi haces clic en una noticia, se abre una nueva ventana con los detalles de la noticia.\nSi haces click en los comentarios, navegas a la página de comentarios de la noticia dentro de la aplicación.\n\n## Conclusión\n\nHacía tiempo que quería crear un clon de Hacker News, ¡y por fin lo hice! ¿Quieres crear algo rápido, minimalista y potente? **Alpine.js** y **Tailwind CSS** son tu combo ganador. Este clon de Hacker News es la prueba: ligero, moderno y funcional en tiempo récord.\n\n¿Te animas a probarlo? Clona el repo [aquí](https://github.com/baumannzone/hacker-news-alpine) o échale un vistazo en vivo [aquí](https://hacker-news-alpine.vercel.app/).\n\n👉 ¿Te gustó? 🤩 ¡Dame una estrellita en GitHub!\n","collection":"blog","data":{"title":"Creando un clon de Hacker News con Alpine.js y Tailwind CSS","description":"Aprende a construir un clon minimalista de Hacker News utilizando Alpine.js y Tailwind CSS. Descubre cómo combinar estas herramientas para crear aplicaciones web modernas y sencillas.","pubDate":"2025-02-11T00:00:00.000Z","published":true,"tags":["CSS","JavaScript"],"author":"Jorge Baumann","type":"blog","ogImage":"https://baumannzone-dev-og.vercel.app/api/og?title=Creando%20un%20clon%20de%20Hacker%20News%20con%20Alpine.js%20y%20Tailwind%20CSS&tags=CSS,JavaScript"}},{"id":"git-tower-el-gui-de-git-mas-potente-para-macos-y-windows.md","slug":"git-tower-el-gui-de-git-mas-potente-para-macos-y-windows","body":"\nUsar Git desde la terminal es algo que deberías dominar si quieres progresar como desarrollador. Sin embargo, si prefieres una interfaz gráfica, [Git Tower](https://www.git-tower.com/?via=baumannzone) es una excelente alternativa.\n\n## ¿Qué es Git Tower?\n\n[![Git Tower](../../assets/blog/git-tower-el-gui-de-git-mas-potente-para-macos-y-windows/logo.png)](https://www.git-tower.com/?via=baumannzone)\n\nGit Tower no es simplemente otro cliente Git con interfaz gráfica. Se trata de una herramienta profesional que revoluciona la manera de trabajar con Git. Llevo años utilizándolo y, gracias a esta experiencia, puedo afirmar que ha transformado mi flujo de trabajo y, sobre todo, mi comprensión de Git.\n\nSí, he aprendido mucho sobre Git gracias a Tower, sigue leyendo y al final te cuento cómo.\n\nDetrás de cada acción que realizamos en cualquier cliente gráfico de Git, existe un comando de Git. Tiene sentido, ¿no?\n\n## Deshacer con `⌘ + Z`\n\nEsta es una de las funcionalidades que más me gustan de Git Tower. La que más uso en mi día a día como desarrollador.\n\n¿Te imaginas deshacer tus cambios en Git con un simple clic? Tower ofrece justo eso y más. Con `⌘ + Z` deshacer acciones recientes con un simple clic o con un atajo de teclado.\n\n- Creas una rama nueva y quieres volver atrás: `⌘ + Z`\n- Haces un commit y te das cuenta de que te has equivocado: `⌘ + Z`\n- Borras un stash por error: `⌘ + Z`\n\n
    \n
    En el video se muestra cómo se crea una rama y con ⌘ + Z se deshace la acción, haciendo que la rama desaparezca. Si luego cambias de opinión y deseas conservar la rama, puedes pulsar Shift + ⌘ + Z para rehacerla.\n\n\nSi después de deshacer una acción te das cuenta de que no era lo que querías hacer, siempre puedes rehacerla con `Shift + ⌘ + Z`. ¡Magia! 🔮\n\n## Arrastra todo en Git Tower con Drag & Drop\n\nUna de las características más irresistibles de [Git Tower](https://www.git-tower.com/?via=baumannzone) es la posibilidad de arrastrar y soltar prácticamente cualquier elemento dentro de la aplicación.\n\n- Quieres hacer un cherry-pick: arrastra y suelta el commit\n- Quieres reordenar tus commits: arrastra y suelta el commit\n- Quieres mover un stash a otra rama: arrastra y suelta el stash\n\n
    ` y el `