Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ jobs:
with:
fetch-depth: 0

- uses: actions/setup-node@v4
with:
node-version: "24"

- name: Build commercial React UI
working-directory: frontend
run: |
npm install --ignore-scripts
npm run build
git diff --exit-code -- ../static

- uses: actions/setup-python@v5
with:
python-version: "3.12"
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ venv/
__pycache__/
*.pyc

# frontend dependencies (the production bundle is committed under static/)
node_modules/

# insightface model cache
.insightface/
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## 6.0.0 — 2026-08-13

- **Complete product UI:** replaced the legacy monolithic interface with a responsive
React application inspired by the clear PROJECTS navigation model, with a granite
visual system and accessible semantic status colors.
- **Task-first navigation:** daily operation is now organized around Dashboard,
Needs review, Events, People, Cameras, Entry, Liveness, Guests and Automations;
calibration and engine tooling live behind progressive disclosure.
- **Commercial mobile experience:** added a real mobile drawer, touch-sized actions,
responsive cards/tables, bottom-sheet dialogs and clip playback that stays above
the event details on small screens.
- **Clear feedback:** loading, empty, success and error states are consistent across
every action, while destructive or security-sensitive operations remain explicit.
- **No lost expert capability:** added curated gallery and ignored-face management,
explicit Frigate import/export, safe merge/replace restore, body-learning handoff
from an event, editable camera map and a visit player that advances clips in route
order while every camera bubble remains directly selectable.
- **Cache-safe frontend:** versioned immutable UI assets are served by FastAPI while
the HTML shell remains no-store, preventing stale Home Assistant WebViews without
requiring private browsing.
- **Source and release guard:** the maintainable Vite/React source is committed and CI
rebuilds it, verifies the generated add-on UI and keeps version metadata aligned.

All notable changes to FaceID. The Home Assistant app shows this file in the
update dialog; standalone users can watch GitHub releases.

Expand Down
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# FaceID — self-hosted face recognition for Frigate + Home Assistant

## FaceID 5.1: a product workflow for homes and offices
## FaceID 6.0: a focused product interface for homes and offices

6.0 replaces the legacy single-file dashboard with a maintainable React interface.
The permanent task-based navigation keeps Home, review, investigation, people and
cameras immediately visible; calibration, body recognition, gallery maintenance,
Frigate library sync, privacy and logs live in a clearly labelled expert area. The
same layout becomes a touch-friendly drawer and bottom-sheet workflow on phones.

Every existing operational workflow has a home: bounded unknown review, visual
camera thresholds, intercom and liveness checks, guest access, Home Assistant entities,
calibration, safe backup/restore, curated Frigate import/export, editable site map and
sequential visit clips. The UI uses versioned immutable bundles while the HTML entry
point is always served `no-store`, preventing stale Home Assistant WebViews.

## FaceID 5.1: security and site intelligence

5.1 adds temporary guest passes with strict liveness/second-factor boundaries, a
drag-and-drop camera site map, anonymous Frigate person-traffic analytics and a visit
Expand Down Expand Up @@ -47,7 +61,7 @@ identity, human-reviewed DINOv2 body appearance with multi-event consensus, and
optional local Vision advisor. A face decision or explicit operator review establishes
identity; body and Vision are supporting signals and must never unlock a door alone.

Open **Advanced recognition** in the web UI to review Frigate person crops, approve or
Open **Expert tools → Body recognition** in the web UI to review Frigate person crops, approve or
reject body material, train the local model and run a historical three-way test. Start
with at least three varied full-person images per resident and add confirmed stranger
examples. Both `body_enabled` and `vision_advisor_enabled` remain off by default.
Expand Down Expand Up @@ -259,7 +273,7 @@ log with `journalctl -u faceid -f` until you see `MQTT verbunden (Success)`, the
**"Scan camera history"** — faces from past Frigate events land in the review queue,
pre-clustered per person, and already-known people are tagged in Frigate retroactively.
(CLI alternative: `venv/bin/python -m app.backfill --days 14`)
2. **Assign clusters** in the UI (Unknown tab): pick a name per cluster — select individual
2. **Assign clusters** in the UI (**Needs review**): pick a name per cluster — select individual
tiles first if a cluster contains a stray face. The ⛶ button shows the full snapshot
for context.
3. Once a few people exist, use **"apply suggestions"** to bulk-assign everything the
Expand Down Expand Up @@ -447,6 +461,21 @@ being unusual, it's automatically kept.
**Full details:** [docs/trimming.md](docs/trimming.md) explains the why, the exact
selection rule (with numbers), and how to restore or curate set-aside photos.

## The 6.0 product interface

