Update docs for Presto, PubSub, and Node.js 26

Add Presto companion display to architecture overview. Document collection API cover sizes (cover, thumb/480px, mini/150px, micro/40px). Update PubSub topic table and LiveView conventions for handle_params subscription management. Bump Node.js version from 25 to 26 in production infrastructure.
This commit is contained in:
Claudio Ortolina
2026-05-07 10:57:23 +01:00
parent 5f240fe573
commit 829d0a2caa
3 changed files with 8 additions and 7 deletions
+4 -3
View File
@@ -19,6 +19,7 @@ Key capabilities:
- AI-powered record chat via OpenAI streaming with web search
- Barcode scanning for quick imports
- Encrypted secret storage (Cloak)
- Presto companion display (MicroPython, 4" IPS LCD, "Records on this day")
**Elixir ~> 1.14, Phoenix ~> 1.8, LiveView ~> 1.1, SQLite3**
@@ -250,8 +251,8 @@ HTTP 429 into `:rate_limit` vs `:auth_error` by reading the body `code`
## PubSub Topics
| PubSub | Topic Pattern | Message | Used By |
| ---------------- | -------------------------- | ------------------- | ------------------------------------------------------------------ |
| `:music_library` | `"records:#{id}"` | `{:update, record}` | CollectionLive.Show, WishlistLive.Show — real-time record updates |
| ---------------- | -------------------------- | ------------------- | ---------------------------------------------------------------------------------------------- |
| `:music_library` | `"records:#{id}"` | `{:update, record}` | CollectionLive.Show, WishlistLive.Show — subscribe in handle_params, unsubscribe on navigation |
| `:music_library` | `"listening_stats:update"` | `%{track_count: n}` | StatsLive.Index, ScrobbledTracksLive.Index — new scrobbles arrived |
---
@@ -345,7 +346,7 @@ All authenticated routes live inside a single `live_session` with three `on_moun
| `LastFmController` | `/auth/last_fm/callback` | Last.fm OAuth |
| `ArchiveController` | `/backup`, `/api/v1/backup` | Database backup download (API route requires token) |
| `AssetController` | `/assets/:transform_payload`, `/public/assets/:transform_payload`, `/api/v1/assets/:transform_payload` | Serve images with transforms (public route for emails, API route requires token) |
| `CollectionController` | `/api/v1/collection/*` | JSON API for collection queries |
| `CollectionController` | `/api/v1/collection/*` | JSON API for collection queries (returns 4 cover sizes: cover, thumb/480px, mini/150px, micro/40px) |
| `ErrorController` | `/api/v1/errors`, `/api/v1/errors/:id`, `/api/v1/errors/:id/mute`, `/api/v1/errors/:id/unmute`, `/api/v1/errors/:id/resolve`, `/api/v1/errors/:id/unresolve` | JSON API for production error queries and mutations (requires Bearer token); POST endpoints for mute/unmute/resolve/unresolve |
---
+1 -1
View File
@@ -29,7 +29,7 @@ push via GitHub Actions.
The Docker image is a multi-stage build:
1. **Builder**`hexpm/elixir:1.20.0-rc.4-erlang-28.5-debian-trixie-20260421-slim` with
Node.js 25, compiles deps, builds assets (`mix assets.deploy`), generates an OTP release.
Node.js 26, compiles deps, builds assets (`mix assets.deploy`), generates an OTP release.
2. **Runner**`debian:trixie-20260421-slim` with minimal runtime deps (`libstdc++6`,
`openssl`, `libncurses6`, `ca-certificates`). Runs as unprivileged `nobody` user.
+1 -1
View File
@@ -20,7 +20,7 @@ Key rules: imperative present tense, single-line under 60 characters, task ID pr
- **Context modules own all queries.** LiveViews never query the database directly -- they call context functions.
- **Schemas hold pure accessor/helper functions** on the struct (e.g., `RecordSet.count_by_status/1`). No side effects in schemas.
- **LiveView standard structure:** `mount/3` sets `@current_section`, `handle_params/3` loads data and sets `@page_title` (via pattern-matched private `page_title/2`), `handle_info/2` receives LiveComponent messages.
- **LiveView standard structure:** `mount/3` sets `@current_section`, `handle_params/3` loads data, sets `@page_title` (via pattern-matched private `page_title/2`), and manages PubSub subscriptions via `LiveHelpers.RecordActions.manage_subscription/2` (unsubscribing from the previous record and subscribing to the new one). `handle_info/2` receives LiveComponent messages and validates inbound record updates against `socket.assigns.record.id` to discard stale messages.
- **LiveComponents communicate with parent** via `send(self(), {__MODULE__, msg})`.
- **Function components go in domain-specific modules:** `CoreComponents` for generic UI, `RecordComponents` for records, `ScrobbleComponents` for scrobbles, `SearchComponents` for search.
- **External API integrations** follow a three-module pattern: Facade (public API), API (Req HTTP client), Config (NimbleOptions).