Related content
GET /content/<slug>/related returns a small list of items related to the current one. V1 uses tag and channel overlap; later versions add explicit pins and signal aggregation.
Purpose
A detail page needs a "see also" rail. The simplest useful relationship is structural: items sharing tags or channels. That's cheap, predictable, and hits ~80% of the UX value with ~20% of the complexity.
Contract reference: AgnosticUI.md §14.
V1 contract
GET /content/<slug>/related?limit=10
Response: { success: true, data: ContentDto[] } (no pagination — fixed-size result).
Max limit: 20. Default: 10.
Scoring (v1)
For a content item X with tags = T and channelSlug = C:
score(Y) = 2 × (Y.channelSlug === C ? 1 : 0)
+ (count of tags shared between X.tags and Y.tags)
Exclusions:
Y._id === X._idY.approvalStatus !== 'approved'Y.isActive !== true
Candidates with score 0 are dropped. Ties broken by approvedAt descending.
Why this formula
- Channel overlap is a strong signal (same editorial cluster), weighted 2.
- Shared tags is weaker but compositional; summed directly.
- Formula is a dot product — trivial to compute, trivial to index.
- Not personalized — deliberately. Personalization is a different product.