explainroo
explainroo is a free, open source tool that lets your AI agent make explainer videos with a voice. It runs on your own computer and needs no API key.
翻訳待ち
An open, agent-first directory of independent blogs. Submit a URL, a list or an OPML file; every blog gets its own page. JSON API, OPML and llms.txt for agents.
翻訳待ち
Loading the full README.
Read the full README ↗An open, agent-first directory of independent blogs.
Submit a URL, a list of URLs or an OPML file. We resolve it to a feed, read it, and give the blog a
permanent page at /<slug> with its latest summaries. No account, no paywall, no waiting list.
The point of difference is the machine-readable half: most of the web now blocks AI crawlers, and this directory deliberately does the opposite. Everything is also published as JSON, OPML and plain text so an agent can read the whole thing in one request.
Live: https://rssamp.com
A pnpm workspace. Both deployables run in Docker on Railway.
apps/web/ Next.js — public pages, JSON API, agent surfaces, PWA
apps/poller/ Crawler daemon — re-fetches feeds on a backoff schedule
apps/cli/ @profullstack/rssamplifier — the directory from a terminal
packages/feed/ Feed discovery, RSS/Atom/JSON Feed parsing, OPML, SSRF guards
packages/ingest/ Submit + crawl orchestration
packages/db/ PostgreSQL client, schema and every query
packages/notify/ Alerts — web push, email digests and webhooks
packages/social/ X and Reddit: canonical identity, and X's provider adapters
Everything outside the Next app is plain ESM with JSDoc types — no build step, so Docker stays
simple and node --test runs the suites directly.
pnpm install
cp .env.example .env # DATABASE_URL=postgres://... (see packages/db/migrations-pg/README.md for a local docker one)
pnpm dev # web on :3000
pnpm poll # crawler, in a second terminal
pnpm test # 42 tests
The poller applies migrations on boot. To run them by hand:
pnpm --filter @rssamplifier/db migrate
| Path | What |
|---|---|
/ | Directory index, newest first |
/<slug> | One blog: metadata plus its latest posts |
/search?q= | Full-text search (Postgres tsvector) |
/submit | Submission form — URLs or an OPML upload |
/discover | Keyword search — name a subject, we go and find blogs about it |
/discoveries/{id} | Progress of one keyword run: what was added, and why the rest was not |
/crawlstats | Crawler and discovery queues, live (/crawlstatus redirects here) |
/random | Redirect to a random blog — the toolbar's ✦ |
/r | Every subreddit and Reddit user in the directory |
/r/<subreddit> | One community: /r/programming, .rss .atom .json .md |
/r/u/<user> | One Reddit user, under the same prefix |
/x | Every X account, search and list in the directory |
/x/<handle> | One timeline: /x/OpenAI, plus /replies and /media |
/x/list/<id> | One X list |
/x/search?q= | An X search as a feed — X's own operators pass through |
/x/status | Which provider is collecting X, and how it is doing |
/ig | Every Instagram account and hashtag in the directory |
/ig/<handle> | One account: /ig/nasa, and /ig/tag/<tag> for a hashtag |
/fb | Facebook Pages whose operators have connected them |
/fb/<page> | One connected Page |
Reddit and X both live under a prefix of their own, and for the same reason from opposite directions. Reddit publishes real RSS, so a subreddit resolves down the ordinary path and lands as an untyped row at a slug of its own — which is how 50,099 of them ended up filed among the blogs. X publishes nothing at all, so without a provider it is not submittable in the first place.
Instagram is X's shape again — no feeds, collected through RSSHub — and cost almost nothing to add, which is the point of having built the namespace once. Facebook is its own thing entirely; see below.
packages/social answers one question for all four: what is the canonical
identity of this thing? @OpenAI, x.com/OpenAI and https://twitter.com/openai/ are
one source (x:user:openai, at /x/OpenAI); /r/programming, /r/Programming/
and /r/programming/new/.rss are one community (r:sub:programming, at
/r/programming). One identity means one row, which means one polling job no
matter how many people subscribe — the thing that matters most when the
upstream rate-limits per account.
A social source is an ordinary row in feeds, not a parallel sources table.
That is what lets it inherit dedupe, backoff, interval learning, keyword
extraction, full-text search, alerts, sitemaps and all five syndication formats
without a line of X-specific code in any of them — and it is why an X post can
appear in /topics/artificial-intelligence.rss beside a blog post with nothing
to tell them apart.
/{slug} still answers for both, and always will: it is the permanent identity
of a row and links already point at it. The /r/ and /x/ address is the
canonical one, which is what search engines are told.
/fb/ is honestly worthFacebook publishes nothing readable without a login. Three doors, measured on 2026-08-29 rather than assumed:
facebook.com/feeds/page.php?format=rss20 endpoint answers 404 —
removed, not deprecatedmbasic.facebook.com/<page> answers 200 and redirects to login.phpSo a Page is read the way X and Instagram are read: with a logged-in session,
off the HTML that mbasic.facebook.com still renders server-side.
FB_COOKIE='c_user=...; xs=...' # a normal browser session, not an app
FB_PAGE_TOKENS= # optional; see below
Where a Page Access Token happens to exist for a Page, Meta's Graph API is used instead — a supported API beats guessing at markup. It is never required and almost never present, because Graph only returns a Page's posts to somebody who administers that Page.
This is the beginning of the README. Read the rest at the original. Read the full README ↗