@banou/stub
v0.0.57
Published
Anime, shows and movies in one place: every source merged into one page per title, played and tracked on your own accounts.
Readme
Stub
Anime, shows and movies in one place. stub gathers the sites you would otherwise check one by one into a single page per title, then plays and tracks it on your own accounts. It runs on the FKN platform, which carries its requests, installs the sources you add and holds the rooms for watch parties, so stub has no server of its own.
- Live at anime.fkn.app, and inside FKN at fkn.app/app/npm:@banou/stub
- Published on npm as
@banou/stub
Features
- One page per title. AniList, MyAnimeList, Kitsu, LiveChart, TMDB, TVmaze, IMDb, Trakt, Simkl, TheTVDB and more are merged into one page: episodes, trailers, scores, related titles and every place to watch it.
- Search everything at once, or browse a season by genre, tag, format, status and year, shown as covers, cards or a list.
- Watch on your own accounts. Crunchyroll plays in stub's own player on your Crunchyroll account, Netflix through the FKN browser extension, and your volume carries over from one episode to the next.
- Movies get a page of their own, with the runtime, the release date and one Play button.
- Track as you watch. One row updates AniList, MyAnimeList, Crunchyroll and stub's own list together; hover a tracker to change just that one. A movie is a single Watched button.
- Watch together. Share a party link and every guest's player follows the host's, with a chat.
- Your sources, your way. Turn any built-in source off in Settings, or add community sources published on npm, each running isolated from stub.
- No API keys, no stub account, no analytics. Your settings stay in your browser, and your list can live in your FKN account, encrypted in your browser before it leaves.
How it is built
- UI: Preact, routed with wouter and styled with Emotion, in
src/routerandsrc/components. urql is the GraphQL client. - Data: a GraphQL Yoga server in a Web Worker (
src/worker), reached from the page over osra. The schema is the.gqlfiles undersrc, andnpm run gql-generatewrites the types tosrc/generated. - Sources: one extractor per source,
src/sources/<name>/extractor.ts, listed insrc/sources/index.ts. Every request goes throughcloud.fetchfrom@fkn/lib. - Merge:
src/worker/storejoins the answers that describe the same title into one record. It lives in memory, so a reload starts fresh. - Player:
@banou/media-playeron its own page (embed.html,src/embed.tsx). - Docs:
docs/is a Starlight site that maps how data moves through stub, with diagrams.
Development
Use Node 24 (.node-version names 24.21.0, which CI uses).
npm ci
npm run data:build # the anime id data, from the newest anime-offline-database release
npm run gql-generate # the GraphQL types, into src/generated
npm run dev # http://localhost:4560npm run data:build-offline rebuilds the anime data from the last download instead of fetching it.
npm run type-check
npm run test:unit # vitest, tests/unit
npm test # the unit tests, a test build, then the Playwright specs in tests/*.spec.ts
npm run build # the app and the npm entry, into build/The Playwright specs run against a test server on port 7357, which playwright.config.ts starts.
A push to main publishes to npm when package.json names a version the registry does not have yet
(.github/workflows/publish-lib.yml).
The docs site
cd docs
npm install
npm run dev # http://localhost:4321
npm run buildnpm run check builds the site and checks every diagram in a real browser. docs/README.md covers
what it needs and how to write a page.
Writing a source
A source you add is an npm package that FKN runs isolated from stub and connects to it.
examples/source-plugin is a working one, a tiny static catalogue. Its contract is StubSource in
src/plugin-api.ts, and the docs site's Plugin sources page (docs/src/content/docs/request/plugins.md)
covers what stub checks on a source. Publish it with the keywords in the example's package.json and
it shows up under Browse sources in Settings. While you work on one, Settings also takes a local dev
address such as localhost:4599.
Privacy
stub has no accounts and no server of its own, and runs no analytics. What it fetched stays in the
tab's memory until you reload. Your settings stay in your browser, and stub's list moves to your FKN
account only when you choose to, encrypted in your browser first. Sign-ins to Crunchyroll, AniList and
MyAnimeList are kept by FKN, or by your browser with the FKN extension, never by stub. The
privacy page lists everything stub keeps, where and for how long
(src/router/privacy).
License
MIT, see LICENSE.
