Commit Graph

5 Commits

Author SHA1 Message Date
Louis King a5fabf7d46 chore(web): remove lit-html fallback & legacy code — Phase 4
The React frontend is complete (Phases 1-3); the lit-html fallback is dead
(its vendor globals were removed in Phase 3). Delete it and the scaffolding:

- Delete the entire src/meshcore_hub/web/static/js/spa/ lit-html tree,
  LitBridge.tsx, and legacy.d.ts.
- Remove the @legacy alias from vite.config.ts and tsconfig.json.
- Remove lit-html and qrcodejs from package.json (both unused now).
- Remove the lit-html fallback {% else %} branch from spa.html — the Vite
  build is now required to serve the UI (no fallback bundle).

Tests (fallback no longer exists):
- test_home/advertisements/nodes/messages.py: assert the React mount point
  (id="app") instead of a bundled-or-fallback script tag.
- test_caching.py: JS-cache tests are header-only (static JS is bundled into
  dist/, absent in test env; the middleware sets headers on 404 too); the
  dist-bundle HTML test drops its fallback branch.

Docs:
- AGENTS.md: new Frontend (React) section (host-run npm/vite/tsc toolchain,
  react-chartjs-2/react-leaflet/react-qr-code, CSS load order); clarified the
  compose-stack rule to exempt frontend tooling.
- REACT_MIGRATION.md: Phase 4 complete, final file structure, decisions.

Verified: tsc --noEmit clean, npm run build, full pytest (1463 passed,
22 skipped), pre-commit (passed).
2026-07-21 19:13:01 +01:00
Louis King 715659607a feat(web): React charts/maps/QR — Phase 3
Replace all window.Chart / window.L / window.QRCode globals and the
charts.js helper script with bundled React components:

- react-chartjs-2: typed config builders in utils/charts.ts
  (buildLineChart, buildActivityChart, buildStackedBar, buildRoutesTrend,
  buildRouteDetailStrip + ChartColors, averageRouteTier, routeQualityToTier)
  and wrappers in components/charts/Charts.tsx (ActivityChart,
  TrendLineChart, StackedBarChart, RoutesTrendChart, RouteDetailStrip).
  utils/charts.ts imports chart.js/auto. Wired into Home, Dashboard, Routes.
- react-leaflet: MapPage rewritten with MapContainer/TileLayer/Marker/Popup
  + a useMap MapController for fit-bounds and memoized markers; NodeDetail
  static hero map with divIcon marker + OffsetCenter. Both import
  leaflet/dist/leaflet.css.
- react-qr-code: replaces window.QRCode in Channels and NodeDetail.

Bundling & shell:
- Chart.js, Leaflet (+CSS), react-qr-code now bundled by Vite; removed the
  leaflet/chart.js/qrcodejs vendor <script>/<link> tags from spa.html and
  their copy steps from build.js (fonts stay vendored). Deleted charts.js.
- Moved the Vite CSS bundle (asset_app_css) into <head> before app.css so
  app.css dark-mode Leaflet overrides win over the bundled leaflet.css.
- Dropped the chart globals from the Window type declaration.

Tests/docs:
- test_caching.py: removed charts.js-specific tests; generic JS-cache tests
  now target spa/app.js.
- Updated charts.js cross-references in collector/routes.py + test_routes.py
  to point at spa-react/utils/charts.ts.

Verified: tsc --noEmit clean, npm run build (153 modules),
pytest tests/test_web (255 passed), pre-commit (passed).
2026-07-21 19:03:04 +01:00
Louis King 510612d69b feat(web): adopt self-hosted IBM Plex Sans and IBM Plex Mono typography
Replace the OS system font stack with IBM Plex: the variable-weight
sans (100-700, one file per subset) for UI and headings, and Plex Mono
400 for the public keys, packet hashes, and hex that font-mono renders
across the app. Latin + latin-ext subsets only (shipped locales are
en/nl); no italics; mono is never rendered bold here.

Fonts are self-hosted from @fontsource packages via the existing
build.js vendor pipeline (no CDN), copied to static/vendor/fonts/ with
a hard build failure on wrong filenames. Wiring:

- input.css: @theme --font-sans/--font-mono + @font-face rules with
  unicode-ranges taken verbatim from the package CSS; Tailwind v4
  derives the document default from --font-sans, re-fonting daisyUI
  components with no other changes.
- spa.html: preload the latin sans variable woff2 (crossorigin, URL
  identical to the @font-face src) to minimize FOUT.
- charts.js: Chart.defaults.font.family to match (Chart.js otherwise
  uses Helvetica/Arial).
- error.html: name-prepend only; the page stays dependency-free.
- middleware.py: long-term immutable cache for /static/vendor/fonts/
  (stable names referenced from CSS, so ?v= versioning can't apply),
  with a matching test.
- app.css: slight hero-title letter-spacing tightening for Plex at
  display sizes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 21:58:58 +01:00
Louis King 3057a4841b feat: add esbuild bundling with content-hash cache busting
Bundle SPA JavaScript with esbuild for production builds, generating
content-hashed filenames for immutable caching. Vendor assets (Leaflet,
Chart.js, QRCode.js) get SHA256-based query params. Locale JSON files
get a combined hash version. Falls back to unbuiltsources when dist/
is absent.
2026-05-05 18:27:41 +01:00
Louis King 189eb3a139 Add HTTP caching for web dashboard resources
Implement cache-control middleware to optimize browser caching and reduce
bandwidth usage. Static files are cached for 1 year when accessed with
version parameters, while dynamic content is never cached.

Changes:
- Add CacheControlMiddleware with path-based caching logic
- Register middleware in web app after ProxyHeadersMiddleware
- Add version query parameters to CSS, JS, and app.js references
- Create comprehensive test suite (20 tests) for all cache behaviors

Cache strategy:
- Static files with ?v=X.Y.Z: 1 year (immutable)
- Static files without version: 1 hour (fallback)
- SPA shell HTML: no-cache (dynamic config)
- Health endpoints: no-cache, no-store (always fresh)
- Map data: 5 minutes (location updates)
- Custom pages: 1 hour (stable markdown)
- API proxy: pass-through (backend controls)

All 458 tests passing, 95% middleware coverage.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-14 00:01:08 +00:00