# TIL — angelcruz.dev

Aprendizajes breves, gotchas y notas del día a día en desarrollo web. Una entrada por cosa aprendida.

- Versión humana: https://www.angelcruz.dev/lab
- RSS: https://www.angelcruz.dev/til.xml
- 18 entradas, de la más reciente a la más antigua.

---

## IndexNow no acelera la indexación en Google

Es el malentendido del protocolo: se implementa creyendo que avisa a Google, y Google no lo usa. Mueve Bing, Yandex, Seznam y Naver. Para Google el canal sigue siendo el sitemap con su `lastmod` y la inspección de URL en Search Console. Tampoco son 100 URLs al día, otro número que se repite: acepta 10.000 por POST y no publica cuota diaria.

- Fecha: `2026-08-15`
- Tags: SEO, Web Platform
- Enlace: https://www.angelcruz.dev/lab#indexnow-no-sirve-para-google
- Markdown: https://www.angelcruz.dev/lab/indexnow-no-sirve-para-google.md
- Fuente: https://www.indexnow.org/documentation

## La URL que más necesitas reenviar a IndexNow es la que acabas de borrar

Al consolidar dos posts en uno, la que hay que reenviar es la vieja: es la única forma de que el motor la rastree y vea el redirect. Y es justo la que ningún script te va a dar, porque la lista suele derivarse del directorio de contenido y esa carpeta ya no existe. Hay que pasarla a mano. Segunda trampa del mismo día: enviar antes de que el deploy salga hace que el motor revalide y reconfirme la versión vieja.

- Fecha: `2026-08-15`
- Tags: SEO, DevOps
- Enlace: https://www.angelcruz.dev/lab#indexnow-origen-de-un-redirect
- Markdown: https://www.angelcruz.dev/lab/indexnow-origen-de-un-redirect.md

## requestAnimationFrame no dispara en pestañas de fondo

Un aviso que se muestra con `requestAnimationFrame` dentro de un `useEffect` no aparece nunca si la pestaña se abrió en segundo plano: el navegador pausa `rAF` en documentos no visibles y lo reanuda recién cuando los miras. Si el `rAF` solo estaba para diferir un `setState` un tick y evitar el cascading-render, `setTimeout(fn, 0)` hace lo mismo y sí corre sin foco.

- Fecha: `2026-08-04`
- Tags: JavaScript, React, Web Platform
- Enlace: https://www.angelcruz.dev/lab#requestanimationframe-pestanas-de-fondo
- Markdown: https://www.angelcruz.dev/lab/requestanimationframe-pestanas-de-fondo.md
- Fuente: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame

## pnpm 10 en CI ignora en silencio los ajustes de pnpm 11

`allowBuilds` y `minimumReleaseAge` viven solo en `pnpm-workspace.yaml` y solo los lee pnpm 11; el campo `pnpm` de `package.json` ya no sirve para esto. Si el runner sigue en `pnpm/action-setup` con `version: 10` no falla nada: los ignora sin avisar, así que esbuild se queda sin su postinstall y Vitest sin transformador, con un error que no apunta a la causa.

- Fecha: `2026-08-04`
- Tags: pnpm, CI/CD, DevOps
- Enlace: https://www.angelcruz.dev/lab#pnpm-10-ci-ignora-ajustes-de-pnpm-11
- Markdown: https://www.angelcruz.dev/lab/pnpm-10-ci-ignora-ajustes-de-pnpm-11.md

## minimumReleaseAgeExclude de pnpm acumula en vez de reemplazar

pnpm 11 trae `minimumReleaseAge` en 1440 minutos por defecto, así que rechaza cualquier versión publicada hace menos de un día. Al forzar la instalación añade la excepción sola a `minimumReleaseAgeExclude`, pero la acumula sobre la entrada vieja en lugar de sustituirla: queda `next@16.2.12 || 16.3.0` aunque la 16.2.12 ya no se instale. Solo hacen falta mientras la versión está dentro del corte, así que conviene podarlas.

- Fecha: `2026-08-04`
- Tags: pnpm, DevOps
- Enlace: https://www.angelcruz.dev/lab#pnpm-minimumreleaseageexclude-acumula
- Markdown: https://www.angelcruz.dev/lab/pnpm-minimumreleaseageexclude-acumula.md
- Fuente: https://pnpm.io/blog/releases/11.0

