Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.7 KiB
Project Guidelines
Version Management
Update the integration version in custom_components/immich_album_watcher/manifest.json only when changes are made to the integration content (files inside custom_components/immich_album_watcher/).
IMPORTANT ALWAYS ask for version bump before doing it.
Do NOT bump version for:
- Repository setup (hacs.json, root README.md, LICENSE, CLAUDE.md)
- CI/CD configuration
- Other repository-level changes
Use semantic versioning:
- MAJOR (x.0.0): Breaking changes
- MINOR (0.x.0): New features, backward compatible
- PATCH (0.0.x): Bug fixes, integration documentation updates
Documentation Updates
IMPORTANT: Always keep the README.md synchronized with integration changes.
When modifying the integration interface, you MUST update the corresponding documentation:
- Service parameters: Update parameter tables and examples in README.md
- New events: Add event documentation with examples and field descriptions
- New entities: Document entity types, attributes, and usage
- Configuration options: Update configuration documentation
- Translation files: Add translations for new parameters/entities in
en.jsonandru.json - services.yaml: Keep service definitions in sync with implementation
The README is the primary user-facing documentation and must accurately reflect the current state of the integration.
Development Servers
IMPORTANT: When the user requests it OR when backend code changes are made (files in packages/server/), you MUST restart the standalone server using this one-liner:
PID=$(netstat -ano 2>/dev/null | grep ':8420.*LISTENING' | awk '{print $5}' | head -1) && [ -n "$PID" ] && taskkill //F //PID $PID 2>/dev/null; sleep 1 && cd packages/server && pip install -e . 2>&1 | tail -1 && cd ../.. && IMMICH_WATCHER_DATA_DIR=./test-data IMMICH_WATCHER_SECRET_KEY=test-secret-key-minimum-32chars nohup python -m uvicorn immich_watcher_server.main:app --host 0.0.0.0 --port 8420 > /dev/null 2>&1 & sleep 3 && curl -s http://localhost:8420/api/health
IMPORTANT: Overlays (modals, dropdowns, pickers) MUST use position: fixed with inline styles and z-index: 9999. Tailwind CSS v4 fixed/absolute classes do NOT work reliably inside flex/overflow containers in this project. Always calculate position from getBoundingClientRect() for dropdowns, or use top:0;left:0;right:0;bottom:0 for full-screen backdrops.
IMPORTANT: When the user requests it, restart the frontend dev server using this one-liner:
PID=$(netstat -ano 2>/dev/null | grep ':5173.*LISTENING' | awk '{print $5}' | head -1) && [ -n "$PID" ] && taskkill //F //PID $PID 2>/dev/null; sleep 1 && cd frontend && npx vite dev --port 5173 --host > /dev/null 2>&1 & sleep 4 && curl -s -o /dev/null -w "Frontend: %{http_code}" http://localhost:5173/
Frontend Architecture Notes
- i18n: Uses
$staterune in.svelte.tsfile (lib/i18n/index.svelte.tsorindex.tswith auto-detect). Locale auto-detects from localStorage at module load time.t()is reactive via$state.setLocale()updates immediately without page reload. - Svelte 5 runes:
$stateonly works in.svelteand.svelte.tsfiles. Regular.tsfiles cannot use runes -- use plain variables instead. - Static adapter: Frontend uses
@sveltejs/adapter-staticwith SPA fallback. API calls proxied via Vite dev server config. - Auth flow: After login/setup, use
window.location.href = '/'(hard redirect), NOTgoto('/')(races with layout auth check). - Tailwind CSS v4: Uses
@themedirective inapp.cssfor CSS variables. Grid/flex classes work butfixed/absolutepositioning requires inline styles in overlay components.
Backend Architecture Notes
- SQLAlchemy async + aiohttp: Cannot nest
async with aiohttp.ClientSession()inside a route that has an active SQLAlchemy async session -- greenlet context breaks. Eagerly load all DB data before entering aiohttp context, or usecheck_tracker_with_session()pattern. - Jinja2 SandboxedEnvironment: All template rendering MUST use
from jinja2.sandbox import SandboxedEnvironment(notjinja2.sandbox.SandboxedEnvironment-- dotted access doesn't work). - System-owned entities:
user_id=0means system-owned (e.g. default templates). Access checks must allowuser_id == 0in_get()helpers. - Default templates: Stored as
.jinja2files inpackages/server/src/immich_watcher_server/templates/{en,ru}/. Loaded byload_default_templates(locale)and seeded to DB on first startup if no templates exist. - FastAPI route ordering: Static path routes (e.g.
/variables) MUST be registered BEFORE parameterized routes (e.g./{config_id}) to avoid path conflicts. __pycache__: Add to.gitignore. Never commit.