Arrancando una librería compartida de enlaces de afiliados en dos sitios
vdaluz.com corre enlaces de afiliados (Amazon Associates, Proton Partners, una referencia de AdGuard), e imperfectsystems.com estaba por necesitar lo mismo en su blog de dev log. Ya se había extraído un paquete compartido de componentes de blog, @vdaluz/astro-blog, al separar los dos sitios. En vez de escribir un segundo sistema de afiliados, ligeramente distinto, para el sitio nuevo, el manejo de afiliados se extrajo también a su propio paquete: @vdaluz/astro-affiliate.
Problema
Los enlaces de afiliados de vdaluz.com se habían desviado. Un spike midió 72 posts usando 4 o más redacciones distintas para la misma frase de divulgación de Amazon, y el texto de divulgación de uno de los programas nunca se renderizaba en ningún lado a pesar de estar definido en la configuración. Las divulgaciones escritas a mano en línea no escalan, y ese mismo desorden estaba a punto de duplicarse en un segundo sitio.
Investigación
El arreglo no es solo “escribir un componente,” es hacer estructuralmente imposible publicar un enlace de afiliado sin su divulgación. Eso significa que el requisito de divulgación tiene que vivir en el build, no en que alguien recuerde agregar una frase.
Se optó por un formato de clave como amazon.atomicHabits o proton.pass: nombre del programa, punto, clave del ítem. En markdown, un enlace se convierte en [Atomic Habits](affiliate:amazon.atomicHabits). Un plugin de remark recorre el AST en tiempo de build, resuelve eso a la URL real, y cruza cada programa realmente usado contra el affiliates: [amazon] del frontmatter del post. Si se usa un enlace de afiliado sin declarar el programa, el build falla con un mensaje que dice exactamente qué agregar. Cumplimiento por construcción en vez de cumplimiento por memoria.
Solución
El paquete refleja casi exactamente las convenciones de astro-blog: código fuente .ts/.astro sin paso de build, exports por ruta, sin dependencias, distribuido como un tarball fijado a un tag (la resolución de npm para el shorthand de GitHub lo reescribe a git+ssh, que falla en CI sin llaves SSH, así que la URL del tarball es la única forma que sobrevive a un runner de CI). Cada sitio provee su propio catálogo, tag de seguimiento, y texto de divulgación vía configuración; el paquete no lleva ningún dato de afiliados propio.
Dos tipos de programa: amazon construye la URL a partir de un ASIN y el tag de Associates de un sitio, links es simplemente un mapa plano de clave a URL para todo lo demás (Proton, AdGuard, lo que venga después). Un componente <AffiliateDisclosure> lee el array affiliates de un post y renderiza el texto correcto en la parte superior del cuerpo del post, antes del scroll, que es justo lo que pide la FTC: divulgación antes de los enlaces, no enterrada en un pie de página.
Reflexión
La verificación tomó una forma un poco particular. Se empaquetó el tarball de verdad y se instaló en vdaluz.com como un consumidor real, y después se corrió astro check y astro build contra una página descartable que ejercitaba cada export, lo cual sacó a la luz problemas reales de tipos y de runtime que un test simulado no habría detectado. Para el plugin de remark en particular, apareció un tropiezo pequeño pero instructivo: el soporte nativo de TypeScript de Node quita los tipos pero igual exige resolución ESM estricta, que requiere extensiones .ts explícitas en los imports relativos, mientras que el código fuente del paquete las omite a propósito porque eso es lo correcto para el consumo vía bundler. Un script rápido contra el código fuente real falló con un error de módulo no encontrado que no tenía nada que ver con la lógica real. El arreglo fue probar las partes sensibles a extensiones a través del pipeline real de Astro, y reservar un script aislado y rápido de Node solo para código sin ninguna superficie de Astro, copiando archivos con las extensiones corregidas en vez de tocar el código fuente real.
El paquete está en vivo en github.com/vdaluz/astro-affiliate, v0.1.0. Lo próximo es conectarlo de verdad en ambos sitios y hacer el barrido de divulgación en los posts existentes de vdaluz.com.
Lecturas relacionadas
Vaciar un backlog: cinco arreglos pequeños en una sola versión
Un arreglo de accesibilidad para una decoración muerta, un campo de esquema que validaba pero nunca se renderizaba, y una corrida de formateo que cambió en silencio el estilo de comillas en cuatro archivos.
El error de escape que solo aparece con un segundo parámetro de consulta
Una función de reescritura que funcionaba en cada prueba y cada URL real que había visto, y aun así se habría roto en el momento en que alguien agregara un segundo parámetro de consulta.
Probar la parte del código que documenta su propia trampa
Una advertencia en el README sobre un modo de fallo sutil es una confesión de que el código todavía no tiene pruebas para eso.