An unofficial static mirror of SeaDex (source), the anime release recommendation index. Built as a static site so the data stays accessible even when the original is down.
Live site: seadex.pages.dev
flowchart LR
A[SeaDex API] --> B[Build Script]
C[AniList API] --> B
B --> D[Static JSON]
D --> E[Vite Build]
E --> F[Cloudflare Pages]
The build script pulls all public entry and torrent data from the SeaDex PocketBase API, enriches it with AniList metadata (titles, covers, scores, relations), and writes everything as static JSON files. Vite bundles the frontend, and the result gets deployed to Cloudflare Pages as a fully static site.
No database, no server-side runtime, no API keys required for browsing.
Prerequisites: Node.js 24+
git clone https://github.com/EithonX/seadex-mirror.git
cd seadex-mirror
npm install
npm run devTo build with live data from upstream:
npm run data:build
npm run dev| Command | What it does |
|---|---|
npm run dev |
Start the Vite dev server |
npm run build |
Build a deployable site snapshot |
npm run build:frontend |
Build only the frontend |
npm run data:build |
Fetch live data from SeaDex + AniList |
npm run build:site |
Build data and frontend together |
npm run deploy |
Deploy to Cloudflare Pages |
npm run typecheck |
Run TypeScript type checking |
npm run verify:mirror-data |
Verify generated JSON structure |
npm run verify:frontend-build |
Verify production build output |
The build script (scripts/build-static-data.mjs):
- Fetches entry IDs from the
listIDsendpoint - Fetches all entries with expanded torrent data (
expand=trs) - Verifies parity between the two data sources
- Resolves relative torrent URLs against
https://releases.moe - Fetches AniList metadata for each entry
- Enriches franchise relation data for entry detail pages
- Writes static JSON files into
frontend/public/mirror-data/
| File | Used by |
|---|---|
catalog.json |
Home page — table filtering and search |
entries/<alId>.json |
Individual entry pages |
sheet-workbook.json |
Sheet view (lazy-loaded separately) |
status.json |
Mirror freshness indicator |
The data builder supports two modes when upstream data hasn't changed:
--onUnchanged=skip— For scheduled CI rebuilds. Exits early without rebuilding or deploying.--onUnchanged=materialize— For deploy builds. Reconstructs local data from cache when upstream is unchanged but local files are missing (e.g. fresh CI checkout).
Deployed to Cloudflare Pages through GitHub Actions using Wrangler Direct Upload.
| Secret | Purpose |
|---|---|
CLOUDFLARE_ACCOUNT_ID |
Cloudflare account identifier |
CLOUDFLARE_API_TOKEN |
API token with Pages deploy permissions |
| Secret / Variable | Purpose |
|---|---|
CLOUDFLARE_PAGES_PROJECT_NAME |
Pages project name (default: seadex) |
ANILIST_ACCESS_TOKEN |
Authenticated AniList access for higher rate limits |
rebuild-mirror.yml runs every 12 hours. Only rebuilds and deploys when upstream data actually changed. Supports a manual force trigger.
deploy-site.yml runs on pushes to main that touch frontend code, scripts, or build config. Uses --onUnchanged=materialize so frontend-only changes still deploy with complete data.
| Path | TTL |
|---|---|
catalog.json, status.json, sheet-workbook.json |
60 seconds |
entries/* |
15 minutes |
| Hashed frontend assets | Immutable |
See CONTRIBUTING.md for setup instructions and guidelines.