**English** | [中文](README.zh.md) # AnimeGo A full-stack anime discovery, tracking, and local playback platform. Browse seasonal anime, manage your watchlist, play local video files with matched danmaku (bullet comments), and connect with other fans. **Live:** [animegoclub.com](https://animegoclub.com) --- ## Project Status > **The Go + Next.js stack is the canonical production branch.** > `main` is the stable/production branch — only tested, reviewed code lands here; production deploys from `main`. `feat/go-backend` is the active development branch where new work is staged before merging into `main`. > The legacy Express + MongoDB + Vite SPA stack was fully retired on 2026-06-01. There is no longer a `client/` or `server/` directory in this repository. **Status:** Live in production (cut over 2026-05-31; legacy retired 2026-06-01) **Migration started:** 2026-05-10 (from v2.0.0 baseline) **Production stack:** Next.js 16 + Bun + Go 1.26 (chi + pgx + sqlc) + PostgreSQL 16 + Node ws-server (Socket.IO) **Built with:** Claude Code (AI-assisted; product direction, decisions, and deployment by the author) ### Branch model | Branch | Purpose | |--------|---------| | `main` | Stable / production. Deploys from here. Only merges in after testing + review. | | `feat/go-backend` | Active development. New features and fixes land here first. | ### Known limitations (intentional, not bugs) - **Danmaku matching** — accuracy is not pursued to 100%; users fall back to the manual per-episode picker for uncommon sequels. See `feedback_danmaku_matching` in the project memory for the reasoning (no LLM/AI matching by design). - **Bangumi enrichment** — background pipeline; newly released anime may take a cycle before Chinese titles/scores appear. - **Single-instance WebSocket** — Socket.IO danmaku does not scale horizontally without Redis adapter. See TODO.md item 5. - **No user privacy toggle** — watchlists at `/u/:username` are publicly visible by design in this phase. See TODO.md item 4. ### Local development 1. Read this README + [CHANGELOG.md](CHANGELOG.md) (most recent 2-3 entries give you the current mental model). 2. Read [TODO.md](TODO.md) to see what was intentionally deferred. 3. `cp .env.example .env && bash scripts/dev.sh` — verify the stack boots locally. 4. SSH to VPS, `docker compose ps` — verify production is healthy. 5. Re-read [DESIGN.md](DESIGN.md) before touching UI. --- ## Features ### Browse & Discover - **Seasonal anime** — filter by genre, format, status; sort by score/title/format - **Trending** — top anime ranked by subscriber count - **Annual rankings** — top rated anime of the current year - **Completed gems** — highly rated finished series, refreshable - **Weekly schedule** — airing times for current season - **Search** — full-text search with genre filters - **Anime detail** — hero banner, dual scores (AniList + Bangumi), synopsis, characters, staff, relations, recommendations - **Episode titles** — sourced from Bangumi with automatic offset normalization for sequels ### Track & Watch - **Subscription system** — watching / completed / plan to watch / dropped - **Episode progress** — track current episode, highlight watched episodes - **Continue watching** — homepage section showing in-progress anime with progress bars - **Torrent search** — aggregate magnet links from ACG.rip RSS, filter by fansub group ### Local Player with Danmaku - **Drag & drop** — drop an anime folder or select video files (MKV, MP4, AVI, WebM) - **Automatic danmaku matching** — file hash + filename matching via dandanplay API, with multi-phase fallback (hash match -> keyword match -> per-file match) - **MKV subtitle extraction** — embedded ASS/SSA/SRT subtitles extracted in-browser via Web Worker, auto-converted to VTT - **Per-episode danmaku picker** — manually set or change the danmaku source for any episode; search any anime on dandanplay and pick the exact episode - **Non-blocking playback** — video plays immediately; subtitles and danmaku load asynchronously in the background - **Episode navigation** — switch episodes without leaving the player ### Community - **Danmaku** — real-time bullet comments overlaid on episode sections (Socket.IO) - **Episode comments** — threaded comments per episode with replies and likes - **Follow system** — follow other users, see their activity in your feed - **Public profiles** — `/u/:username` with watchlist, anime stats, and follower/following counts - **Activity feed** — recent subscription updates from followed users - **Share** — Web Share API with clipboard fallback ### SEO & Social - **Server-rendered meta** — full crawler HTML with structured data (JSON-LD), OG tags, breadcrumbs - **Dynamic sitemap** — auto-generated from database, sorted by score, dynamic priority - **Content-rich pages** — anime detail pages include characters, staff, relations for search indexing - **Google Search Console** verified ### Admin Dashboard - **Enrichment monitor** — real-time queue status for Phase 1-3, Phase 4, and V3 pipelines - **Inline editing** — edit Chinese titles and Bangumi IDs directly - **V3 self-heal** — batch heal missing Chinese titles with progress bar, pause/resume - **User management** — create, edit, delete users; view subscriptions and followers ### Internationalization - Full Chinese/English UI — toggle with persistent preference - `pickTitle()` selects the best title based on current language --- ## Tech Stack | Layer | Technology | |-------|-----------| | Frontend | React 19 · Next.js 16 (App Router, RSC) · Bun 1.3.x · libass-wasm · artplayer · dandanplay-vi | | Backend | Go 1.26 · chi router · pgx v5 · sqlc · river queue · ristretto cache | | Database | PostgreSQL 16 · pg_cron · pg_trgm | | Realtime | ws-server — standalone Node + socket.io process | | Auth | JWT (access 15m + refresh 30d, one session per device) · bcrypt · httpOnly cookies | | Player | Artplayer · libass-wasm (ASS subtitles) · Web Workers (MD5 hash, MKV parsing) | | External APIs | AniList GraphQL · Bangumi API · dandanplay API · ACG.rip RSS | | Deployment | Docker Compose · Nginx reverse proxy · Cloudflare · SSL | | SEO | Server components on `/anime/:id`, `/seasonal`, `/search` · Dynamic sitemap · JSON-LD · OG tags | --- ## Quick Start Fresh clone to `http://localhost:3000` should take under 5 minutes on a clean macOS box. ### Prerequisites Install once: ```bash # Docker Desktop (Postgres container) brew install --cask docker # Bun 1.3+ (Next.js runtime + ws-server) curl -fsSL https://bun.sh/install | bash # Go 1.26+ (go-api) and Air (hot reload) brew install go go install github.com/cosmtrek/air@latest ``` > `scripts/setup.sh` automates this for Debian 12 VPS bootstrap (Docker + UFW). For local macOS dev, run the three commands above once. ### Install & Run ```bash # 1. Copy env template and fill secrets (JWT, dandanplay app id/secret) cp .env.example .env # 2. One-shot dev loop: brings up Postgres, runs go-api with Air, # ws-server (Bun + socket.io), and next-app (Bun + Next.js 16). bash scripts/dev.sh ``` Open `http://localhost:3000`. ### Local prod stack (`docker compose` HTTPS via nginx) To exercise the production layout (nginx routing next-app + go-api + ws-server, self-signed SSL, full docker stack) before deploying to the VPS: ```bash # 1. Generate the local self-signed cert (one-time per machine). bash scripts/gen-local-cert.sh # 2. Copy and fill the prod env template. cp .env.production.example .env.production # ⚠️ Required: ALLOWED_HOSTS=animegoclub.com,localhost,app # ⚠️ Required: DATABASE_URL=postgres://animego:password@postgres:5432/animego # 3. Build + bring up the full stack (next-app, go-api, ws-server, postgres, nginx). docker compose --env-file .env.production up -d --build # 4. Open https://localhost (accept the self-signed cert warning). ``` ### Dev Ports | Port | Service | Notes | |------|---------|-------| | 3000 | next-app | App Router frontend (RSC) | | 3001 | ws-server | socket.io danmaku | | 8080 | go-api | chi + pgx | | 5432 | postgres | primary datastore | ### Environment Variables `.env.example` documents every key with a comment. The required block: ```env # Shared JWT_SECRET=fill-with-32-byte-random-hex JWT_REFRESH_SECRET=fill-with-another-32-byte-random-hex JWT_EXPIRES_IN=15m JWT_REFRESH_EXPIRES_IN=30d DANDANPLAY_APP_ID=fill-with-your-app-id DANDANPLAY_APP_SECRET=fill-with-your-secret # Postgres (Go API) — matches docker-compose.dev.yml POSTGRES_PASSWORD=devpassword DATABASE_URL=postgres://animego:devpassword@localhost:5432/animego?sslmode=disable PORT_GO=8080 ``` > dandanplay API credentials can be obtained at [api.dandanplay.net](https://api.dandanplay.net/). --- ## Docker Deployment ```bash docker compose --env-file .env.production up -d --build ``` Services: `go-api` · `next-app` · `ws-server` · `postgres` (16) · `nginx` --- ## Architecture ``` Browser │ (local video files stay in the browser — bytes never touch the server) │ Cloudflare │ nginx (reverse proxy + SSL, origin locked to Cloudflare ranges) ├── / → next-app (Next.js 16 SSR — all user-facing routes) ├── /api/ → go-api (Go 1.26, chi router) └── /socket.io/ → ws-server (Node + socket.io — real-time danmaku) go-api ├── PostgreSQL 16 (pg_cron · pg_trgm — cache + user data + danmaku) ├── AniList GraphQL ├── Bangumi API ├── dandanplay API (offline cross-check oracle for enrichment bindings) └── ACG.rip RSS ``` next-app serves every user-facing route via SSR: home, `/anime/:id`, `/seasonal`, `/search`, `/login`, `/library`, `/player`, `/admin`, `/u/:username`. ### Data Pipeline 1. **AniList fetch** — seasonal/search/detail queries with 700 ms throttle 2. **PostgreSQL** — single primary datastore; pg_cron handles danmaku TTL cleanup 3. **Bangumi enrichment** — background pipeline via river queue, progressing through four confidence gates: - **v0** — raw AniList data, no Chinese title - **v1** — bind to the correct Bangumi subject via an authoritative AniList↔Bangumi id-map plus a confidence-gated fuzzy scorer; low-confidence bindings are parked for human review, never auto-guessed ("rather show romaji than a wrong Chinese title") - **v2** — Bangumi score, character Chinese names, episode titles - **v3** — terminal Chinese-title heal via direct `bgmId` lookup 4. **dandanplay** — independent offline cross-check oracle for binding validation; not on the request hot path 5. **Priority queue** — user-requested anime jumps to the front of the enrichment queue ### Danmaku Matching Flow 1. **File parsing** — extract episode numbers from filenames (supports `[Group] Title - 01.mkv`, `S01E01`, `EP01`, etc.) 2. **Hash computation** — MD5 of first 16 MB via Web Worker (matches dandanplay spec) 3. **Three-phase matching** — hash+filename combined match -> keyword match -> per-file hash fallback 4. **Episode mapping** — dandanplay episode IDs mapped to local files, with OVA/SP support (`O1`, `S1` patterns) 5. **Comment fetch** — danmaku loaded by dandanplay episode ID, rendered via Artplayer danmaku plugin ### Auth Flow - `accessToken` — JWT, 15 min TTL, stored in memory only (never localStorage) - `refreshToken` — JWT, 14 day TTL, stored in httpOnly cookie - SSR-aware silent refresh: Next.js middleware reads the cookie server-side and refreshes before rendering protected pages - bcrypt for password hashing --- ## API Endpoints All responses follow: `{ data }` · `{ data, pagination }` · `{ error: { code, message } }` | Route | Description | |-------|-------------| | `POST /api/auth/register` | Register | | `POST /api/auth/login` | Login | | `POST /api/auth/refresh` | Refresh access token | | `POST /api/auth/logout` | Logout | | `GET /api/auth/me` | Current user | | `GET /api/anime/seasonal` | Seasonal anime | | `GET /api/anime/search` | Search anime | | `GET /api/anime/schedule` | Weekly schedule | | `GET /api/anime/trending` | Trending (by subscribers) | | `GET /api/anime/:id` | Anime detail | | `GET /api/anime/:id/watchers` | Users watching | | `GET /api/anime/torrents` | Torrent search | | `GET/POST/PATCH/DELETE /api/subscriptions` | Watchlist CRUD | | `GET/POST/DELETE /api/comments` | Episode comments | | `GET/POST/DELETE /api/users/:username/follow` | Follow system | | `GET /api/feed` | Activity feed | | `POST /api/dandanplay/match` | Match anime by hash/filename | | `GET /api/dandanplay/search` | Search anime on dandanplay | | `GET /api/dandanplay/episodes/:animeId` | Get episode list | | `GET /api/dandanplay/comments/:episodeId` | Get danmaku comments | | `WS /` | Socket.IO — danmaku events | Rate limit: 100 requests / 15 min / IP on all `/api` routes. --- ## Testing ```bash # Go API tests cd go-api && go test ./... # Next.js (next-app) tests — Bun's built-in test runner cd next-app && bun test ``` --- ## Credits - [AniList](https://anilist.co/) — anime metadata and GraphQL API - [Bangumi](https://bgm.tv/) — Chinese titles, scores, characters, and episode data - [dandanplay](https://www.dandanplay.com/) — danmaku matching API and episode comment database. Special thanks to the dandanplay developers for their support. - [ACG.rip](https://acg.rip/) — torrent RSS feed - [bangumi-data](https://github.com/bangumi-data/bangumi-data) — the AniList / Bangumi → Mikan Project id map behind the magnet search's per-show Mikan feeds (`go-api/internal/mikanidmap/mikan_map.json`, regenerated weekly), used under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) --- ## Contributing AnimeGo is open source under the **GNU AGPL-3.0** license, and contributions are welcome. By submitting a pull request you agree to license your contribution under AGPL-3.0 and to sign off on the [Developer Certificate of Origin](DCO) (`git commit -s`). Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR. Note that the torrent/magnet metadata-search subsystem is **out of scope** for external contributions — bug reports via issues are welcome, but code PRs for that area are not accepted. See also our [Code of Conduct](CODE_OF_CONDUCT.md) and [Security Policy](SECURITY.md). --- ## License AnimeGo is licensed under the **GNU Affero General Public License v3.0** (AGPL-3.0). You may use, study, modify, and redistribute it under the terms of that license; in particular, if you run a modified version as a network service, you must make your modified source available to its users. See [LICENSE](LICENSE) for the full text. © 2026 lawrenceli0228 (AnimeGo · animegoclub.com). This license covers only the original code in this repository, not the third-party data/APIs it integrates (AniList, Bangumi, bangumi-data, MyAnimeList, dandanplay, ACG.rip), which remain subject to their owners' terms.