Guías

Imágenes

Sube las imágenes de tu contenido una vez, convertidas a WebP al llegar, guardadas en R2 y servidas desde tu Hollware.

Imágenes

Una imagen es un archivo de un sitio. Se envía una vez, se convierte una vez al llegar, se guarda en un bucket de R2 de tu cuenta y el contenido la nombra con una referencia que nunca cambia: asset:ast_…. Los agentes la suben por MCP, y las personas en el admin, en Imágenes.

Un proyecto necesita dos bindings en wrangler.jsonc, que los proyectos creados con la 1.0 ya traen:

"r2_buckets": [{ "binding": "MEDIA", "bucket_name": "my-hollware-media" }],
"images": { "binding": "IMAGES" },

hollware deploy crea el bucket la primera vez, igual que crea la base de datos. Sin MEDIA, upload_asset responde unavailable. Sin IMAGES, cada archivo se guarda tal como llegó, sin convertir. hollware doctor dice cuál falta.

Sube una imagen

Un agente llama a upload_asset con el archivo en base64, su nombre y su alt, lo que muestra la imagen para quien no puede verla:

{ "filename": "continuum.png", "alt": "El logo de Continuum sobre un fondo oscuro", "data": "iVBORw0KGgo…" }

Responde con el asset: su reference, su url, el formato y el tamaño con que se sirve, y el formato y el tamaño con que se envió. El mismo archivo enviado de nuevo responde exists con el mismo asset, así que un agente puede subir sin revisar antes. El mismo archivo en otro sitio del despliegue es otro asset, con su propio id. list_assets lista las imágenes del sitio, de la más nueva a la más antigua, y get_asset trae una por su id.

Qué es un archivo lo dicen sus bytes, nunca su nombre: JPEG, PNG, WebP, AVIF, GIF y SVG, de hasta 10 MB. Cualquier otra cosa se rechaza con lo que hay que hacer.

Muéstrala

Escribe la referencia donde va la imagen, en el frontmatter o en el Markdown:

---
title: Migrar un monorepo a un toolchain nuevo
img: asset:ast_e51afa61663c33d06276f786da
---

![El logo de Continuum sobre un fondo oscuro](asset:ast_e51afa61663c33d06276f786da)

Una imagen de Markdown sin alt propio toma el del asset cuando un sitio la lee, así que el contrato images-have-alt la deja pasar. Lo que muestra una imagen se puede cambiar después: update_asset con su id y un alt nuevo, o Editar lo que muestra en su tarjeta, en Imágenes. Cada entrada que la muestra sin un alt propio lee el nuevo; el archivo nunca cambia.

Los sitios leen la URL, nunca la referencia: getEntry por RPC y la API de lectura convierten cada asset: en la URL de la imagen, en el frontmatter y en el documento renderizado. Por MCP, un agente lee lo que escribió, referencias incluidas.

La URL es <tu Hollware>/assets/<sitio>/<id>, pública y en caché por un año: un asset nunca cambia, así que una imagen nueva es un asset nuevo.

Imágenes responsivas

Cuando llega una imagen, Hollware hace también sus copias más angostas, para que un teléfono cargue una pequeña: una por cada ancho de media.widths del sitio que sea menor que la imagen, 640 y 1280 píxeles por defecto. Cada una se sirve en <url>/<ancho>.

Un sitio las recibe sin pedirlas. En el HTML de una entrada, y en el documento que lee un sitio, cada imagen trae srcset, sizes y su width y height, así la página conserva su espacio mientras carga:

<img src="https://cms.example.com/assets/blog/ast_e51a…" srcset="https://cms.example.com/assets/blog/ast_e51a…/640 640w, https://cms.example.com/assets/blog/ast_e51a…/1280 1280w, https://cms.example.com/assets/blog/ast_e51a… 1600w" sizes="(min-width: 1600px) 1600px, 100vw" width="1600" height="900" alt="…">

Un tamaño que escribió el autor se respeta. Para las imágenes del frontmatter, como una portada, el resumen que lee un sitio (getEntry, listEntries) trae images: por URL, el width, el height y el srcset de cada una.

