| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A directory of podcasts that live on their own domain.
Of the 4.7M feeds in the Podcast Index, ~40% sit on Anchor alone and the ten largest hosts carry about three quarters of everything. This lists the remainder: 21,628 shows on 13,408 distinct domains, each publishing from a domain its creator controls.
A feed is listed when it:
93% of live feeds already sit on a domain in the global top million, because they are all on the same twenty platforms. Domain popularity measures the platform, never the show, and the domains absent from those rankings are precisely the independent ones. It is used here only inverted, as one signal for identifying platforms to exclude.
Next.js (App Router) on Node, Turso/libSQL, deployed on Railway. Search is SQLite FTS5; raw input is tokenised before it reaches MATCH, since FTS5 treats punctuation as query syntax and would otherwise 500.
Every show page carries its full episode list, read live from the publisher's own feed and cached for half an hour — nothing about episodes is stored here. Playing one hands it to a player that lives in the root layout and keeps running while you move around the site, which is why every internal link is a next/link: a plain <a href> reloads the document and takes the audio with it.
About 8% of the directory still serves its mp3s over plain http, which a browser on an https page refuses to play and no CSP can permit. Those go through /api/audio, which streams them over TLS with Range passed through in both directions. The URL is HMAC-signed with AUTH_SECRET so the route cannot be used as an open proxy.
A publisher's feed is the slowest thing on a show page, so the episode list is wrapped in <Suspense> and streams in behind the rest of the page: first byte stays ~100ms whether the feed answers in 200ms or nine seconds.
Emailed magic link plus passkeys, the house pattern — there is no password. Opening the link is the registration, so an unknown address makes the account; /signup and /login are the same component with different wording. The endpoint answers "if that address can receive mail, a link is on its way" whether or not the address is known, whether it was rate limited, and even when Resend is down, so it cannot be used to enumerate who has an account.
Signed-in state is fetched from /api/me in the browser rather than read from cookies in the root layout. A single cookies() call there would opt all 22k show pages out of static rendering.
Create the tables with node scripts/migrate_auth.mjs (safe to re-run). They live in the same Turso database as podcasts but the directory rebuild never touches them, and follows keys shows by slug — the reload reassigns podcasts.id, so a numeric key would silently repoint everyone's follows at other shows.
| Variable | Needed for |
|---|---|
| TURSO_DATABASE_URL, TURSO_AUTH_TOKEN | the database; falls back to ./data/p0dcasters.db |
| AUTH_SECRET | session and audio-proxy signing. Required in production |
| RESEND_API_KEY | sending the magic link. Without it, outside production, the link is printed to the console instead |
python3 ../p0dcasters-data/export_indie.py # writes p0dcasters.db
turso db shell p0dcasters < dump.sql/crawlstats is the status board for the pipeline above, with /api/crawlstats as the same figures in JSON. It exists because that pipeline can die without anything looking wrong: the site keeps serving, the shows are all still there, and they quietly describe a directory that stopped being true weeks ago. Nothing about that is visible from outside.
The page answers four questions — is the cron check still running, when did a rebuild last land, what did it change, and how much of the directory is drifting towards the 90-day cutoff — plus a freshness histogram, per-category sizes with a sparkline per row, the most recently published shows, and the ones closest to being dropped.
Two things shape how it is built:
Its history comes from refresh_runs, written by the pipeline itself — see scripts/README.md. Create the table with node scripts/migrate_runs.mjs, and do not add it to the rebuild's drop list: like the account tables it has to survive a reload, because it is the only record of anything that happened before the current directory existed.
| Back | FazBrowse Home | New Git URL |