Saltar al contenido principal

Cloudflare Pages

Plataforma de hosting con la red más grande del mundo. El plan gratuito tiene bandwidth ilimitado, lo que lo hace ideal para proyectos con mucho tráfico.

Límites del plan gratuito

ParámetroValor
TipoStatic + SSR (con Workers)
DespliegueGit o Wrangler CLI
BandwidthIlimitado
Builds500/mes
ProyectosIlimitados
Workers (Pages Functions)100,000 req/día
Dominio.pages.dev + custom gratis
Preview deploys✅ Por cada PR
Docker❌ No directo (Workers solo JS/WASM)

Despliegue desde GitHub (recomendado)

  1. Ir a https://dash.cloudflare.comWorkers & PagesCreate
  2. Seleccionar PagesConnect to Git
  3. Autorizar GitHub → seleccionar repositorio
  4. Configurar:
FrameworkBuild CommandOutput Dir
Vite (React/Vue)npm run builddist
Next.jsnpm run build.next
Astronpm run builddist
Nuxtnpm run build.output/public
SvelteKitnpm run buildbuild
  1. Save and Deploy

Despliegue con CLI (Wrangler)

npm install -g wrangler
wrangler login

# Desplegar carpeta dist
wrangler pages deploy ./dist --project-name=mi-proyecto

# Crear proyecto nuevo
wrangler pages project create mi-proyecto

Variables de entorno

Workers & Pages → tu-proyecto → Settings → Environment Variables → Add variable
  • Puedes definir variables para Production y Preview por separado
  • Para variables secretas: marcar como Secret (se ocultan en logs)

Pages Functions (backend en el Edge)

Crea una carpeta /functions en tu proyecto. Cada archivo es una ruta:

/functions/api/usuarios.js   →  /api/usuarios
/functions/api/[id].js → /api/:id (rutas dinámicas)
// functions/api/usuarios.js
export async function onRequestGet(context) {
return Response.json({ usuarios: ['Ana', 'Pedro'] })
}

export async function onRequestPost(context) {
const body = await context.request.json()
// procesar...
return Response.json({ creado: true }, { status: 201 })
}
// functions/api/[id].js  (ruta dinámica)
export async function onRequestGet({ params }) {
const { id } = params
return Response.json({ id, nombre: 'Usuario ' + id })
}

Acceso a bindings desde Functions

// functions/api/datos.js
export async function onRequestGet({ env }) {
// D1 Database
const { results } = await env.DB.prepare('SELECT * FROM items').all()

// KV Storage
const valor = await env.MI_KV.get('clave')

// R2 Bucket
const objeto = await env.MI_BUCKET.get('archivo.txt')

return Response.json({ results })
}

Configurar bindings (D1, KV, R2)

En el dashboard: Settings → Functions → Bindings

O en wrangler.toml para deploy desde CLI:

name = "mi-proyecto"
pages_build_output_dir = "./dist"

[[d1_databases]]
binding = "DB"
database_name = "mi-base"
database_id = "xxxx-xxxx"

[[kv_namespaces]]
binding = "MI_KV"
id = "xxxx"

[[r2_buckets]]
binding = "MI_BUCKET"
bucket_name = "mis-archivos"

Configurar redirects y headers

Crear public/_redirects:

/api/*  /api/:splat  200
/* /index.html 200

Crear public/_headers:

/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Cache-Control: public, max-age=3600

/assets/*
Cache-Control: public, max-age=31536000, immutable

Proyectos y organizaciones

  • Los proyectos viven dentro de una cuenta de Cloudflare (puede ser personal o una org)
  • Puedes crear múltiples proyectos (Pages projects) en la misma cuenta
  • Para colaborar: añadir miembros en Account → Members (gratis hasta 5 miembros)

Dominio custom

  1. Settings → Custom domains → Set up a custom domain
  2. Si tu DNS ya está en Cloudflare: se configura automáticamente
  3. Si usas otro proveedor: agregar el CNAME que te indica Cloudflare

⚠️ Limitaciones importantes

  • 500 builds/mes: con muchos commits se puede agotar (usar branch deploys solo en main)
  • Workers = JS/WASM únicamente: no puedes correr Python, Go, etc. en funciones
  • Sin persistencia en Workers: debes usar D1, KV o R2 para estado