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.
Find a file
2026-02-17 21:59:41 +01:00
.github/workflows streamlined 2026-02-17 21:59:41 +01:00
alembic streamlined 2026-02-17 21:59:41 +01:00
app streamlined 2026-02-17 21:59:41 +01:00
frontend streamlined 2026-02-17 21:59:41 +01:00
scripts streamlined 2026-02-17 21:59:41 +01:00
tests streamlined 2026-02-17 21:59:41 +01:00
.dockerignore streamlined 2026-02-17 21:59:41 +01:00
.env.example streamlined 2026-02-17 21:59:41 +01:00
.gitignore streamlined 2026-02-17 21:59:41 +01:00
.python-version First product 2026-02-17 14:51:25 +01:00
AGENTS.MD test 2026-02-17 20:24:12 +01:00
alembic.ini First product 2026-02-17 14:51:25 +01:00
CONTRIBUTING.md streamlined 2026-02-17 21:59:41 +01:00
docker-compose.dev.yml test 2026-02-17 20:24:12 +01:00
docker-compose.yml streamlined 2026-02-17 21:59:41 +01:00
Dockerfile test 2026-02-17 20:24:12 +01:00
pyproject.toml test 2026-02-17 20:24:12 +01:00
README.md streamlined 2026-02-17 21:59:41 +01:00
uv.lock test 2026-02-17 20:24:12 +01:00

scholarr

Self-hosted scholar tracking with a single app image (API + frontend).

CI Docker Pulls Docker Image

Quick Start

  1. Copy env template:
cp .env.example .env
  1. Set required values in .env:
  • POSTGRES_PASSWORD
  • SESSION_SECRET_KEY
  1. Choose a deploy method below.

Use this for normal self-hosted deployment.

docker compose pull
docker compose up -d

Open:

  • App/API: http://localhost:8000
  • Health: http://localhost:8000/healthz

Upgrade:

docker compose pull
docker compose up -d

Deploy Method B: Local Source Build + Dev Frontend

Use this for development on this repository.

docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build

Open:

  • API (FastAPI): http://localhost:8000
  • Frontend dev server (Vite): http://localhost:5173

Stop:

docker compose -f docker-compose.yml -f docker-compose.dev.yml down

Essential Files

  • docker-compose.yml: deployment compose (prebuilt image).
  • docker-compose.dev.yml: dev override (source mounts + Vite dev server).
  • .env.example: full env variable template.
  • Dockerfile: multi-stage build (frontend + backend runtime).
  • README.md: deployment and operations reference.
  • CONTRIBUTING.md: contribution policy and merge checklist.
  • scripts/check_no_generated_artifacts.sh: tracked-artifact guard used by CI.

Environment Variables (Complete Reference)

Notes:

  • Boolean envs accept: 1/0, true/false, yes/no, on/off.
  • Values shown are defaults from .env.example.
  • deploy means used in regular deployment.
  • dev means used in local dev workflow.

Core Compose and Database

Variable Default Options Scope Description
POSTGRES_DB scholar any valid DB name deploy, dev PostgreSQL database name.
POSTGRES_USER scholar any valid DB user deploy, dev PostgreSQL user.
POSTGRES_PASSWORD change-me strong password deploy, dev PostgreSQL password. Required.
DATABASE_URL postgresql+asyncpg://scholar:scholar@db:5432/scholar valid SQLAlchemy asyncpg URL deploy, dev, test App database connection URL.
TEST_DATABASE_URL empty valid SQLAlchemy asyncpg URL test Optional explicit integration test DB URL.
SCHOLARR_IMAGE justinzeus/scholarr:latest any image ref deploy App image tag used by deployment compose.

App Runtime and Networking

