
Cloudflare Pages SEO: configuración completa en 2026
Cloudflare Pages se volvió el deploy default para muchos sitios de contenido y SaaS marketing en 2026. Trae edge global con 300+ ubicaciones, free tier generoso, zero cold start, e integración nativa con Workers, KV, R2 y Cloudflare Analytics. Pero el SEO óptimo no viene out-of-the-box: necesitás configurar 5 archivos clave en orden de prioridad.
Soy Ignacio y deployo en Cloudflare Pages desde 2023, propios y de clientes. Si todavía no leíste sobre performance específicamente, mirá Core Web Vitals en Cloudflare Pages.
¿Por qué Cloudflare Pages vs Vercel o Netlify?
Comparación práctica que mando a clientes:
| Dimensión | Cloudflare Pages | Vercel | Netlify |
|---|---|---|---|
| Edge global | 300+ POPs | 30+ POPs | ~10 POPs |
| Cold starts SSR | Zero (en Workers) | ~50-200ms | ~100-300ms |
| Free tier bandwidth | Ilimitado | 100GB | 100GB |
| Free tier requests | 100k/día | Limitado | 125k |
| Imagen optimization | Cloudflare Images (paga) | Vercel Image (incluida) | Netlify Image |
| DX Next.js avanzado | Bueno | Excelente | Bueno |
| DX SvelteKit/Astro | Excelente | Bueno | Bueno |
| Costo sitio mediano | USD 0 | USD 20-100/mes | USD 20-100/mes |
Cloudflare Pages gana en cost-effectiveness y performance global. Vercel gana en DX para Next.js complejo (App Router, ISR fino).

