Self-hosted academic publication tracker. Track Google Scholar profiles, discover new papers automatically, resolve open-access PDFs, and stay on top of the literature you care about.
| .github/workflows | ||
| alembic | ||
| app | ||
| scripts | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .python-version | ||
| AGENTS.MD | ||
| alembic.ini | ||
| docker-compose.yml | ||
| Dockerfile | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
scholarr
API-first, self-hosted scholar tracking backend in the spirit of the *arr ecosystem.
The legacy server-rendered UI has been removed. This repository now focuses on core ingestion, scheduling, and multi-user API functionality.
Current Scope
- Multi-user accounts with admin-managed user lifecycle
- Same-origin cookie sessions with CSRF enforcement
- API auth flows (login, logout, me, password change)
- Admin user management API
- Scholar CRUD per user
- Per-user ingestion settings
- Manual runs with idempotency support
- Run history, run detail diagnostics, and continuation queue actions
- Publication listing (
new/all) and mark-all-read - Ingestion scheduler + continuation queue retries
- Structured logging with request IDs + redaction
- PostgreSQL + Alembic migrations
- Container-first development workflow with
uv
Functionality Tracking
Planned and supported backend functionality is tracked in:
AGENTS.MD
API Base
- Base path:
/api/v1 - Success envelope:
{"data": ..., "meta": {"request_id": "..."}}
- Error envelope:
{"error": {"code": "...", "message": "...", "details": ...}, "meta": {"request_id": "..."}}
Auth & Session Model
- Session transport: same-origin cookie session (
HttpOnly,SameSite=Lax) - CSRF:
- Required for unsafe methods (
POST,PUT,PATCH,DELETE) viaX-CSRF-Token - Bootstrap token via
GET /api/v1/auth/csrf
- Required for unsafe methods (
API Surface
- Auth:
GET /api/v1/auth/csrfPOST /api/v1/auth/loginGET /api/v1/auth/mePOST /api/v1/auth/change-passwordPOST /api/v1/auth/logout
- Admin users:
GET /api/v1/admin/usersPOST /api/v1/admin/usersPATCH /api/v1/admin/users/{id}/activePOST /api/v1/admin/users/{id}/reset-password
- Scholars:
GET /api/v1/scholarsPOST /api/v1/scholarsPATCH /api/v1/scholars/{id}/toggleDELETE /api/v1/scholars/{id}
- Settings:
GET /api/v1/settingsPUT /api/v1/settings
- Runs:
GET /api/v1/runsGET /api/v1/runs/{id}POST /api/v1/runs/manual(Idempotency-Keysupported)GET /api/v1/runs/queue/itemsPOST /api/v1/runs/queue/{id}/retryPOST /api/v1/runs/queue/{id}/dropDELETE /api/v1/runs/queue/{id}
- Publications:
GET /api/v1/publicationsPOST /api/v1/publications/mark-all-read
- Ops:
GET /healthz
Quick Start
- Copy environment defaults:
cp .env.example .env
- Optional bootstrap admin on startup:
export BOOTSTRAP_ADMIN_ON_START=1
export BOOTSTRAP_ADMIN_EMAIL=admin@example.com
export BOOTSTRAP_ADMIN_PASSWORD=change-me-now
- Start stack:
docker compose up --build
- Health check:
http://localhost:8000/healthz
Admin Bootstrap (Manual)
docker compose run --rm app uv run python scripts/bootstrap_admin.py \
--email admin@example.com \
--password change-me-now \
--force-password
Test Workflow
- Unit tests:
docker compose run --rm app uv run pytest tests/unit
- Integration tests:
docker compose run --rm app uv run pytest -m integration
- Smoke checks:
./scripts/smoke_compose.sh
Logging
Configurable env vars:
LOG_LEVEL(defaultINFO)LOG_FORMAT(consoleorjson, defaultconsole)LOG_REQUESTS(1/0, default1)LOG_UVICORN_ACCESS(1/0, default0)LOG_REQUEST_SKIP_PATHS(default/healthz)LOG_REDACT_FIELDS(additional redact keys)
Project Layout
app/ FastAPI app (API routers, auth, services, db, middleware)
alembic/ Migration environment and versions
scripts/ Entrypoint, db wait/bootstrap, smoke automation
tests/ Unit, integration, and smoke suites
planning/ Scope and implementation planning notes