chore: reorganize docs, improve README, and add FOSS project hygiene

This commit is contained in:
neon
2026-05-13 01:35:58 -06:00
parent a64013a79d
commit 266b57c38a
17 changed files with 209 additions and 50 deletions
+3 -3
View File
@@ -13,9 +13,6 @@ BOOKS_HOST_PATH=./books
PUID=1000 PUID=1000
PGID=1000 PGID=1000
# Node.js JavaScript heap limit in MB. Raise this for very large libraries.
NODE_MAX_OLD_SPACE_SIZE=2048
# Database credentials # Database credentials
POSTGRES_USER=bookorbit POSTGRES_USER=bookorbit
POSTGRES_PASSWORD=change-this-password POSTGRES_PASSWORD=change-this-password
@@ -29,6 +26,9 @@ SETUP_BOOTSTRAP_TOKEN=change-this-to-a-long-random-secret
# External/public URL used by emails and Kobo endpoints # External/public URL used by emails and Kobo endpoints
APP_URL=https://bookorbit.example.com APP_URL=https://bookorbit.example.com
# Node.js JavaScript heap limit in MB. Raise this for very large libraries.
NODE_MAX_OLD_SPACE_SIZE=2048
# --- Optional overrides (uncomment to set) --- # --- Optional overrides (uncomment to set) ---
# If you already run your own PostgreSQL, set DATABASE_URL and remove the # If you already run your own PostgreSQL, set DATABASE_URL and remove the
+7
View File
@@ -1 +1,8 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links:
- name: Questions and Discussions
url: https://github.com/bookorbit/bookorbit/discussions
about: Ask questions, get help with your setup, or share how you use BookOrbit
- name: Documentation
url: https://bookorbit.app
about: Read the full documentation at bookorbit.app
+33
View File
@@ -0,0 +1,33 @@
server:
- changed-files:
- any-glob-to-any-file: "server/**"
client:
- changed-files:
- any-glob-to-any-file: "client/**"
packages:
- changed-files:
- any-glob-to-any-file: "packages/**"
docs:
- changed-files:
- any-glob-to-any-file: "docs/**"
- any-glob-to-any-file: "*.md"
ci:
- changed-files:
- any-glob-to-any-file: ".github/**"
- any-glob-to-any-file: "scripts/**"
- any-glob-to-any-file: "docker/**"
- any-glob-to-any-file: "Dockerfile"
- any-glob-to-any-file: "docker-compose*.yml"
dependencies:
- changed-files:
- any-glob-to-any-file: "package.json"
- any-glob-to-any-file: "pnpm-lock.yaml"
- any-glob-to-any-file: "pnpm-workspace.yaml"
- any-glob-to-any-file: "server/package.json"
- any-glob-to-any-file: "client/package.json"
- any-glob-to-any-file: "packages/*/package.json"
+20
View File
@@ -0,0 +1,20 @@
name: PR Labeler
on:
pull_request_target:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
label:
name: Label PR by Changed Paths
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml
+40
View File
@@ -0,0 +1,40 @@
name: Stale Issues and PRs
on:
schedule:
- cron: "0 3 * * *"
workflow_dispatch:
permissions:
issues: write
pull-requests: write
jobs:
stale:
name: Mark and Close Stale
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/stale@5bef64f19d7facfed25c7e059aefc10cb5ab2bf2 # v9
with:
days-before-issue-stale: 60
days-before-issue-close: 14
days-before-pr-stale: 30
days-before-pr-close: 14
stale-issue-label: stale
stale-pr-label: stale
exempt-issue-labels: "pinned,security"
exempt-pr-labels: pinned
stale-issue-message: >
This issue has been inactive for 60 days. It will be closed in 14 days
unless there is new activity. If this is still relevant, please leave a
comment or update the issue.
stale-pr-message: >
This PR has been inactive for 30 days. It will be closed in 14 days
unless there is new activity. If you are still working on this, please
leave a comment or push an update.
close-issue-message: >
Closing due to inactivity. Feel free to reopen if this is still relevant.
close-pr-message: >
Closing due to inactivity. Feel free to reopen if you want to continue
this work.
+71 -41
View File
@@ -1,21 +1,25 @@
<div align="center"> <div align="center">
<!-- Replace this with your logo once available -->
<img src="docs/logo.png" alt="BookOrbit" width="120" height="120" />
# BookOrbit # BookOrbit
A self-hosted library management and reading platform for epub, pdf, audiobooks, and comics. A self-hosted library management and reading platform for ebooks, PDFs, audiobooks, and comics.
[![Stars](https://img.shields.io/github/stars/bookorbit/bookorbit?style=flat)](https://github.com/bookorbit/bookorbit/stargazers)
[![CI](https://github.com/bookorbit/bookorbit/actions/workflows/ci.yml/badge.svg)](https://github.com/bookorbit/bookorbit/actions/workflows/ci.yml) [![CI](https://github.com/bookorbit/bookorbit/actions/workflows/ci.yml/badge.svg)](https://github.com/bookorbit/bookorbit/actions/workflows/ci.yml)
[![Release](https://github.com/bookorbit/bookorbit/actions/workflows/release.yml/badge.svg)](https://github.com/bookorbit/bookorbit/actions/workflows/release.yml) [![Release](https://github.com/bookorbit/bookorbit/actions/workflows/release.yml/badge.svg)](https://github.com/bookorbit/bookorbit/actions/workflows/release.yml)
[![Latest release](https://img.shields.io/github/v/release/bookorbit/bookorbit?label=latest)](https://github.com/bookorbit/bookorbit/releases) [![Latest release](https://img.shields.io/github/v/release/bookorbit/bookorbit?label=latest)](https://github.com/bookorbit/bookorbit/releases)
[![Commits/month](https://img.shields.io/github/commit-activity/m/bookorbit/bookorbit?label=commits%2Fmonth)](https://github.com/bookorbit/bookorbit/commits/main) [![Commits/month](https://img.shields.io/github/commit-activity/m/bookorbit/bookorbit?label=commits%2Fmonth)](https://github.com/bookorbit/bookorbit/commits/main)
[![Stars](https://img.shields.io/github/stars/bookorbit/bookorbit?style=flat)](https://github.com/bookorbit/bookorbit/stargazers)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](LICENSE)
[![Container image](https://img.shields.io/badge/ghcr.io-bookorbit%2Fbookorbit-informational?logo=docker&logoColor=white)](https://github.com/bookorbit/bookorbit/pkgs/container/bookorbit)
**[Documentation](https://bookorbit.app) · [Live Demo](https://demo.bookorbit.app) · [Report a Bug](https://github.com/bookorbit/bookorbit/issues/new?template=bug_report.yml) · [Request a Feature](https://github.com/bookorbit/bookorbit/issues/new?template=feature_request.yml)** <!--
[Website](https://bookorbit.app) · [Demo](https://demo.bookorbit.app) · [Discussions](https://github.com/bookorbit/bookorbit/discussions) · [Contributing](https://github.com/bookorbit/bookorbit/blob/main/docs/CONTRIBUTING.md) · [Changelog](https://github.com/bookorbit/bookorbit/releases)
-->
[![Website](https://img.shields.io/badge/Website-bookorbit.app-blue?style=flat&logo=googlechrome&logoColor=white)](https://bookorbit.app)
[![Demo](https://img.shields.io/badge/Demo-live-brightgreen?style=flat&logo=rocket&logoColor=white)](https://demo.bookorbit.app)
[![Discussions](https://img.shields.io/badge/Discussions-GitHub-333?style=flat&logo=github&logoColor=white)](https://github.com/bookorbit/bookorbit/discussions)
[![Contributing](https://img.shields.io/badge/Contributing-guide-orange?style=flat&logo=handshake&logoColor=white)](https://github.com/bookorbit/bookorbit/blob/main/docs/CONTRIBUTING.md)
[![GHCR](https://img.shields.io/badge/GHCR-bookorbit/bookorbit-blue?style=flat&logo=docker&logoColor=white)](https://github.com/bookorbit/bookorbit/pkgs/container/bookorbit)
</div> </div>
@@ -25,60 +29,86 @@ A self-hosted library management and reading platform for epub, pdf, audiobooks,
--- ---
## About ## What is BookOrbit?
BookOrbit is a self-hosted book and library manager. Deploy it once on your own server and get a full reading platform: built-in readers, rich metadata, reading statistics, device sync, and multi-user support - all running on your hardware. BookOrbit is a self-hosted digital library and reading platform. Organize and read your books, sync seamlessly with Kobo and KOReader devices, enrich your collection with metadata from multiple providers, and support multiple users with OIDC/SSO authentication and detailed reading statistics. Built-in features include OPDS support, customizable dashboard widgets, Send-to-Kindle delivery, and Smart Scopes for dynamic rule-based shelves and filters - all running on infrastructure you control.
No subscription. No third-party account. No data leaving your server.
---
## Live Demo
Try BookOrbit without installing anything. The demo is pre-loaded with a sample library and resets automatically.
**[Open demo](https://demo.bookorbit.app/magic?token=2d92cb900e184cf0eb8b11f72cffc6011673d1016e1b300d750eb3d76abc1572)** - no account needed, click the link to log in automatically.
--- ---
## Features ## Features
- **4 built-in readers** - eBook (EPUB, KEPUB, MOBI, AZW3, FB2), PDF, Comics (CBZ, CBR, CB7), Audiobook (M4B, MP3, FLAC, and more) **Built-in readers** - no plugins or extra installs required:
- **Multiple libraries** with independent scan rules, format priorities, and metadata configuration
- **Collections and Smart Scopes** - curated lists and saved filters that live in your sidebar | Reader | Formats |
- **Metadata from 9 providers** - Google Books, Goodreads, Hardcover, Amazon, Audible, ComicVine, and more; with field-level rules and confidence scoring | --------- | --------------------------------- |
- **Reading statistics** - daily time, heatmap, streaks, pace, goal tracking, and library health | eBook | EPUB, KEPUB, MOBI, AZW3, AZW, FB2 |
- **Kobo sync** - sideload books and sync reading position over the local network | PDF | PDF |
- **OPDS, email delivery, and Book Dock** for getting books in from anywhere | Comics | CBZ, CBR, CB7 |
- **Multi-user** with per-user permissions, isolated reading data, and OIDC/SSO support | Audiobook | M4B, MP3, M4A, OPUS, OGG, FLAC |
**Multiple libraries:** Per-library folders, scan rules, format priorities, metadata config, and file-write settings.
**Metadata from 9 providers:** Google Books, Amazon, Goodreads, Hardcover, Open Library, iTunes, Audible, AudNexus, and ComicVine - with field-level rules.
**Collections and Smart Scopes:** Curated lists and rule-based saved filters in the sidebar.
**Kobo and KOReader sync:** Auto-push books to Kobo; two-way reading progress sync via KOReader over OPDS.
**OPDS, email delivery, and Book Dock:** OPDS for compatible apps, Send-to-Kindle via email, and browser drag-and-drop uploads.
**Multi-user with multi-provider OIDC/SSO:** Granular per-user permissions, isolated reading data, and simultaneous support for Authentik, Keycloak, Authelia, etc.
**Reading statistics:** Daily reading time, heatmap, streaks, pace, goal tracking, and library health dashboard.
--- ---
## Setup ## Live Demo
See the **[Installation guide](https://bookorbit.app/installation.html)** for Docker setup, NAS installs, environment variables, and upgrade instructions. Try BookOrbit without installing anything.
**[Open Demo](https://demo.bookorbit.app/magic?token=2d92cb900e184cf0eb8b11f72cffc6011673d1016e1b300d750eb3d76abc1572)** - no account needed, the link logs you in automatically.
The demo is pre-loaded with a sample library of public domain books and resets automatically.
--- ---
## Documentation ## Quick Start
Full documentation is at **[bookorbit.app](https://bookorbit.app)**. ```bash
mkdir bookorbit && cd bookorbit
mkdir -p books data/app data/postgres
curl -fsSLo .env https://raw.githubusercontent.com/bookorbit/bookorbit/main/.env.example
curl -fsSLo docker-compose.yml https://raw.githubusercontent.com/bookorbit/bookorbit/main/docker-compose.yml
```
> [What is BookOrbit?](https://bookorbit.app/what-is-bookorbit.html) &nbsp;·&nbsp; [Installation](https://bookorbit.app/installation.html) &nbsp;·&nbsp; [Creating a Library](https://bookorbit.app/creating-a-library.html) &nbsp;·&nbsp; [Metadata](https://bookorbit.app/metadata.html) &nbsp;·&nbsp; [Kobo Sync](https://bookorbit.app/kobo.html) &nbsp;·&nbsp; [Users & Permissions](https://bookorbit.app/users.html) Edit `.env` and set these required values:
```dotenv
APP_URL=http://your-server-ip:3000 # the URL you'll open in your browser
BOOKS_HOST_PATH=./books # folder on your server where your book files live
POSTGRES_PASSWORD= # database password - openssl rand -hex 24
JWT_SECRET= # signs login tokens - openssl rand -hex 32
SETUP_BOOTSTRAP_TOKEN= # one-time setup wizard token - openssl rand -hex 16
```
Then start:
```bash
docker compose up -d
```
Open `http://your-server-ip:3000` and complete setup using your `SETUP_BOOTSTRAP_TOKEN`.
For the full installation guide including reverse proxy setup, file permissions on NAS, external databases, and environment variable reference, see **[bookorbit.app/installation](https://bookorbit.app/installation.html)**.
--- ---
## Developing ## Documentation and Contributing
See **[DEVELOPMENT.md](DEVELOPMENT.md)** for local setup, architecture, project structure, database workflow, and commands. See **[TESTING.md](TESTING.md)** for test suites, coverage, and E2E details. Full documentation is at **[bookorbit.app](https://bookorbit.app)** - covering libraries, metadata, readers, Kobo sync, OPDS, users and permissions, OIDC setup, and more.
--- For local development, see [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md). To contribute, see [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) for the full workflow: branch naming, test expectations, PR checklist, and commit format.
## Contributing
Contributions are welcome. For the full contribution workflow (branch naming, test expectations, PR checklist, commit format), see **[CONTRIBUTING.md](CONTRIBUTING.md)**.
To report a security vulnerability, use [GitHub's private vulnerability reporting](https://github.com/bookorbit/bookorbit/security/advisories/new) - do not open a public issue.
--- ---
+10
View File
@@ -1,8 +1,18 @@
{ {
"name": "client", "name": "client",
"version": "0.0.0", "version": "0.0.0",
"description": "BookOrbit client - self-hosted library management and reading platform",
"author": "neonsolstice",
"private": true, "private": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"homepage": "https://bookorbit.app",
"repository": {
"type": "git",
"url": "https://github.com/bookorbit/bookorbit"
},
"bugs": {
"url": "https://github.com/bookorbit/bookorbit/issues"
},
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
View File
+1 -1
View File
@@ -379,7 +379,7 @@ Releases are created manually via `workflow_dispatch` on the `release.yml` workf
PR titles are validated by commitlint to ensure they follow the [commit guidelines](COMMIT_GUIDELINES.md). Only releasable types (`feat`, `fix`, `perf`, `security`, `db`, `style`) trigger version bumps. PR titles are validated by commitlint to ensure they follow the [commit guidelines](COMMIT_GUIDELINES.md). Only releasable types (`feat`, `fix`, `perf`, `security`, `db`, `style`) trigger version bumps.
For the full release runbook, see [`docs/release-process.md`](docs/release-process.md). For the full release runbook, see [`docs/RELEASE_PROCESS.md`](docs/RELEASE_PROCESS.md).
### E2E in CI ### E2E in CI
@@ -22,7 +22,7 @@ All PRs to `main` must use **squash merge**. The squash commit message becomes t
### PR title format ### PR title format
PR titles must follow the [commit guidelines](../COMMIT_GUIDELINES.md): PR titles must follow the [commit guidelines](COMMIT_GUIDELINES.md):
``` ```
<type>(<scope>): <summary> <type>(<scope>): <summary>
View File
+11
View File
@@ -1,5 +1,16 @@
{ {
"name": "bookorbit", "name": "bookorbit",
"description": "Self-hosted library management and reading platform for ebooks, PDFs, audiobooks, and comics",
"author": "neonsolstice",
"license": "AGPL-3.0",
"homepage": "https://bookorbit.app",
"repository": {
"type": "git",
"url": "https://github.com/bookorbit/bookorbit"
},
"bugs": {
"url": "https://github.com/bookorbit/bookorbit/issues"
},
"private": true, "private": true,
"packageManager": "pnpm@10.32.1", "packageManager": "pnpm@10.32.1",
"scripts": { "scripts": {
+10 -2
View File
@@ -1,10 +1,18 @@
{ {
"name": "server", "name": "server",
"version": "0.0.1", "version": "0.0.1",
"description": "", "description": "BookOrbit server - self-hosted library management and reading platform",
"author": "", "author": "neonsolstice",
"private": true, "private": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"homepage": "https://bookorbit.app",
"repository": {
"type": "git",
"url": "https://github.com/bookorbit/bookorbit"
},
"bugs": {
"url": "https://github.com/bookorbit/bookorbit/issues"
},
"scripts": { "scripts": {
"prestart": "pnpm --filter @bookorbit/types build", "prestart": "pnpm --filter @bookorbit/types build",
"prestart:dev": "pnpm --filter @bookorbit/types build", "prestart:dev": "pnpm --filter @bookorbit/types build",
@@ -387,7 +387,7 @@ export class UserStatisticsRepository {
.from(readingSessions) .from(readingSessions)
.innerJoin(bookFiles, eq(bookFiles.id, readingSessions.bookFileId)) .innerJoin(bookFiles, eq(bookFiles.id, readingSessions.bookFileId))
.innerJoin(books, eq(books.id, bookFiles.bookId)) .innerJoin(books, eq(books.id, bookFiles.bookId))
.where(and(eq(readingSessions.userId, userId), gte(readingSessions.endProgress, 100), libraryFilter)) .where(and(eq(readingSessions.userId, userId), gte(readingSessions.endProgress, 99), libraryFilter))
.groupBy(bookFiles.bookId) .groupBy(bookFiles.bookId)
.as('first_completion'); .as('first_completion');
@@ -467,7 +467,7 @@ export class UserStatisticsRepository {
.from(readingSessions) .from(readingSessions)
.innerJoin(bookFiles, eq(bookFiles.id, readingSessions.bookFileId)) .innerJoin(bookFiles, eq(bookFiles.id, readingSessions.bookFileId))
.innerJoin(books, eq(books.id, bookFiles.bookId)) .innerJoin(books, eq(books.id, bookFiles.bookId))
.where(and(eq(readingSessions.userId, userId), gte(readingSessions.startedAt, since), gte(readingSessions.endProgress, 100), libraryFilter)) .where(and(eq(readingSessions.userId, userId), gte(readingSessions.startedAt, since), gte(readingSessions.endProgress, 99), libraryFilter))
.groupBy(bookFiles.bookId) .groupBy(bookFiles.bookId)
.as('completed_in_window'); .as('completed_in_window');