- Add VERSION file at repo root as single source of truth for app version
- frontend/vite.config.ts reads VERSION file instead of package.json
- backend config.py exposes APP_VERSION read from VERSION (dev) or /app/VERSION (Docker)
- database.py backs up DB to homelab.db.back-{version} before running migrations
(skipped if DB doesn't exist or backup already exists — fully idempotent)
- Dockerfile.backend and Dockerfile.frontend copy VERSION into the image
- Add test_db_backup.py with 4 tests covering create/skip/idempotent/version cases
Add waypoints JSON column to edges table, include it in all edge
schemas (EdgeBase, EdgeUpdate, canvas CanvasEdge) and add the
idempotent ALTER TABLE migration so existing databases are upgraded
on next startup.
- canvasStore.onConnect: include animated in edge data object (was silently dropped)
- Backend schemas: normalize animated bool/int to string ('none'/'snake'/'flow') via field_validator
- ORM model: change animated column from Boolean to String
- DB migration: convert existing 0/1 boolean rows to 'none'/'snake' strings
Add NodeResizer to BaseNode so users can drag corners to resize any node.
Persist width/height through the full stack: DB model, schemas, canvas
save/load route, and migration for existing databases.
Add tests covering save, update, clear, and load of node dimensions.
- Add animated toggle per edge in EdgeModal (cyan switch, "Flow Animation")
- SVG-native <animate> element for reliable cross-browser dot animation
- Persist animated field: backend model, schemas (EdgeBase/EdgeUpdate/EdgeSave), DB migration
- Include animated in App.tsx edgesToSave serialization so it survives save/reload
- Add animated: bool to EdgeData TypeScript type
On fresh installs the data/ dir may not exist, causing SQLite to create a
stub file without write permissions. mkdir(parents=True, exist_ok=True) runs
at import time before any DB operation.
Also add data/.gitignore to prevent homelab.db from ever being committed.
datetime.UTC was introduced in Python 3.11. Users on 3.10 get an ImportError.
Also lower ruff/mypy target-version from py313 to py310 to match minimum supported version.
- Add 65+ icons across 7 categories (Infrastructure, Media, Monitoring,
Storage, Security, Automation, Dev & Containers, Communications) covering
popular self-hosted apps: Home Assistant, Jellyfin, Plex, Grafana, Portainer,
Pi-hole, Vaultwarden, Gitea, Nextcloud, Node-RED, Frigate, etc.
- New nodeIcons.ts utility with ICON_REGISTRY, ICON_MAP and resolveNodeIcon()
- Inline icon picker in NodeModal: collapsible panel with search + grid grouped
by category; click to select, click again or Reset to revert to type default
- BaseNode uses resolveNodeIcon() so custom icon renders live on canvas
- Add custom_icon field to NodeData type, NodeBase/NodeUpdate schemas, Node ORM
model, and database.py idempotent ALTER TABLE migration
- Add custom_color field to EdgeData type, Edge DB model and all schemas
- HomelableEdge applies custom_color as stroke override (before selected highlight)
- EDGE_DEFAULT_COLORS extracted to utils/edgeColors.ts (react-refresh compliant)
- EdgeModal: color picker row showing effective color (custom or type default)
with hex value, Reset button when custom color is active
- Auto-migration adds custom_color column to edges table
- Add resolveNodeColors() utility merging type defaults with per-node overrides
- Default colors per node type (cyan=isp/router/lxc/ap, green=switch/nas,
purple=server/vm, orange=proxmox, amber=iot, gray=generic)
- Remove glowColor prop from BaseNode — colors now come from node data
- ProxmoxGroupNode uses resolveNodeColors for group border/header/icon
- NodeModal: Appearance section with 3 color swatches (border, background, icon)
— click swatch to open native color picker; Reset to defaults button
- custom_colors persisted as JSON in DB (backend model + schemas + migration)
- 7 new unit tests for resolveNodeColors covering all node types + partial overrides
- Double-click any link to open Edit Link modal (type, label, VLAN ID, delete)
- Add updateEdge / deleteEdge actions to canvasStore
- Add container_mode field to proxmox nodes (backend model, schemas, migration)
- NodeModal shows container toggle for proxmox type (defaults ON)
- ProxmoxGroupNode renders as regular BaseNode when container_mode is OFF
- setProxmoxContainerMode store action handles structural changes atomically
(children parentId/extent, node dimensions)
- CanvasContainer filters edges between container proxmox and its children
- Canvas load respects container_mode when assigning parentId/extent
Frontend:
- Split nodeTypes/edgeTypes into separate .ts files (react-refresh)
- Remove setState-in-effect in NodeModal (key prop reset)
- Fix handleSave accessed before declaration (useRef pattern)
- Exclude src/components/ui/** from eslint (shadcn generated)
- Use defineConfig from vitest/config for test type support
Backend:
- ruff --fix: sort imports, datetime.UTC alias
- Raise line-length to 120, ignore E501 in tests
- Break long update_node/update_edge signatures
- pyproject.toml: per-file-ignores for tests