## Chrome pinta el anillo de foco de un SVG en :focus, no en :focus-visible

Un `<path tabindex="0">` enfocado con un clic da `:focus` pero no `:focus-visible`, y aun así Chrome le pinta `outline: auto`. Con `<button>`, `<a>` o un `<div tabindex="0">` no pasa. El reset va en `:focus { outline: none }`, no en `:focus-visible`; en Tailwind, la variante `focus:` y no `focus-visible:`.

- Fecha: `2026-08-01`
- Tags: CSS, Accessibility, Web Platform
- Enlace: https://www.angelcruz.dev/lab#chrome-anillo-de-foco-svg-focus-visible
- Markdown: https://www.angelcruz.dev/lab/chrome-anillo-de-foco-svg-focus-visible.md

## new Date() parsea la fecha sin hora como UTC y con hora como local

`new Date('2026-08-01')` es medianoche UTC, pero `new Date('2026-08-01T00:00:00')` es medianoche local: añadir la hora cambia la zona. Si encima formateas con `Intl` sin fijar `timeZone`, la fecha sin hora retrocede un día en cualquier zona al oeste de UTC.

- Fecha: `2026-08-01`
- Tags: JavaScript, Web Platform
- Enlace: https://www.angelcruz.dev/lab#new-date-utc-vs-local-segun-la-hora
- Markdown: https://www.angelcruz.dev/lab/new-date-utc-vs-local-segun-la-hora.md
- Fuente: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse

## Laravel 13: Context::add() comparte datos entre middlewares y jobs

El nuevo helper `Context` en Laravel 13 permite pasar metadata a lo largo del request sin pasar parámetros. Útil para tracing: `Context::add('request_id', $id)` en un middleware y luego `Context::get('request_id')` desde cualquier job en cola. Persiste automáticamente al despachar jobs.

- Fecha: `2026-05-15`
- Tags: Laravel, PHP, Backend
- Enlace: https://www.angelcruz.dev/lab#laravel-13-context-add-middlewares-y-jobs
- Markdown: https://www.angelcruz.dev/lab/laravel-13-context-add-middlewares-y-jobs.md
- Fuente: https://laravel.com/docs/12.x/context

## PHP 8.4: Property hooks reemplazan getters y setters

PHP 8.4 introduce property hooks nativos. En vez de definir `getName()` y `setName()`, escribes `public string $name { get => ucfirst($this->_name); set => $this->_name = trim($value); }`. Menos boilerplate y API más limpia para value objects y DTOs.

- Fecha: `2026-05-12`
- Tags: PHP, Backend
- Enlace: https://www.angelcruz.dev/lab#php-8-4-property-hooks
- Markdown: https://www.angelcruz.dev/lab/php-8-4-property-hooks.md
- Fuente: https://www.php.net/releases/8.4/en.php

## @starting-style permite animar elementos al aparecer en el DOM

La regla CSS `@starting-style` define el estado inicial de un elemento antes de la primera renderización. Útil para animaciones de entry sin JS: define los valores iniciales dentro de `@starting-style { ... }` y los finales en la regla normal. Soportado en Chrome 117+ y Safari 17.5+.

- Fecha: `2026-05-08`
- Tags: CSS, Animation, Web Platform
- Enlace: https://www.angelcruz.dev/lab#starting-style-animar-al-aparecer
- Markdown: https://www.angelcruz.dev/lab/starting-style-animar-al-aparecer.md
- Fuente: https://developer.mozilla.org/en-US/docs/Web/CSS/@starting-style

## View Transitions API funciona cross-document en Chrome 126+

Las View Transitions ya no son solo para SPAs. Con `@view-transition { navigation: auto; }` en el CSS, Chrome 126+ aplica transiciones automáticas entre navegaciones MPA. Esto significa transiciones suaves en sitios estáticos sin necesidad de un framework JS.

- Fecha: `2026-05-04`
- Tags: CSS, Web Platform, Performance
- Enlace: https://www.angelcruz.dev/lab#view-transitions-cross-document
- Markdown: https://www.angelcruz.dev/lab/view-transitions-cross-document.md
- Fuente: https://developer.chrome.com/docs/web-platform/view-transitions/cross-document

