- Install @mdi/js (~7000 Material Design Icons)
- IconPicker component: dropdown with search, popular icons grid,
clear option. Stores icon name as string (e.g. "mdiCamera")
- MdiIcon component: renders SVG from icon name
- Backend: add `icon` field to ImmichServer, TelegramBot,
TrackingConfig, TemplateConfig, NotificationTarget, AlbumTracker
- All 6 entity pages: icon picker next to name input in create/edit
forms, icon displayed on entity cards
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 features implemented:
1. Server health indicator: green/red/yellow dot on each server card.
Pings Immich in background on page load. New GET /api/servers/{id}/ping.
2. Album selector filter: search input above album list in tracker form.
Filters by name as you type (case-insensitive). Shows total count.
3. Album last update time: each album in the selector shows its
updatedAt date. Backend now returns updatedAt from Immich API.
4. Full Jinja2 template engine in notifier:
- build_full_context() assembles all ~40 variables from blueprint
- Common date/location detection across assets
- Per-asset date/location when they differ
- Favorite indicator, people formatting, asset list with truncation
- Video warning for Telegram
- All template slots from TemplateConfig used contextually
5. Password change: PUT /api/auth/password endpoint (validates current
password, min 6 chars). UI in sidebar footer with inline form.
Also: Phase 9 plan (Telegram bot management) added.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Core library:
- New combine_album_assets() in asset_utils.py: smart redistribution
of unused quota when albums return fewer assets than their share.
Two-pass algorithm: even split then redistribute remainder.
- 6 new tests (56 total passing).
Frontend:
- Fix "leave empty to keep current" not localized in server edit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix i18n: remove $state rune (SSR incompatible in .ts files),
use reactive localeVersion counter in layout to trigger re-render
on locale change. Language switching now works immediately.
- Fix dark theme: add global CSS rules for input/select/textarea to
use theme colors, override browser autofill in dark mode, set
color-scheme for native controls (scrollbars, checkboxes)
- Collapsible sidebar: toggle button (▶/◀) with persistent state,
icons-only mode when collapsed. Theme/language buttons moved to
bottom above user info.
- Loading skeletons: all pages show animated pulse placeholders
while data loads, eliminating content flicker on tab switch
- Edit support: Servers, Trackers, and Targets now have Edit buttons
that open the form pre-filled with current values. Save calls PUT.
Sensitive fields (API key, bot token) can be left empty to keep
current value when editing.
- CLAUDE.md: add dev server restart rules
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Frontend enhancements:
- i18n: Full Russian and English translations (~170 keys each),
language switcher in sidebar and login page, auto-detect from
browser, persists to localStorage
- Themes: Light/dark mode with CSS custom properties, system
preference detection, toggle in sidebar header, smooth transitions
- Dark theme: Full color palette (background, card, muted, border,
success, warning, error variants)
Enhanced forms:
- Tracker creation: asset type filtering (images/videos), favorites
only, include people/details toggles, sort by/order selects,
max assets to show
- Target creation: Telegram media settings (collapsible) with
max media, group size, chunk delay, max asset size, URL preview
disable, large photos as documents
- Template creation: event_type selector (all/added/removed/renamed/deleted)
All pages use t() for translations, var(--color-*) for theme-safe
colors, and proper label-for-input associations.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes 7 issues identified by code-reviewer agent:
1. (Critical) Move JSON.parse inside try/catch in targets page to
handle malformed webhook headers input gracefully
2. (Low) Add window guard to refreshAccessToken for SSR safety
3. (Important) Show loading indicator instead of page content while
auth state is being resolved (prevents flash of protected content)
4. (Important) Add try/catch to trackers load() Promise.all
5. (Important) Add error handling to remove() in servers, trackers,
and templates pages
6. (Important) Track preview per-template with previewId, show
inline instead of global bottom block
7. (Important) Use finally block for loading state in auth
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>