# Mangalord A self-hosted manga and comics reader. Browse, search, read, bookmark, and upload manga and chapters. The HTTP API is consumed by both the SvelteKit web UI and external bots/scripts that perform the same actions programmatically. ## Stack - **Backend**: Rust, axum, sqlx - **Database**: Postgres 16 - **Frontend**: SvelteKit 2 (Svelte 5 runes), TypeScript, Vite - **File storage**: pluggable `Storage` trait — local FS today, S3 (and friends) as future impls - **Deploy**: Docker Compose on a single server ## Quick start ```bash cp .env.example .env docker compose up --build ``` - Frontend: http://localhost:3000 - API: http://localhost:8080/api - API health: http://localhost:8080/api/health ## Local development Run only Postgres in Docker; run backend and frontend natively for fast iteration: ```bash docker compose -f docker-compose.dev.yml up -d # backend cd backend export DATABASE_URL=postgres://mangalord:mangalord@localhost:5432/mangalord cargo run # frontend (separate shell) cd frontend npm install npm run dev ``` The Vite dev server proxies `/api` to `http://localhost:8080`. ## Tests This project is developed test-first. Tests live at three levels: ```bash # Backend: unit (in-module) + integration (tests/, per-test DB via #[sqlx::test]) cd backend && cargo test # Frontend: unit / module tests (Vitest) cd frontend && npm test # Frontend: end-to-end (Playwright; spins up dev server, mocks API by default) cd frontend && npm run test:e2e ``` ## API surface | Method | Path | Purpose | | ------ | ------------------- | -------------------------------------- | | GET | `/api/health` | Liveness | | GET | `/api/mangas` | List / search mangas | | POST | `/api/mangas` | Create a manga | | GET | `/api/mangas/{id}` | Get a manga | | GET | `/api/files/{key}` | Stream a blob (cover, chapter page) | Chapters, uploads, and bookmarks are next — the patterns to extend are documented in [`CLAUDE.md`](./CLAUDE.md).