Skip to content

Commit b780fce

Browse files
bndct-devopsclaude
andcommitted
Initial commit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
0 parents  commit b780fce

162 files changed

Lines changed: 44436 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docker.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Build and Push Docker Image
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ["v*"]
7+
workflow_dispatch:
8+
9+
env:
10+
REGISTRY: ghcr.io
11+
IMAGE_NAME: ${{ github.repository }}
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.12"
24+
cache: pip
25+
26+
- name: Install dependencies
27+
run: pip install '.[dev]'
28+
29+
- name: Run tests
30+
run: pytest tests/ -q
31+
32+
build:
33+
needs: test
34+
runs-on: ubuntu-latest
35+
permissions:
36+
contents: read
37+
packages: write
38+
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v4
42+
43+
- name: Set up Docker Buildx
44+
uses: docker/setup-buildx-action@v3
45+
46+
- name: Log in to GHCR
47+
uses: docker/login-action@v3
48+
with:
49+
registry: ${{ env.REGISTRY }}
50+
username: ${{ github.actor }}
51+
password: ${{ secrets.GITHUB_TOKEN }}
52+
53+
- name: Extract metadata
54+
id: meta
55+
uses: docker/metadata-action@v5
56+
with:
57+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
58+
tags: |
59+
type=ref,event=branch
60+
type=semver,pattern={{version}}
61+
type=semver,pattern={{major}}.{{minor}}
62+
type=sha,prefix=
63+
64+
- name: Build and push
65+
uses: docker/build-push-action@v6
66+
with:
67+
context: .
68+
push: true
69+
tags: ${{ steps.meta.outputs.tags }}
70+
labels: ${{ steps.meta.outputs.labels }}
71+
cache-from: type=gha
72+
cache-to: type=gha,mode=max

.gitignore

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Python
2+
.venv/
3+
__pycache__/
4+
*.pyc
5+
*.pyo
6+
*.egg-info/
7+
dist/
8+
build/
9+
.pytest_cache/
10+
11+
# Data (never commit your library or DB)
12+
data/
13+
books/
14+
bindery/
15+
library/
16+
incoming/
17+
*.db
18+
*.db-wal
19+
*.db-shm
20+
21+
# Frontend
22+
frontend/node_modules/
23+
frontend/dist/
24+
25+
# Env
26+
.env
27+
.env.*
28+
29+
# OS
30+
.DS_Store
31+
Thumbs.db
32+
33+
# IDE
34+
.idea/
35+
.vscode/
36+
*.swp
37+
38+
# Claude Code
39+
.claude/
40+
41+
# Docker (use docker-compose.example.yml as template)
42+
docker-compose.yml
43+
docker-compose.override.yml
44+
45+
# Local dev docs and scratch files
46+
CLAUDE.md
47+
AGENTS.md
48+
PLAN.md
49+
local/
50+
temp/
51+
docs/transfer.md
52+
scripts/tome_transfer.py