The old tab wall was replaced with a responsive task-first interface. The daily workflow
is intentionally short: **Dashboard → Needs review → Events → People**. Cameras, entry,
liveness and guests live under **Security & entry**; Home Assistant and system health live
under **Management**. Calibration, body recognition, Frigate sync, privacy, routes and logs
are preserved under the collapsed **Expert tools** group.

The document shell is never cached, while its versioned JavaScript and CSS are immutable.
This lets Home Assistant load a new release without private browsing and without repeatedly
downloading unchanged assets.

Frontend source lives in `frontend/`; `npm run build` writes the deployable bundle to
`static/`. The production image does not require Node.js because the built files are committed.

## Seeing what it is doing

The **LOG tab** shows the last 500 log lines straight in the UI — including the quiet
Expand Down
2 changes: 1 addition & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = "5.3.0"
VERSION = "6.0.0"
12 changes: 12 additions & 0 deletions app/webui.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ def versioned_index(ui_version: str):
"""Compatibility alias only; Home Assistant ingress always enters at root."""
return _index_response()

@app.get("/assets/{asset_path:path}")
def ui_asset(asset_path: str):
"""Serve only the versioned frontend assets produced by Vite."""
base = (static_dir / "assets").resolve()
target = (base / asset_path).resolve()
if base not in target.parents or not target.is_file():
raise HTTPException(404, "Unknown UI asset")
response = FileResponse(target)
response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
response.headers["X-Content-Type-Options"] = "nosniff"
return response

@app.get("/api/persons")
def persons():
return gallery.persons()
Expand Down
23 changes: 23 additions & 0 deletions faceid-addon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## 6.0.0 — 2026-08-13

- **Complete product UI:** replaced the legacy monolithic interface with a responsive
React application inspired by the clear PROJECTS navigation model, with a granite
visual system and accessible semantic status colors.
- **Task-first navigation:** daily operation is now organized around Dashboard,
Needs review, Events, People, Cameras, Entry, Liveness, Guests and Automations;
calibration and engine tooling live behind progressive disclosure.
- **Commercial mobile experience:** added a real mobile drawer, touch-sized actions,
responsive cards/tables, bottom-sheet dialogs and clip playback that stays above
the event details on small screens.
- **Clear feedback:** loading, empty, success and error states are consistent across
every action, while destructive or security-sensitive operations remain explicit.
- **No lost expert capability:** added curated gallery and ignored-face management,
explicit Frigate import/export, safe merge/replace restore, body-learning handoff
from an event, editable camera map and a visit player that advances clips in route
order while every camera bubble remains directly selectable.
- **Cache-safe frontend:** versioned immutable UI assets are served by FastAPI while
the HTML shell remains no-store, preventing stale Home Assistant WebViews without
requiring private browsing.
- **Source and release guard:** the maintainable Vite/React source is committed and CI
rebuilds it, verifies the generated add-on UI and keeps version metadata aligned.

All notable changes to FaceID. The Home Assistant app shows this file in the
update dialog; standalone users can watch GitHub releases.

Expand Down
2 changes: 1 addition & 1 deletion faceid-addon/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = "5.3.0"
VERSION = "6.0.0"
12 changes: 12 additions & 0 deletions faceid-addon/app/webui.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ def versioned_index(ui_version: str):
"""Compatibility alias only; Home Assistant ingress always enters at root."""
return _index_response()

@app.get("/assets/{asset_path:path}")
def ui_asset(asset_path: str):
"""Serve only the versioned frontend assets produced by Vite."""
base = (static_dir / "assets").resolve()
target = (base / asset_path).resolve()
if base not in target.parents or not target.is_file():
raise HTTPException(404, "Unknown UI asset")
response = FileResponse(target)
response.headers["Cache-Control"] = "public, max-age=31536000, immutable"
response.headers["X-Content-Type-Options"] = "nosniff"
return response

@app.get("/api/persons")
def persons():
return gallery.persons()
Expand Down
4 changes: 2 additions & 2 deletions faceid-addon/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: FaceID
version: "5.3.0"
version: "6.0.0"
slug: faceid
description: Face recognition for Frigate — trainable gallery, clustered unknown review, HA sensors
url: https://github.com/r11a/faceid
Expand All @@ -12,7 +12,7 @@ boot: auto
init: false
ingress: true
ingress_port: 8600
ingress_entry: ui-5.3.0
ingress_entry: ui-6.0.0
panel_icon: mdi:face-recognition
panel_title: FaceID
ports:
Expand Down
1 change: 1 addition & 0 deletions faceid-addon/static/assets/faceid-6.0.0.css

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions faceid-addon/static/assets/faceid-6.0.0.js

Large diffs are not rendered by default.

Loading
Loading