wifi-densepose/frontend
ruv 224689a5bc feat(homecore-ui iter 6): Settings probe-before-persist token validation
CRUD increment 6/6 — closes the sprint. Bearer-token editor now
probes /api/config with the new value BEFORE writing it to
localStorage, so a typo'd or revoked token can't lock the UI out
of the backend.

Three actions:
  - Test token         probe /api/config, no localStorage write
  - Probe & Save       probe; write only on 2xx
  - Clear              remove from localStorage

Inline probe result with sigils:
  ✓ token accepted (40 ms) — server v0.1.0-alpha.0
  ✗ HTTP 401: unauthorized
  ⋯ probing /api/config…

`currently stored:` line shows masked + length: `dev-…ken (9 chars)`
so the operator can see what's persisted without exposing the secret.

Empty input → red border + disabled Test/Save buttons. Bad probes
do NOT persist (this is the whole point — never write a token that
the backend rejects).

frontend/src/pages/Settings.ts — full rewrite (~190 LOC, +110 vs
previous version). No new dependencies.

Browser-verified end-to-end:
  - Backend section: Home / 0.1.0-alpha.0 / RUNNING / components OK
  - Test token: probe ✓, 40 ms, version reported
  - Empty input: buttons disabled + red border
  - Probe & Save: persists to localStorage, toast shown,
    `currently stored:` updates to masked new token
  - Clear: localStorage null, `currently stored: (empty)`
  - 0 unexpected console errors

Note: a clean reload lands on Dashboard (the SPA router has no
URL-encoded view yet). The token persistence itself survives reload
correctly; route persistence is a small follow-up if you want
direct URLs like /?view=settings.

CRUD sprint summary (6/6 runtime-validated):
  iter 1  Add Entity                    e7215a16e
  iter 2  Edit Entity                   89190b6c2
  iter 3  Delete + DELETE route         c0bb6f4fc
  iter 4  Live validation polish        3f5a7411d
  iter 5  Call Service                  99c78f512
  iter 6  Settings probe-before-persist (this)

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-05-26 15:36:44 -04:00
..
src feat(homecore-ui iter 6): Settings probe-before-persist token validation 2026-05-26 15:36:44 -04:00
.gitignore HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00
README.md HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00
index.html HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00
package-lock.json HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00
package.json HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00
tsconfig.json HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00
vite.config.ts HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00
vitest.config.ts HOMECORE: native Rust/WASM/TS port of Home Assistant — ADRs 125-134 implementation (#800) 2026-05-25 22:47:48 -04:00

README.md

@ruvnet/homecore-frontend

HOMECORE web UI — built with Lit 3, TypeScript, and Vite. Design system mirrors the cognitum-v0 / v0-appliance dashboard (ADR-131).

Quick start

cd frontend
npm install
npm run dev          # http://localhost:5173

The Vite dev server proxies /apihttp://localhost:8123, so you need a homecore-api-server (or the wifi-densepose-sensing-server crate) running on :8123.

Scripts

Script Description
npm run dev Start Vite dev server on port 5173
npm run build TypeScript compile + Vite production bundle → dist/
npm run lint ESLint on src/
npm test Vitest unit tests (3 suites, jsdom)

Package layout

frontend/
  src/
    api/
      client.ts        # fetch + WebSocket client (REST + WS)
      types.ts         # TypeScript types matching homecore-api JSON shapes
    components/
      AppShell.ts      # <hc-app-shell> — header + nav + content slot
      StateCard.ts     # <hc-state-card> — single entity state card
    icons/
      lucide.ts        # Tree-shaken Lucide icon wrapper
    styles/
      tokens.css       # 16 CSS custom properties (--hc-*)
      base.css         # Typography reset, page shell, nav layout
    __tests__/         # Vitest unit tests
  index.html           # Shell loading src/main.ts
  vite.config.ts
  tsconfig.json
  vitest.config.ts

Design system

Colors, typography, and components mirror the cognitum-v0 dashboard (http://cognitum-v0:9000/). Dark-only; no light-mode. Key tokens:

  • --hc-primary #19d4e5 — teal (active nav, focus ring, CTA borders)
  • --hc-accent #26d867 — green (success, secondary CTA)
  • --hc-bg #0b0e13 — near-black navy page root
  • Font: Outfit (display) + JetBrains Mono (mono)
  • Icons: Lucide (SVG, stroke: currentColor, no icon font)

See docs/design/HOMECORE-FRONTEND-design-recon.md for the full recon.

Architecture notes

  • Components are standard Lit LitElement custom elements — compatible with any HTML page and with Home Assistant's Lit-based frontend.
  • The REST client uses fetch; the WS client uses WebSocket. Both accept a bearer token and are fully typed against the Rust homecore-api JSON shapes.
  • WASM: vite.config.ts enables .wasm asset import. Hook up via dynamic import('/path/to/module.wasm?init') when WASM bindings are ready.