Files
haos-hacs-immich-album-watcher/plans/primary-plan.md
alexei.dolgolyov 87ce1bc5ec
Some checks failed
Validate / Hassfest (push) Has been cancelled
Add SvelteKit frontend with Tailwind CSS (Phase 4)
Build a modern, calm web UI using SvelteKit 5 + Tailwind CSS v4.

Pages:
- Setup wizard (first-run admin account creation)
- Login with JWT token management and auto-refresh
- Dashboard with stats cards and recent events timeline
- Servers: add/delete Immich server connections with validation
- Trackers: create album trackers with album picker, event type
  selection, target assignment, and scan interval config
- Templates: Jinja2 message template editor with live preview
- Targets: Telegram and webhook notification targets with test
- Users: admin-only user management (create/delete)

Architecture:
- Reactive auth state with Svelte 5 runes
- API client with JWT auth, auto-refresh on 401
- Static adapter builds to 153KB for embedding in FastAPI
- Vite proxy config for dev server -> backend API
- Sidebar layout with navigation and user info

Also adds Rule 2 to primary plan: perform detailed code review
after completing each phase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:46:55 +03:00

10 KiB

Immich Watcher: Standalone Web App + Shared Core Architecture

Status: Planning Created: 2026-03-19


Context

The current immich_album_watcher HA integration contains ~3,600 lines of tightly coupled code: Immich API client, change detection, Telegram notifications, and HA entities/services. A separate HA Blueprint (~2,000 lines) adds message templating, filtering, scheduled notifications, and memory mode.

Goal: Enable Immich album change notifications without Home Assistant via a standalone web application, while keeping the HAOS integration functional and sharing as much logic as possible.


Decisions

Decision Choice Rationale
Architecture Hybrid (Option C) HAOS standalone with shared core lib, optional server sync. No breaking changes for HA-only users.
Frontend SvelteKit + Shadcn-svelte Small bundle, fast, calm UI aesthetic. Good fit for self-hosted.
Notifications Telegram + Generic webhook Telegram from existing code. Webhook enables Discord/Slack/ntfy/custom.
Auth Multi-user (admin/user roles) Supports shared Immich servers. Admin manages servers/users, users manage own trackers.
Backend FastAPI + SQLite + APScheduler Async-native Python, zero external DB deps, proven scheduler.

Repository Structure

immich-watcher/
  packages/
    core/                              # Shared Python library
      pyproject.toml
      src/immich_watcher_core/
        immich_client.py               # Immich API (from coordinator.py)
        models.py                      # AssetInfo, AlbumData, AlbumChange, SharedLinkInfo
        change_detector.py             # Change detection (from coordinator.py)
        telegram/
          client.py                    # Telegram Bot API (from sensor.py)
          cache.py                     # File cache with pluggable backend
          media.py                     # Media download, size checks, group splitting
        webhook/
          client.py                    # Generic webhook notification provider
        templates.py                   # Jinja2 template engine
        storage.py                     # Abstract storage protocol + SQLite impl
        constants.py                   # Shared constants (from const.py)
      tests/

    server/                            # Standalone FastAPI app
      pyproject.toml
      src/immich_watcher_server/
        main.py                        # FastAPI entry point
        database/models.py             # SQLModel ORM
        database/migrations/           # Alembic
        api/                           # REST endpoints
        services/
          scheduler.py                 # APScheduler background polling
          watcher.py                   # Album polling orchestrator
          notifier.py                  # Notification dispatch
      Dockerfile
      docker-compose.yml

    haos/                              # Home Assistant integration (moved)
      custom_components/immich_album_watcher/
        ... (refactored to use core library)
      hacs.json

  frontend/                            # SvelteKit web UI source
    package.json
    src/
    dist/                              # Built static files served by FastAPI

  plans/                               # This folder
  README.md
  LICENSE

Shared Core Library Extractions

Core Module Source File What Gets Extracted
immich_client.py coordinator.py All /api/ calls, session injection via constructor
models.py coordinator.py L66-326 Dataclasses (already HA-independent)
change_detector.py coordinator.py L979-1066 detect_album_changes() pure function
telegram/client.py sensor.py (~1200 lines) Full Telegram Bot API: send_message/photo/video/media_group
telegram/cache.py storage.py TelegramFileCache with CacheBackend protocol
templates.py NEW (from blueprint logic) Jinja2 renderer with ~40 variables matching blueprint
storage.py storage.py Abstract protocol + SQLite implementation
webhook/client.py NEW Generic webhook POST JSON with event data

The ImmichClient accepts an aiohttp.ClientSession in constructor -- HA provides its managed session, standalone creates its own.


Standalone Server Design

Backend: FastAPI + SQLite + APScheduler

Database tables: users, immich_servers, notification_targets, message_templates, album_trackers, album_states, telegram_cache, notification_queue