¿Qué archivos necesita un sitio Cloudflare Pages bien configurado?
Cinco archivos clave viven en la carpeta de assets (static/ en SvelteKit):
_headers: headers HTTP por path_redirects: redirects 301/302 sin códigorobots.txt: directivas para crawlers/sitemap.xml/+server.ts: sitemap dinámico (ensrc/routes/)/llms.txt/+server.ts: llms.txt dinámico (ensrc/routes/)
Repaso cada uno con código real más abajo.
¿Cómo configuro _headers?
El archivo vive en static/_headers y suele tener cuatro bloques mínimos:
# Cache fino: assets versionados un año, HTML corto
/_app/immutable/*
Cache-Control: public, max-age=31536000, immutable
/*
Cache-Control: public, max-age=300, s-maxage=300, stale-while-revalidate=86400
# Headers de seguridad globales
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
# CORS para fonts si las servís cross-origin
/fonts/*
Access-Control-Allow-Origin: *
Detalle importante: los bloques se procesan top-down. El path más específico gana sobre el genérico. Si querés HTML cacheado más largo en una sección particular, declarala antes del /* genérico.
stale-while-revalidate=86400 es la clave para HTML dinámico: el cache sirve la versión vieja inmediatamente mientras revalida en background. UX sin penalty SEO porque la versión vieja sigue siendo válida.
¿Cómo configuro _redirects?
Archivo en static/_redirects. Sintaxis: <from> <to> <status>.
# Redirects 301 por cambio de slug
/old-article /articles/new-slug 301
# Mover sección entera con splat
/blog/* /articles/:splat 301
# Forzar idioma por geo (opcional, suele preferirse el idioma del navegador)
# (esto requiere Workers, no se hace en _redirects)
# Trailing slash consistente
/articles/*/ /articles/:splat 301
# Dominio canónico (apex → www o viceversa)
https://www.tusitio.com/* https://tusitio.com/:splat 301!
El ! al final del status fuerza el redirect incluso si la URL destino existe (útil para canonicalización de dominio).
Para 95% de los casos SEO, _redirects alcanza. Solamente necesitás Workers cuando hacés A/B tests, geo-routing fino, o transformaciones de URL complejas.
¿Cómo se ve robots.txt para AEO + SEO?
# Sitemap principal
Sitemap: https://ignax.dev/sitemap.xml
# Search engines clásicos
User-agent: Googlebot
Allow: /
User-agent: Bingbot
Allow: /
# Crawlers de IA (necesarios para AEO)
User-agent: GPTBot
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: PerplexityBot
Allow: /
User-agent: Google-Extended
Allow: /
User-agent: CCBot
Allow: /
# Bloquear áreas privadas si las hay
User-agent: *
Disallow: /admin/
Disallow: /api/internal/
Allow: /
Detalle importante: los crawlers de IA respetan robots.txt. Si los bloqueás, no aparecés citado. Más contexto en cómo aparecer citado por ChatGPT.
¿Cómo genero sitemap.xml dinámico en SvelteKit?
Ruta +server.ts que recorre el registry de Markdown y genera XML:
// src/routes/sitemap.xml/+server.ts
import { listAllContent } from '$lib/content/loader';
const BASE = 'https://ignax.dev';
export async function GET() {
const entries = await listAllContent();
// Agrupar por canonicalSlug para juntar variantes idiomáticas
const groups = new Map<string, typeof entries>();
for (const e of entries) {
const key = `${e.type}:${e.canonicalSlug}`;
if (!groups.has(key)) groups.set(key, []);
groups.get(key)!.push(e);
}
const urls = [...groups.values()].map(group => {
const en = group.find(g => g.lang === 'en');
const es = group.find(g => g.lang === 'es');
const primary = en ?? es!;
const alternates = group.map(g =>
`<xhtml:link rel="alternate" hreflang="${g.lang}" href="${urlFor(g)}" />`
).join('\n ');
const xDefault = en
? `<xhtml:link rel="alternate" hreflang="x-default" href="${urlFor(en)}" />`
: '';
return `<url>
<loc>${urlFor(primary)}</loc>
${alternates}
${xDefault}
<lastmod>${primary.updatedAt}</lastmod>
<changefreq>monthly</changefreq>
</url>`;
}).join('\n');
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
${urls}
</urlset>`;
return new Response(xml, {
headers: {
'content-type': 'application/xml',
'cache-control': 'public, max-age=3600, s-maxage=3600',
},
});
}
function urlFor(entry: { lang: string; type: string; slug: string }) {
const prefix = entry.lang === 'en' ? '' : `/${entry.lang}`;
const typeSegment = typeSegmentFor(entry.lang, entry.type);
return `${BASE}${prefix}/${typeSegment}/${entry.slug}`;
}
Cloudflare Pages ejecuta este +server.ts como Worker en el edge; el sitemap se sirve en <50ms globalmente.
¿Cómo configuro IndexNow?
IndexNow es un protocolo que avisa a Bing (y por extensión a ChatGPT que usa Bing para browsing) cuando hay contenido nuevo. Setup en 30 minutos. Detalle completo en el tutorial de IndexNow.
Resumen:
- Generás una key UUID y la servís en
/{key}.txten raíz del dominio. - Cuando publicás contenido, hacés POST a
https://api.indexnow.org/indexnowcon la URL nueva y la key. - Bing crawlea en minutos en vez de días.
¿Qué hago con assets pesados (imágenes, videos)?
Cloudflare R2 + Cloudflare Images:
- R2 (S3-compatible). USD 0 egreso, USD 0.015/GB storage. Para videos, PDFs, datasets.
- Cloudflare Images. USD 5/mes hasta 100k imágenes. On-the-fly resize, AVIF/WebP automático.
Para sitios chicos, los archivos en static/ con _headers de cache largo alcanza. Para sitios con catálogo de imágenes o video, R2 + Images se paga rápido.
¿Cómo monitoreo SEO en Cloudflare Pages?
Mi stack:
- Cloudflare Analytics: pageviews, top URLs, top referrers. Liviano, sin cookies.
- Cloudflare Web Analytics Beacon: Core Web Vitals reales en tu dashboard.
- Google Search Console: queries, posiciones, errores de indexación.
- Bing Webmaster Tools: equivalente a GSC para Bing/ChatGPT browsing.
Sin Google Analytics tradicional (pesado y privacy-issue). Para casos donde se necesite, Plausible o Umami son livianos y privacy-friendly.
¿Qué errores comunes evitar?
Cinco que veo en auditorías:
- No declarar headers de seguridad. Lighthouse penaliza, browsers warning, score Mozilla Observatory bajo.
- Cache-Control genérico para todo. Assets versionados deberían ser 1 año immutable; HTML cortos.
- No incluir crawlers de IA en robots.txt. Excluís citas sin querer.
- Sitemap.xml estático que no se actualiza. Generalo dinámico del registry de contenido.
- Olvidar hreflang en sitemap multilingüe. Detalle en la guía de hreflang en SvelteKit + Paraglide.
¿Por dónde arrancar?
Tres archivos críticos para esta semana:
_headerscon cache + seguridad (1 hora).robots.txtcon permisos a crawlers de IA (10 minutos).sitemap.xmldinámico con hreflang (2 horas).
¿Cómo migrar desde Vercel o Netlify?
Para sitios SvelteKit, migrar de Vercel a Cloudflare Pages es razonable en 1-2 días:
- Cambiar adapter:
@sveltejs/adapter-vercel→@sveltejs/adapter-cloudflare. - Mover variables de entorno al panel de Cloudflare Pages.
- Configurar build settings (build command, output directory) en Cloudflare Pages.
- Apuntar DNS al nuevo dominio (con preview deploy primero).
- Cutover DNS cuando el preview esté verificado.
Para Next.js: usar @cloudflare/next-on-pages para adaptar Next.js a Workers. La compatibilidad mejoró mucho en 2025-2026; ya soporta App Router, Server Actions y middleware sin sorpresas.
¿Vale la pena para clientes existentes?
Tres razones para migrar:
- Costos: sitios con mucho bandwidth (>100GB/mes) salen Gs 0 en Cloudflare vs Gs 200k-1M/mes en Vercel/Netlify.
- Performance global: edge en LATAM/SE Asia mucho más completo.
- Integración con resto del ecosistema Cloudflare: R2, KV, D1, Workers AI, Stream: todo bajo una factura.
Tres razones para no migrar:
- Ya tenés DX optimizada en Vercel para Next.js App Router. Si el equipo conoce Vercel a fondo, la migración no agrega valor proporcional.
- Dependés de features específicas de Vercel (ISR avanzado, Image Optimization integrada, Edge Functions con runtime Node específico).
- Sitio chico con tráfico bajo. El gain de costos es marginal.
Si querés que te haga el setup completo, escribime a [email protected] o mirá el servicio de setup SEO + AEO. La documentación oficial de Cloudflare Pages tiene referencias detalladas para cada archivo. Para entender el contexto AEO completo, mirá qué es AEO.
Preguntas frecuentes
¿Cloudflare Pages es mejor que Vercel para SEO?
Para sitios estáticos y SSR ligero en SvelteKit/Astro/Next.js, sí. Tres ventajas concretas: edge global con mejor cobertura LATAM/SE Asia, costos predecibles sin sorpresas por bandwidth, y zero cold start en assets. Vercel gana en DX para Next.js avanzado (ISR complejo, Image Optimization integrada). Para 90% de los sitios de contenido y SaaS marketing, Cloudflare Pages es la elección correcta en 2026.
¿Cómo configuro redirects sin escribir Workers?
Con el archivo `_redirects` en la carpeta de assets. Sintaxis simple: `/vieja-url /nueva-url 301`. Soporta wildcards, splats y captura de grupos. Para 95% de los casos de redirect SEO (cambio de slug, dominio, idioma), `_redirects` alcanza sin necesidad de Workers. Workers se reservan para lógica condicional (geo-redirects, A/B tests, manipulación de headers complejos).
¿Qué pongo en _headers para SEO y seguridad?
Cuatro bloques mínimos: cache-control fino (1 año para assets versionados, 5 min para HTML), headers de seguridad (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy), HSTS para forzar HTTPS, y Content-Security-Policy si tenés handle del third-party JS. Cloudflare aplica estos headers en el edge sin runtime overhead, gratis en rendimiento.
¿Cómo genero sitemap.xml dinámico en SvelteKit + Cloudflare Pages?
Con una ruta `/sitemap.xml/+server.ts` que lee el registry de contenido (Markdown del repo) y genera el XML. Cloudflare Pages la ejecuta como Worker en el edge, así que el sitemap se sirve en <50ms desde cualquier región. Incluí xhtml:link para hreflang si tu sitio es bilingüe. Detalle de hreflang correcto en /es/articulos/hreflang-sveltekit-paraglide.
¿Robots.txt debe permitir crawlers de IA?
Si querés aparecer citado por ChatGPT, Claude, Perplexity, sí. Listá explícitamente: GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot, Google-Extended (Gemini), CCBot (Common Crawl). Bloquearlos es decisión legítima si querés excluir tu contenido del entrenamiento, pero entonces no esperes citas. Detalle en /es/articulos/aparecer-citado-chatgpt y la sección AEO en /es/articulos/que-es-aeo.
¿Qué pasa con HTTPS y certificados?
Cloudflare Pages provee certificados SSL/TLS automáticos vía Cloudflare. Sin configuración. HTTPS forzado por default. HTTP/3 + QUIC activo. Lo único a configurar manualmente: si tu dominio está en otro registrador, apuntá los DNS a Cloudflare o usá CNAME flattening. La integración con Cloudflare DNS es lo que da la mejor performance.