## Next.js 16: 'use cache' + cacheLife() reemplaza configuración fetch

Con Cache Components habilitado, marcar una función con `'use cache'` y opcionalmente `cacheLife('hours')` reemplaza el viejo `fetch(url, { next: { revalidate } })`. Más declarativo y funciona con cualquier fuente de datos, no solo fetch. PPR genera shells estáticos + streaming dinámico.

- Fecha: `2026-04-30`
- Tags: Next.js, Cache, Performance
- Enlace: https://www.angelcruz.dev/lab#next-16-use-cache-cachelife
- Markdown: https://www.angelcruz.dev/lab/next-16-use-cache-cachelife.md

## Next.js revalidateTag() requiere expire: 0 para invalidación inmediata

Descubrí que `revalidateTag(tag)` en Next.js 16 no invalida inmediatamente por defecto. Debes usar `revalidateTag(tag, { expire: 0 })` para forzar invalidación inmediata del cache. Esto es crítico para webhooks de revalidación.

- Fecha: `2026-01-29`
- Tags: Next.js, Cache, Performance
- Enlace: https://www.angelcruz.dev/lab#next-revalidatetag-expire-0
- Markdown: https://www.angelcruz.dev/lab/next-revalidatetag-expire-0.md
- Fuente: https://nextjs.org/docs/app/api-reference/functions/revalidateTag

## OKLCH es superior a HSL para dark mode

OKLCH (color space) mantiene la percepción de brillo constante entre colores, a diferencia de HSL. Esto significa que un color con L=0.5 en OKLCH se verá igualmente brillante que cualquier otro color con L=0.5, perfecto para sistemas de diseño consistentes en dark mode.

- Fecha: `2026-01-28`
- Tags: CSS, Design, Accessibility
- Enlace: https://www.angelcruz.dev/lab#oklch-vs-hsl-en-dark-mode
- Markdown: https://www.angelcruz.dev/lab/oklch-vs-hsl-en-dark-mode.md

## React.cache() deduplica requests en Server Components

Usar `cache()` de React en funciones de data fetching en Next.js App Router deduplica automáticamente requests idénticos durante el mismo render tree. Ejemplo: si 3 componentes llaman a `getPost('slug-123')`, solo se ejecuta 1 request.

- Fecha: `2026-01-27`
- Tags: React, Next.js, Performance
- Enlace: https://www.angelcruz.dev/lab#react-cache-deduplica-requests
- Markdown: https://www.angelcruz.dev/lab/react-cache-deduplica-requests.md

## Tailwind @theme inline reemplaza extend en v4

En Tailwind CSS v4, `@theme inline` es la nueva forma de extender el tema. Reemplaza `theme: { extend: {} }` de v3. Mejora el performance del build y permite CSS variables nativas.

- Fecha: `2026-01-26`
- Tags: Tailwind, CSS
- Enlace: https://www.angelcruz.dev/lab#tailwind-theme-inline-en-v4
- Markdown: https://www.angelcruz.dev/lab/tailwind-theme-inline-en-v4.md

## AVIF reduce imágenes 50% vs WebP

AVIF logra la misma calidad visual que WebP con ~50% menos tamaño de archivo. Para Next.js, configurar `formats: ['image/avif', 'image/webp']` como fallback es la mejor estrategia. Safari soporta AVIF desde v16.4.

- Fecha: `2026-01-25`
- Tags: Performance, Images, Next.js
- Enlace: https://www.angelcruz.dev/lab#avif-vs-webp-peso-de-imagenes
- Markdown: https://www.angelcruz.dev/lab/avif-vs-webp-peso-de-imagenes.md

## adjustFontFallback previene CLS en font loading

Next.js tiene `adjustFontFallback: true` en next/font que ajusta métricas del fallback font para match el custom font, previniendo layout shift (CLS) durante la carga. Crítico para Core Web Vitals.

- Fecha: `2026-01-24`
- Tags: Next.js, Performance, Fonts
- Enlace: https://www.angelcruz.dev/lab#adjustfontfallback-previene-cls
- Markdown: https://www.angelcruz.dev/lab/adjustfontfallback-previene-cls.md
