API 在一个星期二上线了。我不知道谁会使用它。

我正在构建 NewTqnia,一个提供英语和阿拉伯语双语内容的科技出版物,需求不断扩大。网站、RSS、JSON API、可嵌入小部件、浏览器新标签页、结构化时间线——每一个都需要以不同方式交付相同的内容。

这引出了一个我至今仍没有明确答案的问题:

如何在不构建六个互不相连的产品的情况下,支持六种内容分发渠道?

这不是一个成功故事。它是一系列权衡,有些有效,有些值得商榷,还有一些我正在积极撤销。


API:有意保持精简

首个公开版本的 Daily Digest API 几乎什么都没做。

curl "https://newtqnia.com/v1/news/today?locale=en&limit=5"

Enter fullscreen mode Exit fullscreen mode

就是这样。todaylatest,两个查询参数,无需 API 密钥。每分钟 60 次请求,支持 ETag,合理的 Cache-Control

我本可以在第一天就发布分类、标签、搜索、推荐和分析端点。但一个拥有不稳定契约的大型 API,只不过是一个碰巧有公开文档的私有 API。我想要的正好相反:一个小型接口,即使有人真的基于它构建,也不会让我难堪。

尴尬之处在于:开发者无法请求他们不知道可能存在的端点。所以“等待需求”是安全的策略,但可能不是正确的策略。我仍在寻找“谨慎地精简”与“无用地精简”之间的界限。


小部件问题:隔离的代价

有些人只是想在自己的网站上展示标题,而不想编写 HTTP 客户端。于是我构建了一个脚本:

<script
  async
  src="https://newtqnia.com/news-widget.js"
  data-count="5"
  data-locale="en"
  data-layout="cards"
  data-orientation="horizontal"
  data-theme="auto"
  data-accent="#03c0f9"
  data-order="latest"
  data-show-image="true"
  data-show-summary="true">
</script>

Enter fullscreen mode Exit fullscreen mode

小部件生成器会生成这段代码并显示实时预览。

这里有一个没人警告过我的问题:每一种隔离策略都会将复杂性转移到别处。

  • Iframe? 样式隔离强,但响应式尺寸会变成与宿主页面的协商。
  • Shadow DOM? 防止 CSS 泄漏,但主题和无障碍遍历会变得奇怪。
  • 带作用域 CSS 的普通脚本? 对嵌入者来说熟悉,但宿主页面的一条 !important 规则就能让你的布局崩溃。

我目前选择了简单的脚本和 data-* 属性。我不认为这是长期答案。如果你发布过可嵌入小部件,我真诚地想知道:你是否后悔一开始没有使用 Web Components?


时间线不是文章

新闻文章描述一个时刻。时间线必须解释多年间这些时刻如何关联。

我们发布关于生成式 AI 的演进互联网的历史等主题的时间线。在内部,这些不是长文章,而是带有以下字段的事件集合:

  • 精确或近似日期
  • 事件类型和重要性级别
  • 主要和次要来源
  • 相关链接
  • 事件特定媒体
  • 双语标题和替代文本
  • 署名和许可

这使得内容可复用,但也引入了代码无法解决的编辑问题。当两个可靠来源对日期存在分歧时该怎么办?如何标记时间线为不完整而不损害其可信度?如何表示一个可信但次要的来源?

我对公开格式也不确定。自定义 JSON 易于设计。JSON-LD 或现有事件词汇表更难,但互操作性更强。如果你从 API 消费时间线数据,你更倾向于哪种?


双语支持始于数据模型

阿拉伯语不是“换成不同单词的英语”。它需要 RTL 布局、不同的排版、本地化日期,以及不一定与英语端镜像的界面决策。

对于结构化内容,最简单的模型是显式的双语字段:

{
  "title_en": "The Transformer rewrites the architecture of language AI",
  "title_ar": "بنية المحولات تعيد صياغة هندسة الذكاء الاصطناعي اللغوي"
}

Enter fullscreen mode Exit fullscreen mode

当你只有两种语言时,这很容易查询和验证。当有五到十种语言时,它会变得丑陋。规范化的翻译表扩展性更好,但会增加我目前不需要的连接、回退逻辑和发布状态复杂性。

我目前的规则是:在添加第三种语言之前重新考虑模型,而不是之前。过早规范化仍然是过早优化。


媒体意外成为一个子系统

当时间线开始使用事件特定图像时,仅存储单个 URL 已不够用。一个有用的媒体记录现在需要:

  • 稳定的内部 ID
  • 处理状态和响应式变体
  • 尺寸和文件类型
  • 双语替代文本和标题
  • 原始来源、署名和许可
  • 与时间线或单个事件的关联关系

图像被处理成多种尺寸和格式。事件引用内部资源,而不是外部 URL。这将无障碍元数据附加到它所描述的内容上,并避免将发布页面与第三方主机的正常运行时间绑定。

我无法自动化的部分:替代文本是否真正好。验证仅检查是否存在,不检查是否有用。


分发创建了署名边界

你让内容越便携,对其使用方式的控制就越少。

仅返回标题和 URL,API 几乎没用。返回完整文章,你就是在邀请未署名的再版。摘要是折中方案,但即使是摘要也会被聚合到无面目的信息流中。

目前 API 要求消费者保留文章 URL 并显示可见的署名。这是社会契约,而不是技术契约。我研究过签名内容、更严格的条款、计量访问和 API 密钥。每一种都会提高合法实验的成本。

如果你设计过公开内容 API,你是如何决定要给出多少内容的?


我会做不同的选择

  • 更早开始使用时间线数据模型。 先将时间线视为文章意味着我本可避免的一次迁移。
  • 更严格地质疑嵌入策略。 一个脚本标签感觉是简单路径,直到你在一个不控制的站点上调试 CSS 特异性。
  • 记录 API 的理念,而不仅仅是它的端点。 开发者需要在决定是否在其上构建之前了解它为什么小。

我卡住的问题

如果你要审查这个系统,我希望听到你对以下问题的看法:

  1. 范围蔓延: 一个小型 REST API 在什么时候需要分类、标签或搜索?
  2. 推送 vs. 拉取: 新故事的 webhook 是否有用,还是 RSS 已经解决了这个问题?
  3. 嵌入接口: data-* 脚本在 2026 年仍然是好的集成格式吗?
  4. Web Components: 它们真的解决了小部件隔离问题,还是只是转移了问题?
  5. 时间线格式: 你会如何在公开 API 中表示有来源的历史事件?
  6. 多语言模型: 支持未来扩展的最不复杂的模型是什么?
  7. 内容边界: 公开新闻 API 应该返回多少文章内容?
  8. 版本控制: 在 API 增长之前,我应该修复哪些缓存或契约错误?

你可以通过开发者页面小部件生成器和实时的时间线集合来查看当前实现。

如果这个系统中的某一部分值得被简化、替换或完全避免,那会是哪一部分?




Enter fullscreen mode Exit fullscreen mode