Создание Собственной Рассылки с Claude
Второй день всплеска трафика с Hacker News. Сорок тысяч посетителей, никакого способа связаться с ними снова. Мне нужна была форма подписки на рассылку.
Я посмотрел на Buttondown, Beehiiv, Substack, ConvertKit. Все излишне сложное. Мне нужно было только собирать электронные адреса. Мне не нужны были кампании, аналитика или управление подписчиками. И я хотел владеть своими данными.
Поэтому я попросил 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 токен Cloudflare API через переменную окружения и описал, что я хочу: форму, которая собирает электронные адреса и хранит их где-то, где я контролирую.
Менее чем через 30 минут у меня была работающая рассылка.
Что Построил Claude
| Компонент | Технология |
|---|---|
| Форма | HTML + vanilla JS |
| Бэкенд | Cloudflare Worker |
| Хранилище | Cloudflare KV |
| Синхронизация | GitHub Actions |
Форма — это частичный шаблон Hugo, который отправляет на /api/subscribe:
<form id="newsletter-form">
<input type="email" name="email" placeholder="[email protected]" required>
<button type="submit">Subscribe</button>
</form>
Бэкенд — это 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" });
}
// 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 });
}
Ограничение скорости исходит от встроенной защиты Cloudflare — дополнительный код не нужен.
Рабочий процесс GitHub Actions запускается ежедневно для синхронизации подписчиков из Cloudflare KV в файл JSONL в репозитории. Мой список подписчиков живет в системе контроля версий. Если Cloudflare завтра закроет мой аккаунт, у меня все еще есть мои данные. И они в формате, с которым LLM могут легко работать.
Рабочий Процесс
Claude итерировал локально, пока все не заработало — отправка формы, хранилище KV, обработка ошибок. Затем отправил в предварительную версию приложения, протестировал полный поток и слил с main.
Форма вышла в продакшен, пока трафик все еще шел.
Все это было построено за одну сессию.
Почему Не SaaS?
Buttondown отлично подходит, если вам это нужно. Мне нет. Мои требования:
- Собирать электронные адреса
- Хранить их где-то, где я контролирую
- Быстро развернуть
Вот и все. Мне не нужны капельные кампании или A/B-тестирование или причудливые шаблоны. Мне нужен список адресов электронной почты, который принадлежит мне.
42 строки кода вместо еще одной месячной подписки. Иногда простое решение — правильное.
Вывод: несовершенное и живое бьет совершенное и запланированное. Я мог бы потратить часы на оценку сервисов рассылок, сравнение функций, чтение отзывов. Вместо этого я развернул что-то за 30 минут и двинулся дальше.