Dockerfile

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Build frontend
2+
FROM node:22-alpine AS frontend-build
3+
WORKDIR /app/frontend
4+
COPY frontend/package*.json ./
5+
RUN npm ci --legacy-peer-deps
6+
COPY frontend/ ./
7+
RUN npm run build
8+
9+
# Runtime
10+
FROM python:3.12-slim
11+
WORKDIR /app
12+
13+
RUN apt-get update && apt-get install -y --no-install-recommends unrar-free && rm -rf /var/lib/apt/lists/*
14+
15+
COPY pyproject.toml ./
16+
COPY backend/__init__.py ./backend/
17+
RUN pip install --no-cache-dir .
18+
19+
COPY backend/ ./backend/
20+
COPY alembic.ini ./
21+
COPY alembic/ ./alembic/
22+
COPY --from=frontend-build /app/frontend/dist ./frontend/dist
23+
24+
ENV TOME_DATA_DIR=/data \
25+
TOME_LIBRARY_DIR=/books \
26+
TOME_INCOMING_DIR=/bindery
27+
28+
RUN useradd -m -u 1000 tome \
29+
&& mkdir -p /data /books /bindery \
30+
&& chown tome:tome /data /books /bindery
31+
USER tome
32+
33+
VOLUME ["/data", "/books", "/bindery"]
34+
EXPOSE 8080
35+
36+
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8080"]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Tome Contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Tome
2+
3+
A self-hosted ebook library server. Scan, upload, browse, and read your entire collection from any device.
4+
5+
Built with FastAPI, React, and SQLite. Ships as a single Docker image.
6+
7+
> **Early release** -- actively developed, expect rough edges.
8+
9+
![Home](docs/screenshots/home.png)
10+
*Continue reading where you left off. Track streaks, pages, and reading time at a glance.*
11+
12+
## Highlights
13+
14+
- **Built-in reader** -- EPUBs, manga (CBZ/CBR), and PDFs render directly in the browser. Two-page spread, RTL mode, webtoon scroll, pinch-to-zoom on mobile. [Details](docs/reader.md)
15+
- **KOReader sync** -- custom TomeSync plugin syncs reading positions and sessions, works fully offline. [Details](docs/koreader-plugin.md)
16+
- **Bindery** -- an inbox for incoming books. Drop files in a folder, review pre-filled metadata, accept into your library. [Details](docs/bindery-deployment.md)
17+
- **Metadata from 3 sources** -- fetch and compare metadata from [Hardcover](https://hardcover.app), Google Books, and OpenLibrary with a side-by-side diff UI
18+
- **OPDS feed** -- browse and download from [KOReader](https://koreader.rocks), Panels, Chunky, or any OPDS client
19+
- **Reading stats** -- session tracking, streaks, time-of-day heatmaps, and charts
20+
- **9 themes** -- light, dark, Catppuccin (4 flavors), Nord, Neon, 8-bit
21+
22+
Plus: series browsing, bulk operations, libraries with icons, saved filters, Quick Connect (6-char code sign-in), OPDS PINs (e-ink-friendly passwords), granular user permissions, audit logging, and a bulk import script. [Full feature list](docs/features.md)
23+
24+
![Dashboard](docs/screenshots/dashboard.png)
25+
*Filter, sort, and browse your library. Bulk select for metadata edits, library assignment, or export.*
26+
27+
![Series Detail](docs/screenshots/series-detail.png)
28+
*Drill into a series to see every volume, track progress per book, and pick up where you stopped.*
29+
30+
![Book Detail](docs/screenshots/book-detail.png)
31+
*Full metadata view with cover, description, tags, and one-click reading.*
32+
33+
![Series](docs/screenshots/series.png)
34+
*All your series at a glance with volume counts and descriptions.*
35+
36+
![Stats](docs/screenshots/stats.png)
37+
*Reading activity, streaks, session history, and time-of-day patterns.*
38+
39+
### Mobile
40+
41+
Tome works as a PWA on mobile. Pin it to your home screen for a native app feel.
42+
43+
| | | | | |
44+
|---|---|---|---|---|
45+
| ![Home](docs/screenshots/mobile-home.png) | ![Stats](docs/screenshots/mobile-stats.png) | ![Sidebar](docs/screenshots/mobile-sidebar.png) | ![Series](docs/screenshots/mobile-series.png) | ![Reader](docs/screenshots/mobile-reader.png) |
46+
47+
## Quick Start
48+
49+
```bash
50+
docker run -d \
51+
-p 8080:8080 \
52+
-v /path/to/data:/data \
53+
-v /path/to/ebooks:/books:ro \
54+
-v /path/to/bindery:/bindery \
55+
-e TOME_SECRET_KEY=changeme \
56+
ghcr.io/benedictpetutschnig/tome
57+
```
58+
59+
Open `http://localhost:8080` and follow the setup wizard to create your admin account.
60+
61+
Or use Docker Compose -- copy `docker-compose.example.yml`, edit the values, and `docker compose up -d`.
62+
63+
### Volumes
64+
65+
| Mount | Purpose |
66+
|-------|---------|
67+
| `/data` | SQLite database and cover cache |
68+
| `/books` | Ebook library (read-only is fine) |
69+
| `/bindery` | Incoming folder for new books |
70+
71+
### Environment Variables
72+
73+
| Variable | Required | Default | Description |
74+
|----------|----------|---------|-------------|
75+
| `TOME_SECRET_KEY` | Yes | -- | JWT signing secret |
76+
| `TOME_DATA_DIR` | No | `/data` | DB and cover cache |
77+
| `TOME_LIBRARY_DIR` | No | `/books` | Library root |
78+
| `TOME_INCOMING_DIR` | No | `/bindery` | Bindery folder |
79+
| `TOME_PORT` | No | `8080` | HTTP port |
80+
| `TOME_HARDCOVER_TOKEN` | No | -- | [Hardcover](https://hardcover.app) API token for metadata |
81+
82+
### Supported Formats
83+
84+
| Format | Reader | Notes |
85+
|--------|--------|-------|
86+
| EPUB | Text reader | CFI position tracking |
87+
| CBZ | Comic reader | Streaming page delivery |
88+
| CBR | Comic reader | Auto-repacked to ZIP |
89+
| PDF | Browser viewer | Served directly |
90+
91+
## Development
92+
93+
Requirements: Python 3.12+, Node.js 18+
94+
95+
```bash
96+
./dev.sh # starts backend :8080 + frontend :5173
97+
```
98+
99+
| Layer | Technology |
100+
|-------|------------|
101+
| Backend | Python 3.12+ / FastAPI |
102+
| Database | SQLite (WAL) / SQLAlchemy 2.0 |
103+
| Frontend | React 19 / Vite / TypeScript |
104+
| Styling | Tailwind CSS 4 |
105+
| Auth | JWT (python-jose) |
106+
107+
Built with [Claude Code](https://claude.ai/code).
108+
109+
## Documentation
110+
111+
- [Reader](docs/reader.md) -- EPUB, comic/manga reader, keyboard shortcuts, ComicInfo.xml
112+
- [KOReader Plugin](docs/koreader-plugin.md) -- TomeSync setup, sync behavior, offline support
113+
- [Bindery](docs/bindery-deployment.md) -- setting up the incoming book inbox
114+
- [Import Script](docs/import.md) -- bulk importing an existing collection
115+
- [Features](docs/features.md) -- Quick Connect, OPDS PINs, permissions, themes, and more
116+
117+
## Acknowledgements
118+
119+
- [KOReader](https://koreader.rocks) -- the open source e-reader app that Tome's sync plugin and OPDS integration are built for
120+
- [Hardcover](https://hardcover.app) -- book metadata and cover art API
121+
- [foliate-js](https://github.com/johnfactotum/foliate-js) -- the EPUB rendering engine powering Tome's built-in reader
122+
123+
## License
124+
125+
MIT

0 commit comments

Comments
 (0)