---
title: Imágenes
description: Sube las imágenes de tu contenido una vez, convertidas a WebP al llegar, guardadas en R2 y servidas desde tu Hollware.
section: guides
order: 8
---

# 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:

```jsonc
"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:

```json
{ "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:

```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:

```html
<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.

```ts
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`):

```json
"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 como | Se guarda como |
| --- | --- |
| JPEG | `format` con `quality`, con pérdida |
| PNG | `format`, sin pérdida: capturas, diagramas y logos conservan sus bordes y su transparencia |
| GIF | `format` con todos sus cuadros, animado |
| WebP, AVIF | tal como llegaron |
| SVG | tal 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:

```sh
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.
