用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

表单是一个发送到/api/subscribe的Hugo partial:

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

后端是一个42行的Cloudflare Worker,处理验证、规范化、重复检测和引用来源清理:

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很棒。我不需要。我的要求:

  1. 收集电子邮件
  2. 将它们存储在我控制的地方
  3. 快速发布

就是这样。我不需要滴灌营销活动或A/B测试或花哨的模板。我需要一个我拥有的电子邮件地址列表。

42行代码而不是另一个月度订阅。有时简单的解决方案就是正确的。

要点:不完美但上线胜过完美但计划中。我本可以花几个小时评估新闻通讯服务、比较功能、阅读评论。相反,我在30分钟内发布了一些东西并继续前进。