Creando Mi Propio Newsletter con Claude
Día dos del pico de tráfico de Hacker News. Cuarenta mil visitantes, sin forma de contactarlos de nuevo. Necesitaba un formulario de suscripción al newsletter.
Miré Buttondown, Beehiiv, Substack, ConvertKit. Todo excesivo. Solo necesitaba recolectar correos electrónicos. No necesitaba campañas, analíticas o gestión de suscriptores. Y quería ser dueño de mis datos.
Así que le pedí a Claude que lo construyera.
flowchart LR
User([User]) --> Form[Newsletter Form]
Form -->|POST /api/subscribe| Worker[Cloudflare Worker]
Worker --> KV[(Cloudflare KV)]
KV -.->|Daily sync| GHA[GitHub Actions]
GHA -.-> Repo[(subscribers.jsonl)]
flowchart TB
User([User]) --> Form[Newsletter Form]
Form -->|POST /api/subscribe| Worker[Cloudflare Worker]
Worker --> KV[(Cloudflare KV)]
KV -.->|Daily sync| GHA[GitHub Actions]
GHA -.-> Repo[(subscribers.jsonl)]
La Configuración
Le di a Claude un token de API de Cloudflare mediante una variable de entorno y describí lo que quería: un formulario que recolecte correos y los almacene en un lugar que yo controle.
Menos de 30 minutos después, tenía un newsletter funcionando.
Lo Que Claude Construyó
| Componente | Tecnología |
|---|---|
| Formulario | HTML + vanilla JS |
| Backend | Cloudflare Worker |
| Almacenamiento | Cloudflare KV |
| Sincronización | GitHub Actions |
El formulario es un partial de Hugo que envía datos a /api/subscribe:
<form id="newsletter-form">
<input type="email" name="email" placeholder="[email protected]" required>
<button type="submit">Subscribe</button>
</form>
El backend es un Cloudflare Worker de 42 líneas:
export async function onRequestPost(context) {
const { email } = await request.json();
// Validate, normalize, check for duplicates
const emailKey = email.trim().toLowerCase();
const existing = await env.SUBSCRIBERS.get(emailKey);
if (existing) {
return Response.json({ success: true, message: "Already subscribed" });
}
// Store in KV with metadata
await env.SUBSCRIBERS.put(emailKey, JSON.stringify({
subscribedAt: new Date().toISOString(),
source: sanitizedReferer
}));
return Response.json({ success: true }, { status: 201 });
}
Un flujo de GitHub Actions se ejecuta diariamente para sincronizar los suscriptores desde Cloudflare KV a un archivo JSONL en el repositorio. Mi lista de suscriptores vive en control de versiones. Si Cloudflare cierra mi cuenta mañana, aún tengo mis datos. Y está en un formato con el que los LLMs pueden trabajar fácilmente.
El Flujo de Trabajo
Claude iteró localmente hasta que todo funcionó—envío del formulario, almacenamiento en KV, manejo de errores. Luego publicó en una app de vista previa, probó el flujo completo y fusionó a main.
El formulario se publicó mientras el tráfico todavía fluía.
Todo esto se construyó en una sesión.
¿Por Qué No SaaS?
Buttondown es genial si lo necesitas. Yo no. Mis requisitos:
- Recolectar correos electrónicos
- Almacenarlos en un lugar que controle
- Lanzar rápido
Eso es todo. No necesito campañas de goteo ni pruebas A/B ni plantillas elegantes. Necesito una lista de direcciones de correo que yo posea.
42 líneas de código en lugar de otra suscripción mensual. A veces la solución simple es la correcta.
La conclusión: imperfecto y publicado supera a perfecto y planificado. Podría haber pasado horas evaluando servicios de newsletter, comparando características, leyendo reseñas. En cambio, lancé algo en 30 minutos y seguí adelante.