diff --git a/docs/.vitepress/config.base.ts b/docs/.vitepress/config.base.ts index 82298fb8..2023b175 100644 --- a/docs/.vitepress/config.base.ts +++ b/docs/.vitepress/config.base.ts @@ -52,6 +52,7 @@ export default defineConfig({ { text: 'CLI Reference', link: '/guide/cli' }, ], }, + { text: 'Integrations 🔗', link: '/api/integrations/' }, ], }, { @@ -75,6 +76,16 @@ export default defineConfig({ items: [ { text: 'Overview', link: '/api/' }, { text: 'Headless Setup & API Keys', link: '/api/setup' }, + { + text: 'Integrations', + link: '/api/integrations/', + collapsed: true, + items: [ + { text: 'Dashy', link: '/api/integrations/dashy' }, + { text: 'Home Assistant', link: '/api/integrations/homeassistant' }, + { text: 'Homepage', link: '/api/integrations/homepage' }, + ], + }, ], }, ], diff --git a/docs/api/integrations/dashy.md b/docs/api/integrations/dashy.md new file mode 100644 index 00000000..73ee033e --- /dev/null +++ b/docs/api/integrations/dashy.md @@ -0,0 +1,137 @@ +# Dashy + +LibrisLog can be integrated into [Dashy](https://dashy.to/), a self-hosted +dashboard for your services, using its +[HTML embedded widget](https://dashy.to/docs/widgets#html-embedded-widget). + +This widget displays your reading statistics as styled stat cards directly on +your Dashy dashboard. + +## Prerequisites + +- A running LibrisLog instance reachable from your Dashy server +- An [API key](/api/integrations/#api-keys) with access to the + statistics endpoint +- **CORS must be configured** — add your Dashy URL to the + [`CORS_ORIGINS`](/guide/configuration#core-settings) environment variable + of the LibrisLog backend so that the browser can fetch the API directly + +## Configuration + +Add the following to the Dashy `conf.yml` under the section or item where you +want the widget to appear: + +```yaml +widgets: + - type: embed + updateInterval: 300 + options: + html: | +
+
+ Reading + - +
+
+ Read + - +
+
+ Want to Read + - +
+
+ Total Books + - +
+
+ css: | + .librislog-widget { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 0.75rem; + padding: 0.5rem; + font-family: inherit; + } + .ll-stat-item { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background: var(--background-elevated, rgba(255,255,255,0.05)); + border: 1px solid var(--outline-color, rgba(255,255,255,0.1)); + border-radius: 6px; + padding: 0.5rem; + text-align: center; + } + .ll-label { + font-size: 0.8rem; + opacity: 0.7; + color: var(--text-color, #fff); + margin-bottom: 0.25rem; + text-transform: uppercase; + letter-spacing: 0.05em; + } + .ll-value { + font-size: 1.4rem; + font-weight: bold; + color: var(--primary, #00bc8c); + } + script: | + (async function() { + const apiUrl = '/api/books/stats'; + const apiKey = ''; + + try { + const response = await fetch(apiUrl, { + method: 'GET', + headers: { + 'X-API-Key': apiKey, + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) throw new Error('API request failed'); + + const data = await response.json(); + + document.getElementById('ll-reading').innerText = data.books_currently_reading ?? data.books_reading ?? 0; + document.getElementById('ll-read').innerText = data.books_read ?? 0; + document.getElementById('ll-wtr').innerText = data.books_want_to_read ?? 0; + document.getElementById('ll-total').innerText = data.total_books ?? 0; + + } catch (error) { + console.error('LibrisLog Widget Error:', error); + const elements = ['ll-reading', 'll-read', 'll-wtr', 'll-total']; + elements.forEach(id => { + const el = document.getElementById(id); + if (el) el.innerText = '!'; + if (el) el.style.color = 'var(--danger, #ff0033)'; + }); + } + })(); +``` + +Replace the placeholders with your own values: + +| Placeholder | Example | Description | +|---|---|---| +| `` | `http://192.168.1.100:8000` | The base URL of your LibrisLog instance (http or https) | +| `` | `lk_nRHsF3jxIBDa9u....` | An API key with access to the statistics endpoint | + +The `updateInterval` is specified in seconds. `300` equals 5 minutes. + +## CORS + +Since the widget runs inside the Dashy iframe and fetches the LibrisLog API +directly from the browser, you must add your Dashy URL to the +[`CORS_ORIGINS`](/guide/configuration#core-settings) environment variable of +the LibrisLog backend. For example: + +``` +CORS_ORIGINS=["https://dashy.YOUR-DOMAIN"] +``` + +## Result + +![Dashy Widget](/screenshots/integrations-dashy.png) diff --git a/docs/api/integrations/homeassistant.md b/docs/api/integrations/homeassistant.md new file mode 100644 index 00000000..d0c267f8 --- /dev/null +++ b/docs/api/integrations/homeassistant.md @@ -0,0 +1,83 @@ +# Home Assistant + +LibrisLog can be integrated into [Home Assistant](https://www.home-assistant.io/), +a popular open-source home automation platform, using its +[RESTful integration](https://www.home-assistant.io/integrations/rest/). + +This integration creates sensors that expose your LibrisLog reading statistics +directly in Home Assistant. + +## Prerequisites + +- A running LibrisLog instance reachable from your Home Assistant server +- An [API key](/api/integrations/#api-keys) with access to the + statistics endpoint + +## Configuration + +Add the following to your Home Assistant `configuration.yaml`: + +```yaml +rest: + - resource: /api/books/stats + method: GET + headers: + X-API-Key: "" + Content-Type: application/json + scan_interval: 300 + sensor: + - name: "Total Books" + unique_id: librislog_total_books + value_template: "{{ value_json.total_books }}" + icon: mdi:bookshelf + unit_of_measurement: "Books" + - name: "Books Read" + unique_id: librislog_books_read + value_template: "{{ value_json.books_read }}" + icon: mdi:book-check + unit_of_measurement: "Books" + - name: "Books Currently Reading" + unique_id: librislog_books_currently_reading + value_template: "{{ value_json.books_reading }}" + icon: mdi:book-open-page-variant + unit_of_measurement: "Books" + - name: "Want to Read" + unique_id: librislog_books_want_to_read + value_template: "{{ value_json.books_want_to_read }}" + icon: mdi:bookmark-plus + unit_of_measurement: "Books" + + - resource: /api/statistics + method: GET + headers: + X-API-Key: "" + Content-Type: application/json + scan_interval: 600 + sensor: + - name: "Average Rating" + unique_id: librislog_average_rating + value_template: "{{ value_json.average_rating | round(2) if value_json.average_rating is not none else 'N/A' }}" + icon: mdi:star + unit_of_measurement: "★" + - name: "Average Page Count" + unique_id: librislog_average_page_count + value_template: "{{ value_json.avg_page_count | round(0) if value_json.avg_page_count is not none else 'N/A' }}" + icon: mdi:file-document-multiple + unit_of_measurement: "Pages" +``` + +Replace the placeholders with your own values: + +| Placeholder | Example | Description | +|---|---|---| +| `` | `http://192.168.1.100:8000` | The base URL of your LibrisLog instance (http or https) | +| `` | `lk_nRHsF3jxIBDa9u....` | An API key with access to the statistics endpoint | + +The `scan_interval` is specified in seconds. The first resource polls every +5 minutes, the second every 10 minutes. + +## Result + +![Home Assistant Sensors - Part 1](/screenshots/integrations-homeassistant-1.png) + +![Home Assistant Sensors - Part 2](/screenshots/integrations-homeassistant-2.png) diff --git a/docs/api/integrations/homepage.md b/docs/api/integrations/homepage.md new file mode 100644 index 00000000..a4feefa2 --- /dev/null +++ b/docs/api/integrations/homepage.md @@ -0,0 +1,60 @@ +# Homepage + +LibrisLog can be integrated into [Homepage](https://gethomepage.dev/), a +modern dashboard for your self-hosted services, using its +[custom API widget](https://gethomepage.dev/widgets/services/customapi/). + +This widget displays your reading statistics directly on your Homepage +dashboard. + +## Prerequisites + +- A running LibrisLog instance reachable from your Homepage server +- An [API key](/api/integrations/#api-keys) with access to the + statistics endpoint + +## Configuration + +Add the following entry to your Homepage `services.yaml`: + +```yaml +- librislog: + icon: mdi-book-heart + href: + siteMonitor: + widget: + type: customapi + url: /api/books/stats + method: GET + headers: + X-API-Key: "" + refreshInterval: 300000 + display: block + mappings: + - field: books_read + label: Read + format: number + - field: books_reading + label: Reading + format: number + - field: books_want_to_read + label: Want to read + format: number + - field: total_books + label: Total + format: number +``` + +Replace the placeholders with your own values: + +| Placeholder | Example | Description | +|---|---|---| +| `` | `http://192.168.1.100:8000` | The base URL of your LibrisLog instance (http or https) | +| `` | `lk_nRHsF3jxIBDa9u....` | An API key with access to the statistics endpoint | + +The `refreshInterval` is specified in milliseconds. `300000` ms equals 5 +minutes. + +## Result + +![Homepage Widget](/screenshots/integrations-homepage.png) diff --git a/docs/api/integrations/index.md b/docs/api/integrations/index.md new file mode 100644 index 00000000..75017507 --- /dev/null +++ b/docs/api/integrations/index.md @@ -0,0 +1,28 @@ +# Integrations + +LibrisLog exposes a full REST API that third-party applications can use to +display your reading data, automate workflows, or build custom dashboards. + +All integrations below are backed by the LibrisLog API. You will need an +API key to use them. You can create one either: + + + +- **Via the web UI** — go to your [Profile](/api/#creating-an-api-key) + page and click "Create API Key". +- **Via the API** — see the + [Headless Setup](/api/setup#3-create-an-api-key) guide for a + CLI-based workflow. + +## Available Integrations + +- [Dashy](/api/integrations/dashy) — Display your LibrisLog statistics as + styled stat cards on a [Dashy](https://dashy.to/) dashboard using the HTML + embedded widget. +- [Home Assistant](/api/integrations/homeassistant) — Expose your LibrisLog + reading statistics as sensors in + [Home Assistant](https://www.home-assistant.io/) using the RESTful + integration. +- [Homepage](/api/integrations/homepage) — Display your LibrisLog statistics + on a [Homepage](https://gethomepage.dev/) dashboard using the custom API + widget. diff --git a/docs/public/screenshots/integrations-dashy.png b/docs/public/screenshots/integrations-dashy.png new file mode 100644 index 00000000..10c36b1f Binary files /dev/null and b/docs/public/screenshots/integrations-dashy.png differ diff --git a/docs/public/screenshots/integrations-homeassistant-1.png b/docs/public/screenshots/integrations-homeassistant-1.png new file mode 100644 index 00000000..babced8e Binary files /dev/null and b/docs/public/screenshots/integrations-homeassistant-1.png differ diff --git a/docs/public/screenshots/integrations-homeassistant-2.png b/docs/public/screenshots/integrations-homeassistant-2.png new file mode 100644 index 00000000..9b39ab50 Binary files /dev/null and b/docs/public/screenshots/integrations-homeassistant-2.png differ diff --git a/docs/public/screenshots/integrations-homepage.png b/docs/public/screenshots/integrations-homepage.png new file mode 100644 index 00000000..3cc13252 Binary files /dev/null and b/docs/public/screenshots/integrations-homepage.png differ