Skip to content

feat(ui): Add next gen frontend (Work in progress)#2215

Open
herberthobregon wants to merge 1 commit into
dalathegreat:mainfrom
herberthobregon:lit-frontend
Open

feat(ui): Add next gen frontend (Work in progress)#2215
herberthobregon wants to merge 1 commit into
dalathegreat:mainfrom
herberthobregon:lit-frontend

Conversation

@herberthobregon

@herberthobregon herberthobregon commented Apr 10, 2026

Copy link
Copy Markdown

WORK IN PROGRESS

What

  • Single-page application (SPA) built with Lit (Web Components), replacing HTML generated inside C++ (processor, string-built pages, battery-specific HTML snippets).
  • REST-style JSON APIs for dashboard, settings, battery status, CAN log, events, and “extra” battery data as structured rows—not HTML fragments.
  • Static shell + bundle: (WIP) the browser loads a minimal HTML shell and one JavaScript bundle; the firmware serves the bundle (precompressed with gzip) from the embedded web server alongside the existing routes.
  • Settings and advanced views (WIP) use the same POST /saveSettings and command endpoints as before, but the UI labels and selects are driven by data from the device (e.g. select_options on /api/settings) so enums stay in sync with the firmware.

Why

  1. Maintainability
    Mixing UI markup with C++ made every UI tweak a firmware rebuild and encouraged copy-pasted HTML across battery types. Moving the UI to TypeScript/Lit keeps view code in one place and uses normal web tooling (TypeScript, Vite, linting).

  2. Correct separation of concerns
    The device should expose state and actions (JSON, form posts), not presentation (tables, sections, styling). Battery-specific “extra” info is now label/value rows (and optional section titles); the SPA decides how to render them. That scales better as more batteries and screens are added.

  3. Bandwidth and flash
    Embedded devices benefit from small payloads. The production bundle is roughly ~60 kB raw and, with gzip, on the order of ~17–20 kB over the wire (exact numbers shift slightly each build). The web server sets Content-Encoding: gzip so clients download the compressed asset only, which keeps OTA and flash budgets predictable.

  4. Future-proofing
    A component-based SPA is easier to extend (new routes, mocks for local dev, i18n, accessibility) without touching the real-time C++ paths except to add or extend APIs.


How

  1. Build
    Vite bundles frontend/src into dist/app.bundle.js (and a tiny index.html shell where applicable). A small script emits C++ sources (app_bundle.cpp / app_bundle.h) that embed the gzipped bytes so the firmware can call request->beginResponse(..., data, len) with Content-Encoding: gzip.

  2. Serve
    The web server registers routes for the SPA entry and /app.bundle.js (gzip), while authenticated JSON routes power the Lit app. Legacy HTML pages are removed or reduced so there is a single UI story.

  3. Data flow
    Lit components call fetch (via a thin API layer) → JSON → reactive @state → declarative html templates. Forms that mirror the old POST body field names preserve compatibility with existing NVM handling in webserver.cpp.


Benefits of Lit (LitElement)

  • Small runtime
    Lit keeps a minimal and efficient core, reducing bundle size and improving performance.

  • Standards-based
    Components are real custom elements, compatible with all modern browsers and easy to integrate with vanilla JS or other tools.

  • Declarative templates
    html tagged templates enable efficient re-rendering and reduce boilerplate compared to manual DOM manipulation.

  • TypeScript-friendly
    Strong typing for properties and state, with clear component boundaries, improves safety and readability in large projects.

  • Scoped styles
    static styles or adoptedStyleSheets isolate CSS within the component, preventing global style collisions in multi-screen SPAs.

  • Framework-agnostic
    Lit is built on native HTMLElement and does not rely on proprietary syntaxes like JSX or custom DSLs. This ensures that JavaScript written today will remain valid and understandable decades into the future, independent of framework trends.


Summary

Topic Outcome
What Lit SPA + JSON APIs + gzip bundle served from the ESP32 web server.
Why Easier maintenance, separation of UI vs device logic, small wire size.
How Vite build → gzipped embed → routes; Lit consumes JSON and forms.
Lit Lightweight, standards-based components, good DX for a small footprint.

This architecture trades a bit of upfront tooling for clear boundaries, smaller transfers on the wire, and a UI that can evolve without turning every change into a C++ string-concatenation exercise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant