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: |
+
+ 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
+
+
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
+
+
+
+
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
+
+
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