68ac13b452
Add full NUT support as a polling-based service provider: - Async TCP client for upsd protocol (port 3493, configurable) - 8 event types: online, on_battery, low_battery, battery_restored, comms_lost, comms_restored, replace_battery, overload - 3 bot commands: /status, /devices, /battery - 38 Jinja2 templates (EN+RU notification + command templates) - Database: tracking config fields, migration, seeds - Frontend: provider form with host/port/credentials, grid items, i18n Provider-agnostic UI improvements: - Remove hardcoded 'immich' defaults from all config forms - Dynamic collection labels per provider type (Albums/Repos/Boards/UPS Devices) - Capability-driven test types instead of provider type checks - Template variable helpers for all providers (was Immich-only) - Guard Immich-only shared link check to Immich providers - Auto-clear stale global provider filter from localStorage - EntitySelect search placeholder shows current selection - Fix noneLabel in linked target config selectors New CLAUDE.md rule #8: no provider-specific hardcoding
3.9 KiB
3.9 KiB
Project Guidelines
Detailed context is split into focused documents under .claude/docs/. Read the relevant file when working in that area.
| Area | File | Key rules |
|---|---|---|
| Dev servers & credentials | dev-servers.md | MUST restart backend after code changes; frontend restart on request |
| Frontend architecture | frontend-architecture.md | Svelte 5 runes, overlays, entity cache system, i18n, auth flow |
| Backend architecture | backend-architecture.md | SQLAlchemy async constraints, Jinja2 sandbox, route ordering |
| Entity relationships | entity-relationships.md | Full entity graph and DB conventions |
| Template system | template-system.md | 6-file sync rule for template variables |
Critical Rules (always apply)
- Restart backend after ANY change to
packages/server/orpackages/core/— see dev-servers.md for the one-liner. - Overlays MUST use
position: fixedwith inline styles andz-index: 9999— see frontend-architecture.md. - Template variables must be updated in 6 files simultaneously — see template-system.md.
- Entity cache — shared entities use
$state-based caches infrontend/src/lib/stores/caches.svelte.ts. Always use cache for cross-page data; invalidate after mutations — see frontend-architecture.md. - Selector placeholders — use plain text without decorative dashes.
Select provider...not— Select provider —— see frontend-architecture.md. - Telegram API — ALL Telegram Bot API calls (sendMessage, sendPhoto, sendMediaGroup, etc.) MUST go through
TelegramClientinpackages/core/src/notify_bridge_core/notifications/telegram/client.py. NEVER duplicate sending logic in command handlers, API routes, or services. IfTelegramClientlacks a method you need, add it there. - Service provider defaults — when implementing a new service provider, ALWAYS create default notification and command templates and configs. This requires changes across all of these locations:
- Jinja2 notification templates for each locale in
packages/core/src/notify_bridge_core/templates/defaults/{en,ru}/ - Jinja2 command templates for each locale in
packages/core/src/notify_bridge_core/templates/command_defaults/{en,ru}/{provider}/ - Notification slot mapping in
packages/core/src/notify_bridge_core/templates/defaults/loader.py(PROVIDER_SLOT_FILE_MAP) - Command slot mapping in
packages/core/src/notify_bridge_core/templates/command_defaults/loader.py(PROVIDER_COMMAND_SLOTS) - Provider capabilities in
packages/core/src/notify_bridge_core/providers/capabilities.py - Seed functions in
packages/server/src/notify_bridge_server/database/seeds.py(notification templates, command templates, tracking configs, command configs) - Template variable definitions in
packages/server/src/notify_bridge_server/api/template_configs.py(get_template_variables())
- Jinja2 notification templates for each locale in
- No provider-specific hardcoding — UI labels, icons, form defaults, and feature checks MUST be provider-agnostic. NEVER hardcode a specific provider type (e.g.
'immich') where multiple providers could appear:- Form defaults: use
provider_type: ''(empty), not'immich' - Collection labels: use the
collectionMetalookup inTrackerForm.svelte, not hardcoded "Albums" - Feature gating: check
capabilities.notification_slotsorcapabilities.commands, notprovider.type === 'immich' - Provider-specific API calls (e.g.
/albums/.../shared-links): guard with a provider type check - Template variable helpers: ALL provider types must have entries in
get_template_variables()
- Form defaults: use