Key API endpoints:

  • POST /api/auth/setup / POST /api/auth/login -- JWT auth
  • CRUD /api/servers -- Immich server connections
  • GET /api/servers/{id}/albums -- Fetch album list from Immich
  • CRUD /api/trackers -- Album trackers (album selection, event types, template overrides, targets)
  • CRUD /api/templates -- Message templates with preview
  • CRUD /api/targets -- Notification targets (Telegram chats, webhooks)
  • CRUD /api/users -- User management (admin only)
  • GET /api/status -- Dashboard data

Background: APScheduler runs one job per tracker at its scan interval. Each job: fetch album -> detect changes -> render template -> dispatch notification.

Frontend: SvelteKit + Shadcn-svelte

Pages:

  1. Setup wizard -- First-run: create admin account, connect Immich server
  2. Login -- Username/password
  3. Dashboard -- Active trackers overview, recent events timeline, server status
  4. Servers -- Add/edit Immich server connections (URL + API key validation)
  5. Trackers -- Create/edit album trackers:
    • Album picker (multi-select, fetched from Immich)
    • Event type toggles (assets added/removed, renamed, sharing changed, deleted)
    • Notification target selection
    • Template selection or per-tracker override
    • Scan interval, quiet hours
  6. Templates -- Jinja2 template editor:
    • CodeMirror with Jinja2 syntax highlighting
    • Live preview with sample album data
    • Variable reference sidebar
    • Default templates for common use cases
  7. Targets -- Manage notification destinations (Telegram chats, webhooks)
  8. Users -- User management (admin only)
  9. Settings -- Global defaults

Auth: Multi-user, bcrypt + JWT

  • Multiple user accounts with admin/user roles
  • Admin: full access (user management, server configuration)
  • User: manage own trackers, templates, and targets
  • First-run setup creates initial admin account

Deployment: Single Docker container, SQLite in mounted volume


HAOS Integration Changes

The integration gets refactored to delegate to core:

# coordinator.py becomes thin wrapper
class ImmichAlbumWatcherCoordinator(DataUpdateCoordinator):
    def __init__(self, ...):
        self._client = ImmichClient(session, url, api_key)  # from core

    async def _async_update_data(self):
        album = await self._client.get_album(self._album_id)
        change = detect_album_changes(old, album, pending)  # from core
        if change: self._fire_events(change, album)          # HA-specific
        return album

# sensor.py Telegram methods delegate to core
async def _execute_telegram_notification(self, ...):
    telegram = TelegramClient(session, token, cache)  # from core
    return await telegram.send_notification(...)

Phases

Rule 1: Before starting work on any phase, create a detailed trackable subplan at plans/phase-N-<name>.md with granular tasks, specific files to create/modify, and acceptance criteria. Do not begin implementation until the subplan is reviewed.

Rule 2: After completing each phase, perform a detailed code review of all changes. Use the code-reviewer agent to check for bugs, logic errors, security vulnerabilities, code quality issues, and adherence to project conventions. Document review findings in the phase subplan under a "## Review" section and fix any issues before committing.

Phase 1: Extract Core Library [x]

  • Extract models, Immich client, change detection, Telegram client, cache into packages/core/
  • Write unit tests for all extracted modules
  • Subplan: plans/phase-1-core-library.md

Phase 2: Wire Core into HAOS Integration [x]

  • Move integration to packages/haos/
  • Refactor coordinator.py, sensor.py, storage.py to use core library
  • Update manifest.json, hacs.json for new structure
  • Verify identical behavior with real Immich server
  • Subplan: plans/phase-2-haos-refactor.md

Phase 3: Build Server Backend [x]

  • FastAPI app with database, scheduler, API endpoints
  • Telegram + webhook notification providers
  • Jinja2 template engine with variable system matching blueprint
  • Subplan: plans/phase-3-server-backend.md

Phase 4: Build Frontend [x]

  • SvelteKit app with all pages (setup, dashboard, trackers, templates, targets, users)
  • Template editor with live preview
  • Album picker connected to Immich API
  • Subplan: plans/phase-4-frontend.md

Phase 5: HAOS-Server Sync (Optional) [ ]

  • Add optional server URL to HA config flow
  • Implement tracker/template config sync
  • Subplan: plans/phase-5-haos-server-sync.md

Phase 6: Claude AI Telegram Bot Enhancement (Optional) [ ]

  • Integrate Claude AI to enhance the Telegram notification bot
  • Enable conversational interactions: users can ask questions about their albums, get summaries, request specific photos
  • AI-powered message formatting: intelligent caption generation, album descriptions
  • Smart notification filtering: AI decides notification importance/relevance
  • Natural language tracker configuration via Telegram chat
  • Subplan: plans/phase-6-claude-ai-bot.md

Verification

  1. Core library: Unit tests for Immich client (mocked HTTP), change detection (pure function), Telegram client (mocked API), template rendering
  2. HAOS integration: After refactoring, verify all existing entities, services, and events work identically with a real Immich server
  3. Server backend: API integration tests with SQLite in-memory DB, scheduler tests
  4. Frontend: Manual testing of all pages, template editor preview, album picker
  5. End-to-end: Docker Compose up -> create account -> connect Immich -> create tracker -> trigger album change -> verify notification received