The API went live on a Tuesday. I had no idea who would use it.
I was building NewTqnia, a bilingual technology publication in English and Arabic, and the requirements kept expanding. Website, RSS, JSON API, embeddable widget, browser new-tab page, structured timelines—each one wanted the same content delivered differently.
That raised a question I still don’t have a clean answer to:
How do you support six delivery surfaces without building six disconnected products?
This is not a success story. It’s a set of tradeoffs, some working, some questionable, and a few I’m actively looking to undo.
The API: small on purpose
The first public version of the Daily Digest API does almost nothing.
curl "https://newtqnia.com/v1/news/today?locale=en&limit=5"
That’s it. today, latest, two query params, no API key. Sixty requests per minute, ETag support, sensible Cache-Control.
I could have shipped categories, tags, search, recommendations, and analytics endpoints on day one. But a large API with unstable contracts is just a private API that happens to have public documentation. I wanted the opposite: a small surface that would not embarrass me if someone actually built against it.
The awkward part? Developers can’t ask for endpoints they don’t know are possible. So “wait for demand” is a safe strategy, but maybe not the right one. I’m still figuring out where the line is between “prudently small” and “uselessly small.”
The widget problem: isolation is expensive
Some people just want headlines on their site without writing HTTP clients. So I built a script:
<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>
The widget builder generates this and shows a live preview.
Here is the part nobody warned me about: every isolation strategy moves complexity somewhere else.
- Iframe? Strong style isolation, but responsive sizing becomes a negotiation with the host page.
- Shadow DOM? Protects against CSS leaks, but theming and accessibility traversal get weird.
-
Plain script with scoped CSS? Familiar to embedders, but one
!importantrule on the host side and your layout collapses.
I went with the simple script and data-* attributes for now. I’m not convinced it’s the long-term answer. If you’ve shipped an embeddable widget, I’d genuinely like to know: did you regret not using Web Components from the start?
Timelines are not articles
A news article describes a moment. A timeline has to explain how moments relate across years.
We publish timelines on things like the evolution of generative AI and the history of the Internet. Internally, these are not long articles. They are collections of events with fields like:
- Exact or approximate dates
- Event types and importance levels
- Primary and secondary sources
- Related links
- Event-specific media
- Bilingual captions and alt text
- Attribution and licensing
This makes the content reusable, but it also introduces editorial problems that code can’t solve. What do you do when two reputable sources disagree on a date? How do you mark a timeline as incomplete without undermining it? How do you represent a source that is credible but secondary?
I’m also unsure about the public format. Custom JSON is easy to design. JSON-LD or an existing event vocabulary is harder but more interoperable. If you were consuming timeline data from an API, which would you prefer?
Bilingual support starts in the data model
Arabic is not “English with different words.” It needs RTL layout, different typography, localized dates, and interface decisions that don’t always mirror the English side.
For structured content, the simplest model is explicit bilingual fields:
{
"title_en": "The Transformer rewrites the architecture of language AI",
"title_ar": "بنية المحولات تعيد صياغة هندسة الذكاء الاصطناعي اللغوي"
}
This is easy to query and validate when you have exactly two languages. It becomes ugly at five or ten. A normalized translation table scales better, but it adds joins, fallback logic, and publishing-state complexity that I don’t need yet.
My current rule: reconsider the model before adding a third language, not before. Premature normalization is still premature optimization.
Media became a subsystem by accident
Once timelines started using event-specific images, storing a single URL wasn’t enough. A useful media record now needs:
- A stable internal ID
- Processing status and responsive variants
- Dimensions and file type
- Bilingual alt text and captions
- Original source, attribution, and licensing
- A relationship to either a timeline or an individual event
Images are processed into multiple sizes and formats. Events reference the internal asset, not an external URL. This keeps accessibility metadata attached to the thing it describes, and it avoids tying published pages to the uptime of some third-party host.
The part I can’t automate: whether the alt text is actually good. Validation checks for presence. It does not check for usefulness.
Distribution creates an attribution boundary
The more portable you make content, the less control you have over how it’s used.
Return only a title and URL, and the API is barely useful. Return full articles, and you’re inviting unattributed republication. Summaries are a middle ground, but even summaries get aggregated into faceless feeds.
Right now the API asks consumers to preserve article URLs and display visible attribution. That is a social contract, not a technical one. I’ve looked at signed content, stricter terms, metered access, and API keys. Each one raises the cost of legitimate experimentation.
If you’ve designed a public content API, how did you decide how much to give away?
What I would do differently
- Start with the timeline data model earlier. Treating timelines as articles first meant a migration I could have avoided.
- Question the embed strategy harder. A script tag feels like the easy path until you’re debugging CSS specificity on a site you don’t control.
- Document the API’s philosophy, not just its endpoints. Developers need to know why it’s small before they decide whether to build on it.
Questions I’m stuck on
If you were reviewing this system, I’d value your take on:
- Scope creep: At what point does a small REST API need categories, tags, or search?
- Push vs. pull: Would webhooks for new stories be useful, or does RSS already solve that?
-
Embed interfaces: Is a
data-*script still a good integration format in 2026? - Web Components: Do they actually solve the widget isolation problem, or just shift it?
- Timeline formats: How would you represent sourced historical events in a public API?
- Multilingual models: What is the least complicated model that still supports future expansion?
- Content boundaries: How much article content should a public news API return?
- Versioning: Which caching or contract mistakes should I fix before the API grows?
You can poke at the current implementation through the developer page, the widget builder, and the live timeline collection.
If one part of this system deserves to be simplified, replaced, or avoided entirely, which one is it?
Top comments (0)