Создание Собственной Рассылки с Claude

Второй день всплеска трафика с Hacker News. Сорок тысяч посетителей, но нет способа снова их достучаться. Мне нужна была форма подписки на рассылку.

Я посмотрел на Buttondown, Beehiiv, Substack, ConvertKit. Всё избыточно. Мне просто нужно было собирать email-адреса. Мне не нужны были кампании, аналитика или управление подписчиками. И я хотел владеть своими данными.

Поэтому я попросил Claude построить это.

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

Настройка

Я передал Claude токен API Cloudflare через переменную окружения и описал, что мне нужно: форма, которая собирает email-адреса и хранит их там, где я контролирую.

Менее чем через 30 минут у меня была рабочая рассылка.

Что Построил Claude

КомпонентТехнология
ФормаHTML + vanilla JS
BackendCloudflare Worker
ХранилищеCloudflare KV
СинхронизацияGitHub Actions

Форма — это Hugo partial, который отправляет POST на /api/subscribe:

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

Backend — это Cloudflare Worker на 42 строки:

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

Workflow GitHub Actions запускается ежедневно для синхронизации подписчиков из Cloudflare KV в файл JSONL в репозитории. Мой список подписчиков живет в системе контроля версий. Если Cloudflare закроет мой аккаунт завтра, у меня всё равно будут мои данные. И они в формате, с которым LLM могут легко работать.

Рабочий Процесс

Claude итерировал локально, пока всё не заработало — отправка формы, хранение в KV, обработка ошибок. Затем запушил в preview-приложение, протестировал полный процесс и смержил в main.

Форма вышла в production, пока трафик ещё шёл.

Всё это было построено за одну сессию.

Почему Не SaaS?

Buttondown отличный, если он вам нужен. Мне не нужен. Мои требования:

  1. Собирать email-адреса
  2. Хранить их там, где я контролирую
  3. Быстро запустить

Вот и всё. Мне не нужны drip-кампании или A/B тесты или красивые шаблоны. Мне нужен список email-адресов, которым я владею.

42 строки кода вместо ещё одной месячной подписки. Иногда простое решение — правильное.

Вывод: несовершенное и запущенное побеждает совершенное и запланированное. Я мог бы потратить часы на оценку сервисов рассылок, сравнение функций, чтение отзывов. Вместо этого я запустил что-то за 30 минут и двинулся дальше.