# Cloudflare

> Despliega con Cloudflare Workers y assets estáticos: la configuración que usa el propio htmlpress.dev.

Cloudflare Workers puede servir directamente un directorio de assets estáticos: sin cómputo aparte ni shim de SPA. Así se publica `htmlpress.dev`, y la misma estructura de `wrangler.jsonc` sirve para cualquier sitio htmlpress. Los assets estáticos de Workers también leen el archivo `_headers` que escribe cada compilación.

## Compila el sitio

```sh
htmlpress build
```

La salida queda en `.htmlpress/build/`.

## Configura `wrangler.jsonc`

Coloca esto en la raíz de tu proyecto:

```
{
  "name": "my-docs",
  "compatibility_date": "2026-04-01",
  "workers_dev": true,
  "assets": {
    "directory": ".htmlpress/build",
    "not_found_handling": "404-page",
  },
}
```

Tres campos hacen el trabajo pesado:

| Campo                       | Propósito                                                                                |
| --------------------------- | ---------------------------------------------------------------------------------------- |
| `assets.directory`          | Apunta Wrangler a la salida de compilación de htmlpress. Cada archivo se sirve tal cual. |
| `assets.not_found_handling` | Responde a las rutas desconocidas con el `404.html` de la compilación.                   |
| `workers_dev`               | Te da una URL de previsualización `<name>.<account>.workers.dev` mientras haces pruebas. |

## Despliega desde tu máquina

```sh
htmlpress build
npx wrangler deploy
```

La primera ejecución te pide `wrangler login` para autorizar el acceso a tu cuenta de Cloudflare.

## Despliega con GitHub Actions

```yaml
name: deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v4
        with:
          node-version: 24
      - run: npx gethtmlpress build
      - uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
```

Crea un token de API con alcance limitado en **My Profile → API Tokens** (la plantilla "Edit Cloudflare Workers" concede exactamente lo que necesitas) y guarda ambos valores como secretos del repositorio.

Sin un workflow, Workers Builds puede ejecutar la compilación por sí mismo: conecta el repositorio en el panel y añade un bloque `build` a `wrangler.jsonc`, como hace htmlpress.dev con `"build": { "command": "pnpm build:docs" }`.

## Dominio personalizado

Añade un bloque `routes` cuando tu zona esté en Cloudflare:

```
{
  "name": "my-docs",
  "compatibility_date": "2026-04-01",
  "assets": { "directory": ".htmlpress/build", "not_found_handling": "404-page" },
  "routes": [{ "pattern": "docs.example.com", "custom_domain": true }],
}
```

`custom_domain: true` indica a Cloudflare que aprovisione un dominio gestionado: DNS, certificado y ruta se encargan por ti. Define `site` con el mismo dominio en `htmlpress.yaml` para que las URLs absolutas del sitemap coincidan.

> **Consejo**
>
> El propio `wrangler.jsonc` del repositorio de htmlpress es una referencia funcional; consulta la [raíz del proyecto](https://github.com/datisthq/htmlpress/blob/main/wrangler.jsonc).

## Markdown para agentes

Los agentes de IA piden una página en Markdown enviando `Accept: text/markdown`. Los assets estáticos siempre responden con HTML, así que añade a tu zona una URL Rewrite Rule que dirija esas peticiones a la [copia en Markdown](/es/customization/ai-agents/) de la página: `/guides/build/` tiene `/guides/build/index.md` junto a su HTML. Las URL Rewrite Rules están disponibles en todos los planes, incluido Free, y el sitio sigue siendo totalmente estático.

En el panel, abre tu dominio, ve a **Rules → Overview → Create rule → URL Rewrite Rule** y rellena:

| Campo                      | Valor                                                                  |
| -------------------------- | ---------------------------------------------------------------------- |
| Rule name                  | `Markdown for agents`                                                  |
| If incoming requests match | Custom filter expression (abajo)                                       |
| Path                       | Rewrite to → **Dynamic** → `concat(http.request.uri.path, "index.md")` |
| Query                      | Preserve                                                               |

```
any(http.request.headers["accept"][*] contains "text/markdown") and ends_with(http.request.uri.path, "/")
```

Las URLs de página terminan en `/`, así que la regla solo afecta a las páginas. Los assets estáticos sirven los archivos `.md` como `text/markdown`, así que el tipo de respuesta no necesita ninguna regla adicional.

> **Warning**
>
> Despliega una compilación que contenga las copias en Markdown antes de activar la regla. De lo contrario, un agente que pida Markdown recibirá un 404.

## Ver también

- [Agentes de IA](/es/customization/ai-agents/): lo que la compilación publica para los agentes.
- [Metadatos del sitio](/es/customization/site-metadata/): `site` hace posibles las URLs absolutas y el sitemap.
- [Despliegue](/es/deployment/): volver al índice de hosts.
