{% extends "base.html" %} {% block title %}Config — Libris{% endblock %} {% block content %} {%- macro path_row(name, value, label, hint='') -%}
{% if hint %}

{{ hint }}

{% endif %}
{%- endmacro -%} {%- macro text_row(name, value, label, type='text', hint='', placeholder='') -%}
{% if hint %}

{{ hint }}

{% endif %}
{%- endmacro -%} {%- macro number_row(name, value, label, step='0.1', min='0', hint='') -%}
{% if hint %}

{{ hint }}

{% endif %}
{%- endmacro -%} {%- macro check_row(name, checked, label, hint='') -%}
{{ label }} {% if hint %}

{{ hint }}

{% endif %}
{%- endmacro -%} {%- macro select_row(name, value, label, options, hint='') -%}
{% if hint %}

{{ hint }}

{% endif %}
{%- endmacro -%}

Config

Editing {{ config_file }}

{% if save_success %}
Config saved successfully.
{% endif %} {% if config_error %}
Error: {{ config_error }}
{% endif %}
{% if config %}

Watcher

{{ path_row("watcher.incoming_dir", config.watcher.incoming_dir, "incoming_dir", "Drop ebooks/audiobooks here for automatic processing.") }} {{ number_row("watcher.poll_interval_seconds", config.watcher.poll_interval_seconds, "poll_interval_seconds", step="0.5", min="0.5") }} {{ number_row("watcher.scan_interval_hours", config.watcher.scan_interval_hours, "scan_interval_hours", step="0.5", min="0") }}

Paths

{{ path_row("paths.staging_dir", config.paths.staging_dir, "staging_dir", "Temporary directory for format conversion.") }} {{ path_row("paths.review_dir", config.paths.review_dir, "review_dir", "Low-confidence matches land here for manual review.") }} {{ path_row("paths.failed_dir", config.paths.failed_dir, "failed_dir", "Processing errors quarantined here.") }} {{ path_row("paths.state_db", config.paths.state_db, "state_db", "SQLite database file (parent directory must exist).") }}

Calibre

{{ path_row("calibre.library_db_path", config.calibre.library_db_path, "library_db_path", "Directory containing metadata.db.") }} {{ path_row("calibre.book_file_path", config.calibre.book_file_path, "book_file_path", "Physical book files location (split-library setup). Leave blank if same as library_db_path.") }}
{{ text_row("calibre.docker_container", config.calibre.docker_container, "docker_container", placeholder="calibre-web") }}

One host_path: container_path mapping per line.

{{ text_row("calibre.reconnect_url", config.calibre.reconnect_url, "reconnect_url", placeholder="http://192.168.1.10:8083/reconnect", hint="Optional: calibre-web /reconnect URL (requires -r flag).") }}

Metadata

{{ "%.2f" % config.metadata.confidence_threshold }}
{{ select_row("metadata.duplicate_action", config.metadata.duplicate_action, "duplicate_action", [("review","review — quarantine for inspection"), ("skip","skip — discard silently"), ("import","import — always import")]) }} {{ check_row("metadata.overwrite_existing", config.metadata.overwrite_existing, "overwrite_existing", "Overwrite embedded metadata tags on import.") }} {{ check_row("metadata.mock_mode", config.metadata.mock_mode, "mock_mode", "Return fixture data only — no real HTTP calls. For testing.") }} {{ text_row("metadata.google_books_api_key", config.metadata.google_books_api_key, "google_books_api_key", type="password", hint="Clear to remove. 60 req/min without a key.") }}

Output

{{ select_row("output.preferred_ebook_format", config.output.preferred_ebook_format, "preferred_ebook_format", [("epub","epub"),("mobi","mobi")]) }} {{ select_row("output.preferred_audio_format", config.output.preferred_audio_format, "preferred_audio_format", [("m4b","m4b")]) }} {{ select_row("output.ebook_format_policy", config.output.ebook_format_policy, "ebook_format_policy", [("preferred","preferred — convert to preferred format"), ("all","all — import native format as-is")]) }} {{ check_row("output.embed_cover_art", config.output.embed_cover_art, "embed_cover_art", "Download and embed cover images on import.") }}

Notifications (ntfy)

{{ check_row("ntfy.enabled", config.ntfy.enabled, "enabled") }} {{ text_row("ntfy.topic", config.ntfy.topic, "topic", placeholder="my-libris-topic") }} {{ text_row("ntfy.base_url", config.ntfy.base_url, "base_url", placeholder="https://ntfy.sh") }} {{ text_row("ntfy.auth_token", config.ntfy.auth_token, "auth_token", type="password", hint="Optional Bearer token for private topics.") }}

Multi-part audiobooks

{{ number_row("multipart.timeout_hours", config.multipart.timeout_hours, "timeout_hours", step="1", min="0", hint="Hours to wait for missing parts before escalating to review.") }}

Directive API

{{ check_row("api.enabled", config.api.enabled, "enabled", hint="Lets an external tool (e.g. Librarr) pre-register a metadata match for an incoming file via /api/v1/directives. Off by default.") }} {{ text_row("api.api_key", config.api.api_key, "api_key", hint="Required in the X-Api-Key header on every request. Leave blank to keep the API rejecting all requests even if enabled.") }}

Logging

{{ select_row("log_level", config.log_level, "log_level", [("DEBUG","DEBUG"),("INFO","INFO"),("WARNING","WARNING"), ("ERROR","ERROR"),("CRITICAL","CRITICAL")]) }}
{% endif %}
{% endblock %}