const cover = entry.images?.[entry.frontmatter.img]
// <img src={entry.frontmatter.img} srcset={cover?.srcset ?? undefined} width={cover?.width} …>

upload_asset, get_asset y list_assets también responden widths y srcset. Las imágenes subidas antes de 1.0.0-rc.3 no tienen copias.

Cómo se convierten

Cada sitio lo dice en su ajuste media, parte de su estructura (léelo con get_structure y cámbialo con update_site):

"media": { "format": "webp", "quality": 85, "maxWidth": 2400, "widths": [640, 1280], "keepOriginals": true }

Esos son los valores por defecto, los que recibe un sitio que no dice nada. En el admin están en Sitio, en Imágenes.

Se envía comoSe guarda como
JPEGformat con quality, con pérdida
PNGformat, sin pérdida: capturas, diagramas y logos conservan sus bordes y su transparencia
GIFformat con todos sus cuadros, animado
WebP, AVIFtal como llegaron
SVGtal como llegó, nunca se convierte

Si es más ancha que maxWidth (de 320 a 8192 píxeles), una imagen se reduce, nunca se agranda. format acepta webp, avif (todavía más liviano, un poco más lento de codificar) u original, que guarda cada archivo tal como llegó, sin copias. widths acepta hasta cuatro anchos entre 320 y 8192, de menor a mayor, o [] para no hacer copias. Un cambio se aplica a las imágenes que se suban después.

Hollware guarda también el original de cada archivo, que nunca se sirve, en /v1/assets/<id>/original con un token personal, así que un cambio de formato posterior tiene de dónde partir. Un sitio que prefiere ocupar menos espacio pone keepOriginals en false (Guardar el original de cada imagen en el admin): guarda solo el archivo que sirve y sus copias, y la descarga de un original, y hollware export, entregan el archivo servido. Las imágenes subidas antes conservan el suyo.

SVG

Un SVG sigue siendo vectorial y nunca se reescribe. Hollware lo acepta solo cuando nada en él puede ejecutarse ni salir del archivo: sin <script>, <foreignObject>, <iframe>, <embed> ni <object>, sin atributos on…, sin URLs javascript: ni data:, sin <!DOCTYPE> ni <!ENTITY>, y sin enlaces fuera del archivo. Las referencias de carácter y las entidades distintas de las cinco de XML (&amp;, &lt;, &gt;, &quot;, &apos;), las barras invertidas y las animaciones de un enlace (<set> o <animate> de href) también se rechazan, porque pueden escribir lo que buscan las otras reglas. Cualquier otra cosa se rechaza indicando la parte que hay que quitar. Un optimizador de SVG limpia la mayoría de los archivos que salen de una herramienta de diseño.

Se sirve con una política de seguridad que no ejecuta nada, aunque un navegador lo abra solo.

Lo que cuesta

La conversión es Cloudflare Images sobre almacenamiento en R2. Cada imagen nueva es una transformación, dos cuando es más ancha que maxWidth, y una más por cada copia; una imagen enviada de nuevo no cuesta nada. Si la cuota se acaba mientras se hacen las copias, la imagen conserva las que ya se hicieron. El plan gratuito incluye 5.000 transformaciones al mes: pasado eso, una subida responde unavailable hasta el mes siguiente, y no se cobra nada. R2 guarda 10 GB gratis.

Tus imágenes en tu sitio

Las URLs de los assets están en el dominio de tu Hollware, que les pide a los buscadores no indexarlo. Un sitio que quiere sus imágenes indexadas en su propio dominio las sirve él mismo:

npx hollware export ./content --published --assets public/images/cms --assets-url /images/cms/ --url https://cms.example.com --token-file export.token

El token es uno personal con content:read: hollware token create --label export --scopes content:read --remote.

--assets escribe en ese directorio cada imagen que muestran las entradas publicadas, tal como se sirve, y cada referencia asset: de la exportación apunta a --assets-url. Un sitio estático se construye desde esa exportación.

Sin --assets, una exportación deja las referencias como están y escribe las imágenes, tal como se subieron, en _assets/ con un assets.json al lado. hollware import las vuelve a subir antes que las entradas que las muestran, así que una exportación es un respaldo de tu contenido y de sus imágenes.