Meinen Eigenen Newsletter mit Claude Erstellen

Tag zwei des Hacker News Verkehrsansturms. Vierzigtausend Besucher, keine Möglichkeit, sie wieder zu erreichen. Ich brauchte eine Newsletter-Anmeldung.

Ich schaute mir Buttondown, Beehiiv, Substack, ConvertKit an. Alles übertrieben. Ich musste nur E-Mails sammeln. Ich brauchte keine Kampagnen, Analysen oder Abonnentenverwaltung. Und ich wollte meine Daten besitzen.

Also bat ich Claude, es zu bauen.

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)]

Die Einrichtung

Ich gab Claude ein Cloudflare API-Token über eine Umgebungsvariable und beschrieb, was ich wollte: ein Formular, das E-Mails sammelt und sie irgendwo speichert, wo ich die Kontrolle habe.

Weniger als 30 Minuten später hatte ich einen funktionierenden Newsletter.

Was Claude Gebaut Hat

KomponenteTechnologie
FormularHTML + vanilla JS
BackendCloudflare Worker
SpeicherCloudflare KV
SynchronisationGitHub Actions

Das Formular ist ein Hugo Partial, das an /api/subscribe sendet:

<form id="newsletter-form">
  <input type="email" name="email" placeholder="[email protected]" required>
  <button type="submit">Subscribe</button>
</form>

Das Backend ist ein 42-zeiliger Cloudflare Worker, der Validierung, Normalisierung, Duplikaterkennung und Referer-Bereinigung handhabt:

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" });
  }

  // Sanitize referer (strip query params for privacy)
  const referer = request.headers.get("Referer");
  const source = referer ? new URL(referer).origin + new URL(referer).pathname : "direct";

  // Store in KV with metadata
  await env.SUBSCRIBERS.put(emailKey, JSON.stringify({
    subscribedAt: new Date().toISOString(),
    source
  }));

  return Response.json({ success: true }, { status: 201 });
}

Die Ratenbegrenzung kommt von Cloudflares integriertem Schutz—kein zusätzlicher Code erforderlich.

Ein GitHub Actions Workflow läuft täglich, um Abonnenten von Cloudflare KV in eine JSONL-Datei im Repository zu synchronisieren. Meine Abonnentenliste lebt in der Versionskontrolle. Wenn Cloudflare morgen mein Konto schließt, habe ich immer noch meine Daten. Und sie sind in einem Format, mit dem LLMs leicht arbeiten können.

Der Workflow

Claude iterierte lokal, bis alles funktionierte—Formularübermittlung, KV-Speicher, Fehlerbehandlung. Dann auf eine Vorschau-App gepusht, den vollständigen Ablauf getestet und mit main zusammengeführt.

Das Formular ging live, während der Verkehr noch floss.

Das Ganze wurde in einer Sitzung gebaut.

Warum Kein SaaS?

Buttondown ist großartig, wenn man es braucht. Ich nicht. Meine Anforderungen:

  1. E-Mails sammeln
  2. Sie irgendwo speichern, wo ich die Kontrolle habe
  3. Schnell ausliefern

Das ist alles. Ich brauche keine Drip-Kampagnen oder A/B-Tests oder ausgefallene Vorlagen. Ich brauche eine Liste von E-Mail-Adressen, die mir gehört.

42 Zeilen Code statt eines weiteren monatlichen Abonnements. Manchmal ist die einfache Lösung die richtige.

Die Quintessenz: unvollkommen und live schlägt perfekt und geplant. Ich hätte Stunden damit verbringen können, Newsletter-Dienste zu bewerten, Funktionen zu vergleichen, Bewertungen zu lesen. Stattdessen habe ich in 30 Minuten etwas ausgeliefert und bin weitergegangen.