Sign inSign up

getcoral/librarian

By getcoral

•Updated 11 days ago

Organise, enrich and maintain self-hosted media libraries.

Image
0

3.6K

getcoral/librarian repository overview

Librarian logo — an open book split by a glowing gutter line, gold pages above and teal below

⁠Librarian

GitHub Sponsors Discord

A Coral⁠ module for organizing, enriching, and maintaining self-hosted media libraries.


⁠Getting started

⁠1. Install dependencies
pnpm install
⁠2. Start developing
pnpm dev

App runs at http://localhost:3000.

If JELLYFIN_URL, JELLYFIN_API_KEY, and JELLYFIN_USER_ID are present in your environment, Librarian skips setup and connects immediately. Otherwise it will open /setup and store the connection details in local SQLite under ./data/librarian.sqlite.


⁠Product direction

Librarian is the Coral module focused on media hygiene and enrichment:

  • Scan a library for missing or inconsistent metadata
  • Flag duplicates, poster gaps, and low-quality assets
  • Queue background jobs for renaming, tagging, and enrichment
  • Prepare media for downstream Coral modules while keeping Jellyfin as the source of truth

The current repo contains the first product shell and landing experience for that workflow.

⁠Local storage

  • Default database path: ./data/librarian.sqlite
  • Override with: LIBRARIAN_DATA_DIR=/path/to/data
  • Main use today: persisted Jellyfin connection details when env vars are not provided

⁠Access control

Librarian requires a Jellyfin sign-in by default. That is deliberate and differs from the read-only Coral modules: Aurora and Tide default open because the worst an open instance does is show someone a library they could already stream, whereas this one moves and deletes files.

Anything that touches the filesystem additionally requires the signed-in user to be a Jellyfin administrator, and that gate does not relax when sign-in is switched off. Turning sign-in off opens browsing, never file operations.

VariableDefaultEffect
LIBRARIAN_REQUIRE_LOGINtruePins the setting and hides the UI toggle
CORAL_SERVICE_TOKENunsetGrants another module full access without issuing a token in the UI

⁠Filesystem roots

Librarian only touches directories you have enabled.

LIBRARIAN_DOWNLOADS_DIR and LIBRARIAN_MEDIA_DIR seed root records; they do not grant permission. A seeded root arrives switched off and a human turns it on, so a container that happens to have /media bind-mounted can do nothing with it until somebody says so.

Mount media and downloads under one mount point. A hardlink cannot cross a mount, even when both sides are the same filesystem, and hardlinking is what makes an import cost zero bytes and lets a torrent keep seeding. Split them and every import silently becomes a full copy — visible as "Copy" rather than "Hardlink" in the import preview.

⁠Stack

ToolPurpose
TanStack Start⁠Full-stack React framework
TanStack Router⁠Type-safe file-based routing
TanStack Query⁠Server state management
Tailwind v4⁠Styling
Biome⁠Linting & formatting
@get-coral/jellyfin⁠Jellyfin API client
Vitest⁠Testing

⁠Scripts

pnpm dev        # Start dev server on :3000
pnpm build      # Production build
pnpm start      # Run production server
pnpm typecheck  # TypeScript check
pnpm check      # Biome lint + format check
pnpm lint       # Biome lint with auto-fix
pnpm test       # Run tests

⁠Docker

# Pull the published image
docker pull getcoral/librarian:latest

# Or build it yourself
docker build -t librarian .

# Run
docker run -p 3000:3000 \
  -e JELLYFIN_URL=http://your-nas:8096 \
  -e JELLYFIN_API_KEY=your-key \
  -e JELLYFIN_USER_ID=your-user-id \
  getcoral/librarian:latest

Published automatically on every release via GitHub Actions:

  • getcoral/librarian on Docker Hub
  • ghcr.io/get-coral/librarian on GHCR

⁠CI / CD

WorkflowTriggerWhat it does
ci.ymlEvery PR + push to mainTypecheck, lint, test, build, Docker build check
docker-publish.ymlPush to main + version tagsPublishes to GHCR
release-please.ymlPush to mainOpens release PR, publishes Docker on merge

Releases are fully automated via Release Please⁠. Use conventional commits:

Commit prefixVersion bump
feat:Minor
fix:Patch
feat!: / fix!:Major
chore:, docs:No bump

⁠Part of Coral

This module is part of the Coral⁠ ecosystem. See the contributing guide⁠ before opening PRs.

Tag summary

Content type

Image

Digest

sha256:84ffb31bb…

Size

107.7 MB

Last updated

11 days ago

docker pull getcoral/librarian