Variable Default Options Scope Description
APP_NAME scholarr any string deploy, dev FastAPI app name/title.
APP_HOST 0.0.0.0 bind host deploy, dev Uvicorn bind host inside container.
APP_PORT 8000 integer deploy, dev Uvicorn bind port inside container.
APP_HOST_PORT 8000 integer deploy, dev Host port mapped to app container port 8000.
APP_RELOAD 0 boolean deploy, dev Enable uvicorn reload mode. Recommended 0 in deploy, 1 in dev.
MIGRATE_ON_START 1 boolean deploy, dev Run Alembic migrations during app startup.
FRONTEND_ENABLED 1 boolean deploy, dev Serve bundled frontend assets from FastAPI.
FRONTEND_DIST_DIR /app/frontend/dist absolute path deploy, dev Path to built frontend assets inside app container.

Dev Frontend Overrides

Variable Default Options Scope Description
FRONTEND_HOST_PORT 5173 integer dev Host port mapped to Vite dev server.
CHOKIDAR_USEPOLLING 1 boolean dev File watching mode for containerized Vite.
VITE_DEV_API_PROXY_TARGET http://app:8000 URL dev Vite proxy target for /api and /healthz.

Auth and Session Security

Variable Default Options Scope Description
SESSION_SECRET_KEY replace-with-a-long-random-secret-at-least-32-characters long random string deploy, dev Session signing secret. Required in deploy.
SESSION_COOKIE_SECURE 1 boolean deploy, dev Mark session cookie as HTTPS-only. Set 1 behind HTTPS.
LOGIN_RATE_LIMIT_ATTEMPTS 5 integer >= 1 deploy, dev Login attempts allowed per window.
LOGIN_RATE_LIMIT_WINDOW_SECONDS 60 integer >= 1 deploy, dev Login rate limit window in seconds.

Logging

Variable Default Options Scope Description
LOG_LEVEL INFO DEBUG, INFO, WARNING, ERROR, CRITICAL deploy, dev Application log level.
LOG_FORMAT console console, json deploy, dev Log output format.
LOG_REQUESTS 1 boolean deploy, dev Enable request start/completion logs.
LOG_UVICORN_ACCESS 0 boolean deploy, dev Enable uvicorn access logs.
LOG_REQUEST_SKIP_PATHS /healthz comma-separated path prefixes deploy, dev Request log skip list.
LOG_REDACT_FIELDS empty comma-separated keys deploy, dev Extra fields to redact in structured logs.

Scheduler and Ingestion

Variable Default Options Scope Description
SCHEDULER_ENABLED 1 boolean deploy, dev Enable background scheduler loop.
SCHEDULER_TICK_SECONDS 60 integer >= 1 deploy, dev Scheduler interval in seconds.
SCHEDULER_QUEUE_BATCH_SIZE 10 integer >= 1 deploy, dev Queue items processed per scheduler tick.
INGESTION_NETWORK_ERROR_RETRIES 1 integer >= 0 deploy, dev Retries for transient ingestion network errors.
INGESTION_RETRY_BACKOFF_SECONDS 1.0 float >= 0 deploy, dev Backoff delay for retry attempts.
INGESTION_MAX_PAGES_PER_SCHOLAR 30 integer >= 1 deploy, dev Upper bound of pages fetched per scholar run.
INGESTION_PAGE_SIZE 100 integer >= 1 deploy, dev Requested Scholar page size.
INGESTION_ALERT_BLOCKED_FAILURE_THRESHOLD 1 integer >= 1 deploy, dev Trigger blocked/captcha scrape alert flag when this many blocked failures occur in a run.
INGESTION_ALERT_NETWORK_FAILURE_THRESHOLD 2 integer >= 1 deploy, dev Trigger network scrape alert flag when this many network failures occur in a run.
INGESTION_ALERT_RETRY_SCHEDULED_THRESHOLD 3 integer >= 1 deploy, dev Trigger retry alert flag when scheduled retry count reaches this threshold in a run.
INGESTION_CONTINUATION_QUEUE_ENABLED 1 boolean deploy, dev Enable continuation queue for long runs.
INGESTION_CONTINUATION_BASE_DELAY_SECONDS 120 integer >= 0 deploy, dev Initial delay before retrying continuation queue items.
INGESTION_CONTINUATION_MAX_DELAY_SECONDS 3600 integer >= 0 deploy, dev Maximum continuation retry delay.
INGESTION_CONTINUATION_MAX_ATTEMPTS 6 integer >= 1 deploy, dev Max failed continuation attempts before dropping item.

