03ec9b3c86
Adds telegram bot command system with 13 commands (search, latest, random, etc.), webhook/polling handlers, rate limiting, app settings page, and various UI/UX improvements across all entity pages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68 lines
4.9 KiB
Markdown
68 lines
4.9 KiB
Markdown
# Project Guidelines
|
|
|
|
## 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:
|
|
```bash
|
|
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 ../.. && NOTIFY_BRIDGE_DATA_DIR=./test-data NOTIFY_BRIDGE_SECRET_KEY=test-secret-key-minimum-32chars nohup python -m uvicorn notify_bridge_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:
|
|
```bash
|
|
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/
|
|
```
|
|
|
|
## Test Credentials
|
|
|
|
Default test account: username `admin`, password `admin1`.
|
|
|
|
## Frontend Architecture Notes
|
|
|
|
- **i18n**: Uses `$state` rune in `.svelte.ts` file. Locale auto-detects from localStorage. `t()` is reactive via `$state`. `setLocale()` updates immediately without page reload.
|
|
- **Svelte 5 runes**: `$state` only works in `.svelte` and `.svelte.ts` files. Regular `.ts` files cannot use runes -- use plain variables instead.
|
|
- **Static adapter**: Frontend uses `@sveltejs/adapter-static` with SPA fallback. API calls proxied via Vite dev server config.
|
|
- **Auth flow**: After login/setup, use `window.location.href = '/'` (hard redirect), NOT `goto('/')`.
|
|
- **Tailwind CSS v4**: Uses `@theme` directive in `app.css` for CSS variables.
|
|
|
|
## 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.
|
|
- **Jinja2 SandboxedEnvironment**: All template rendering MUST use `from jinja2.sandbox import SandboxedEnvironment`.
|
|
- **System-owned entities**: `user_id=0` means system-owned (e.g. default templates).
|
|
- **FastAPI route ordering**: Static path routes MUST be registered BEFORE parameterized routes.
|
|
- **`__pycache__`**: Add to `.gitignore`. Never commit.
|
|
|
|
## Project Structure (Phase 1)
|
|
|
|
- **packages/core** (`notify_bridge_core`): Shared library — providers, models, notifications, templates. No DB dependency.
|
|
- **packages/server** (`notify_bridge_server`): FastAPI REST API + SQLite. Depends on core.
|
|
- **frontend**: SvelteKit 2 + Svelte 5 + Tailwind CSS v4. Static adapter with SPA fallback. Dev proxy to :8420.
|
|
- **Environment vars**: `NOTIFY_BRIDGE_DATA_DIR`, `NOTIFY_BRIDGE_SECRET_KEY`, `NOTIFY_BRIDGE_DATABASE_URL`
|
|
- Core package includes `jinja2` dependency (template rendering lives in core, not server).
|
|
|
|
## Entity Relationships (Phase 6)
|
|
|
|
```
|
|
ServiceProvider → type: "immich", config: JSON (url, api_key, external_domain)
|
|
Tracker → provider_id, tracking_config_id, target_ids: JSON list, collection_ids: JSON list
|
|
TrackingConfig → provider_type (must match provider), event flags, scheduling
|
|
TemplateConfig → provider_type (must match provider), Jinja2 slots per event type
|
|
NotificationTarget → template_config_id, type: "telegram"/"webhook", config: JSON
|
|
```
|
|
|
|
- TrackingConfig owned by Tracker (what to watch), TemplateConfig owned by Target (how to format)
|
|
- `user_id=0` on TemplateConfig = system default (EN/RU seeded on first startup)
|
|
- DB: SQLite + async SQLAlchemy via sqlmodel, auto-created on startup
|
|
- API: All CRUD routes under `/api/`, auth via JWT Bearer, `NOTIFY_BRIDGE_` env prefix
|
|
|
|
## Template System Sync Rules
|
|
|
|
**IMPORTANT**: When adding or changing template context variables, you MUST update ALL of these in sync:
|
|
1. **`packages/core/.../templates/context.py`** — `build_template_context()` where variables are computed
|
|
2. **`packages/server/.../api/template_configs.py`** — `_SAMPLE_CONTEXT` dict (for preview rendering)
|
|
3. **`packages/server/.../api/template_configs.py`** — `get_template_variables()` endpoint (`event_vars`, `asset_fields`, `album_fields`, `scheduled_vars`, per-slot variable dicts)
|
|
4. **`packages/core/.../templates/defaults/{en,ru}/*.jinja2`** — default template files using the new variables
|
|
5. **`packages/core/.../providers/immich/provider.py`** — `IMMICH_VARIABLES` list (provider-specific variable definitions)
|