You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(social): Reddit lives at /r/, X lives at /x/, and X gets providers
Two namespaces, and one package that answers the same question for both:
what is the canonical identity of a thing on a platform?
Reddit needed only a name. It publishes real RSS, so a subreddit resolved
down the ordinary path and landed as an untyped row at a slug of its own —
which is how 50,099 of them ended up filed among the blogs, 41% of the
crawl queue. They are not moved or renamed: the migration gives them an
identity, /r/programming answers, and /{slug} keeps working for every link
already pointing at it.
X needed the rest. It publishes nothing, so posts are collected through a
provider stack — RSSHub, then Teapot, then the official API — with session
rotation, cooldowns, failover and spend caps. The provider appears in no
public URL, so the collection method can be replaced under a live
subscriber without their reader noticing.
The design decision worth stating: a social source is an ordinary row in
`feeds`, not the parallel `sources`/`items` pair the PRD sketches. That
pair already exists here, carrying dedupe, backoff, interval learning,
keyword extraction, FTS, alerts, sitemaps and five syndication formats —
so an X post reaches /topics/*.rss beside a blog post with no code in the
topic path that knows X exists.
- packages/social: canonicalisation for both platforms; X providers,
session pool, registry with failover, post normalisation
- migration: social_network/social_ref/social_config on feeds, provider
and session health tables (no credentials: those stay in the
environment), and a deterministic backfill of the existing subreddits
- crawl: a third ingestion path beside fetch and scrape, on a five-minute
floor rather than the directory's hourly one
- web: /r, /r/<sub>, /r/u/<user>, /x, /x/<handle>, /x/<handle>/replies,
/x/<handle>/media, /x/list/<id>, /x/search, /x/status — each with
.rss/.atom/.json/.md, canonical tags, and an offer to add what is not
here yet
- rivers now answer If-None-Match with a 304, computed before the ad
fetch so an unchanged feed never meters an impression it did not deliver
Not built: the /admin/x buttons of §34. There is no notion of an
administrator in this codebase to guard them with, and shipping a kill
switch anyone can pull is worse than not shipping one. X_ENABLED and
X_PRIMARY_PROVIDER cover it without a code deploy; /x/status is the
read-only half.
64 new tests, all 12 packages green under Node 22 and 24.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q6QEgpuS4MLamogXtr2ZX6
0 commit comments