Crear un proyecto con C3
npm create cloudflare (C3) como el andamiaje canónico de un Worker: las fases del comando, las plantillas del Worker mínimo al framework, y la anatomía de la estructura resultante con wrangler como dependencia del proyecto.
Todo Worker empieza con un problema banal y tozudo: la página en blanco. Qué archivos necesito, cómo se llama la config, qué versión de wrangler instalo, cómo declaro el primer binding. Cloudflare resuelve esa fricción con create-cloudflare —C3 para los amigos—, un andamiador que no solo copia plantillas: materializa en archivos la opinión de la plataforma sobre cómo debe verse un proyecto del edge. Entender qué hace C3 en cada fase es entender, de paso, el esqueleto que vas a habitar el resto del track.
- Ejecutar C3 con
npm create cloudflarey comprender cada fase del proceso. - Distinguir las plantillas: el Worker mínimo, los frameworks y las plantillas desde un repositorio.
- Leer la estructura resultante y saber qué papel cumple cada archivo.
- Situar
wranglercomo una dependencia del proyecto, no como una herramienta global.
npm create cloudflare: qué es C3
El comando npm create cloudflare@latest parece magia, pero obedece a una convención vieja de npm: npm create foo es azúcar sintáctico para descargar y ejecutar el paquete create-foo. Aquí ese paquete es create-cloudflare, y por eso el mismo andamiaje existe en todos los gestores: pnpm create cloudflare@latest, yarn create cloudflare o bun create cloudflare. El sufijo @latest no es decorativo: C3 evoluciona rápido siguiendo a la plataforma, y anclar a la última versión evita reproducir un esqueleto obsoleto.
# la forma interactiva: C3 te pregunta nombre, plantilla y lenguaje
npm create cloudflare@latest
# equivalente con otros gestores
pnpm create cloudflare@latest
bun create cloudflare@latest
C3 no es un mero copiador de archivos. Encadena varias fases: recoge tus respuestas, escribe el andamiaje, instala las dependencias con tu gestor, inicializa un repositorio git con un primer commit y, al final, te ofrece desplegar. Cada fase es un paso que tendrías que dar a mano; C3 los orquesta con las decisiones por defecto que Cloudflare considera correctas en 2026.
flowchart LR A[npm create cloudflare] --> B[Elegir plantilla y lenguaje] B --> C[Escribir el andamiaje] C --> D[Instalar dependencias] D --> E[Iniciar git y primer commit] E --> F[Desplegar opcional]
La fase final —desplegar— es opcional y te pide autenticarte con wrangler login si aún no lo hiciste; puedes declinarla y publicar más tarde. Ese “más tarde” es lo normal cuando aún no tienes cuenta o quieres tocar el código antes de que nadie lo vea.
C3 no es tu proyecto: es el andamiador que lo crea y luego desaparece. Por eso quieres siempre su última versión —@latest—, que conoce las plantillas actuales, la compatibility_date sensata de hoy y el formato de manifiesto vigente. Fijar una versión vieja de C3 reproduciría un esqueleto de otra época. La versión que sí importa anclar es la de wrangler, y esa queda dentro del proyecto, en package.json, no en el comando que lo generó.
Las plantillas: del Worker mínimo al framework
C3 agrupa sus plantillas en categorías, y la elección determina radicalmente el resultado. La plantilla Hello World genera un Worker desnudo: un fetch handler y poco más, ideal para aprender. Las plantillas de framework (Astro, Next, Remix, SvelteKit, TanStack) no las escribe C3 por su cuenta: delega en la herramienta de andamiaje del propio framework y luego cablea el adaptador de Cloudflare y wrangler encima. Las plantillas de aplicación parten de casos con bindings ya conectados —una cola, un Durable Object, una API con D1—.
Puedes evitar el diálogo interactivo pasando las respuestas como flags. Todo lo que va tras -- se reenvía a C3 sin que npm lo interprete como propio:
# no interactivo: nombre, framework y lenguaje de una sola vez
npm create cloudflare@latest -- mi-app --framework=astro --lang=ts
# un Worker mínimo en TypeScript, sin desplegar al terminar
npm create cloudflare@latest -- mi-worker --type=hello-world --deploy=false
# arrancar desde un repositorio de GitHub como plantilla
npm create cloudflare@latest -- mi-app --template=cloudflare/templates/worker-typescript
La pregunta correcta no es cuál plantilla te suena, sino qué vas a construir. Para un endpoint o un cron, arranca del Hello World y añade bindings a mano: entenderás cada línea. Para una app full-stack con SSR, deja que la plantilla de framework traiga su adaptador ya integrado; reconstruir ese cableado a mano es tedioso y propenso a errores. Y para explorar un patrón concreto —Queues, Durable Objects—, una plantilla de aplicación te da un ejemplo funcional que puedes diseccionar.
La estructura resultante
Un Worker mínimo en TypeScript deja un árbol pequeño y legible. Nada sobra, y cada archivo responde a una pregunta distinta de la cadena de herramientas:
mi-worker/
├── src/
│ └── index.ts # el Worker: el fetch handler
├── test/
│ └── index.spec.ts # pruebas con vitest sobre workerd
├── package.json # scripts y wrangler como devDependency
├── tsconfig.json # config de TypeScript
├── vitest.config.mts # el pool de vitest para Workers
├── worker-configuration.d.ts # tipos generados por wrangler types
└── wrangler.jsonc # el manifiesto del Worker
El corazón es src/index.ts, y su forma revela el modelo mental de la plataforma: un objeto con handlers, exportado por defecto, tipado contra tu propio entorno.
export default {
async fetch(request, env, ctx): Promise<Response> {
return new Response('Hello World!');
},
} satisfies ExportedHandler<Env>;
Ese satisfies ExportedHandler<Env> merece una pausa: Env no es un tipo que escribas tú, sino uno que wrangler types genera a partir de tus bindings declarados en wrangler.jsonc y deja en worker-configuration.d.ts. Tu infraestructura se convierte en tipos de TypeScript. El package.json cierra el círculo: incluye wrangler como dependencia de desarrollo y un puñado de scripts que estabilizan el vocabulario del proyecto.
{
"scripts": {
"dev": "wrangler dev",
"deploy": "wrangler deploy",
"cf-typegen": "wrangler types"
}
}
El resto del árbol es andamiaje de calidad, silencioso pero deliberado. tsconfig.json fija una configuración de TypeScript coherente con el runtime del edge, y la carpeta test/ trae vitest ya cableado con el pool de Workers: tus pruebas no corren en Node, sino dentro de workerd, el mismo runtime que ejecutará el Worker en producción. Es la idea de fidelidad que atraviesa todo el ecosistema llevada hasta los tests —validar el código en una aproximación sería volver a abrir la grieta que la plataforma se esfuerza por cerrar—.
src/index.ts
El Worker en sí: exporta handlers como fetch o scheduled. La función pura del edge que recibe env y devuelve una Response.
wrangler.jsonc
El manifiesto. Nombre, punto de entrada, compatibility_date y bindings. La siguiente lección lo disecciona entera.
worker-configuration.d.ts
Los tipos generados a partir de tus bindings. No lo edites a mano: lo regenera wrangler types.
package.json
wrangler vive aquí como devDependency y los scripts dev, deploy y cf-typegen fijan el flujo de trabajo.
C3 no te ahorra teclear: te enseña, sin decirlo, cómo piensa la plataforma. Fíjate en las tres decisiones que codifica el esqueleto y que definen el resto del track. Primero, wrangler es una dependencia del proyecto, no un binario global: cada Worker fija su propia versión del CLI, y así el equipo, el CI y tu máquina despliegan con exactamente la misma herramienta —el mismo principio que hace reproducible cualquier build moderna—. Segundo, la configuración es código versionado: el manifiesto wrangler.jsonc vive en el repositorio junto al Worker, de modo que la infraestructura no es un panel que alguien tocó una vez, sino un archivo cuya historia cuenta git. Tercero, y más sutil, los tipos fluyen desde la infraestructura hacia el código: wrangler types lee tus bindings y genera el Env contra el que se compila tu Worker, cerrando el hueco entre lo que declaras que existe y lo que tu código cree que existe. Interiorizar esto cambia cómo lees un proyecto de Workers: no es un script suelto con una config al lado, sino un artefacto autocontenido donde compute, contrato de infraestructura y tipos son tres vistas de la misma verdad. Quien empieza tecleando npm create cloudflare no está ahorrando cinco minutos: está heredando una disciplina.
- Genera un Worker mínimo con
npm create cloudflare@latest -- mi-worker --type=hello-world --lang=ts --deploy=falsey recorre cada archivo del árbol resultante. - Abre
package.jsony confirma quewranglerestá endevDependencies; anota su versión exacta. - Genera un segundo proyecto con
--framework=astroy compara: qué archivos nuevos aparecen y de dónde salió el adaptador de Cloudflare. - Abre
src/index.tsdel Worker mínimo y localizaExportedHandler<Env>; rastrea de dónde saleEnvhastaworker-configuration.d.ts. - Ejecuta
npm run cf-typegeny observa si el archivo de tipos cambia; razona por qué se regenera desde el manifiesto.