Scholar Images and Name Search Safety

Variable Default Options Scope Description
SCHOLAR_IMAGE_UPLOAD_DIR /var/lib/scholarr/uploads writable absolute path deploy, dev Storage path for uploaded scholar images. Use a persistent mounted path in production.
SCHOLAR_IMAGE_UPLOAD_MAX_BYTES 2000000 integer >= 1 deploy, dev Max uploaded image size in bytes.
SCHOLAR_NAME_SEARCH_ENABLED 1 boolean deploy, dev Enable name-search helper endpoint.
SCHOLAR_NAME_SEARCH_CACHE_TTL_SECONDS 21600 integer >= 1 deploy, dev Cache TTL for successful name-search responses.
SCHOLAR_NAME_SEARCH_BLOCKED_CACHE_TTL_SECONDS 300 integer >= 1 deploy, dev Cache TTL for blocked/captcha responses.
SCHOLAR_NAME_SEARCH_CACHE_MAX_ENTRIES 512 integer >= 1 deploy, dev Max cached search entries.
SCHOLAR_NAME_SEARCH_MIN_INTERVAL_SECONDS 8.0 float >= 0 deploy, dev Minimum interval between live name-search requests.
SCHOLAR_NAME_SEARCH_INTERVAL_JITTER_SECONDS 2.0 float >= 0 deploy, dev Added jitter to reduce request burst patterns.
SCHOLAR_NAME_SEARCH_COOLDOWN_BLOCK_THRESHOLD 1 integer >= 1 deploy, dev Consecutive blocked responses before cooldown starts.
SCHOLAR_NAME_SEARCH_COOLDOWN_SECONDS 1800 integer >= 1 deploy, dev Cooldown duration after repeated blocked responses.
SCHOLAR_NAME_SEARCH_ALERT_RETRY_COUNT_THRESHOLD 2 integer >= 1 deploy, dev Emit retry-threshold observability warning when name-search retry count reaches this value.
SCHOLAR_NAME_SEARCH_ALERT_COOLDOWN_REJECTIONS_THRESHOLD 3 integer >= 1 deploy, dev Emit cooldown-threshold observability alert after this many requests are rejected during active cooldown.

Startup Bootstrap and DB Wait

Variable Default Options Scope Description
BOOTSTRAP_ADMIN_ON_START 0 boolean deploy, dev Auto-create admin at startup.
BOOTSTRAP_ADMIN_EMAIL empty valid email deploy, dev Bootstrap admin email.
BOOTSTRAP_ADMIN_PASSWORD empty strong password deploy, dev Bootstrap admin password.
BOOTSTRAP_ADMIN_FORCE_PASSWORD 0 boolean deploy, dev Force-reset bootstrap admin password if user already exists.
DB_WAIT_TIMEOUT_SECONDS 60 integer >= 1 deploy, dev Max seconds to wait for DB readiness at startup.
DB_WAIT_INTERVAL_SECONDS 2 integer >= 1 deploy, dev Interval between DB readiness checks.

Quality and Test Commands

Backend:

docker compose -f docker-compose.yml -f docker-compose.dev.yml run --rm app uv run pytest tests/unit
docker compose -f docker-compose.yml -f docker-compose.dev.yml run --rm app uv run pytest -m integration

Frontend:

cd frontend
npm install
npm run typecheck
npm run test:run
npm run build

Contract drift:

python3 scripts/check_frontend_api_contract.py

Repository hygiene:

./scripts/check_no_generated_artifacts.sh

Scheduled fixture probes run in GitHub Actions via .github/workflows/scheduled-probes.yml.

API Contract

  • Base path: /api/v1
  • Success envelope: {"data": ..., "meta": {"request_id": "..."}}
  • Error envelope: {"error": {"code": "...", "message": "...", "details": ...}, "meta": {"request_id": "..."}}