Modernize the embedded web UI: React 19, Vite 8, TypeScript 7 - #37
Merged
Conversation
All five open /web bumps, as one change, because four of them could not land separately: hls.js 1.6.16 -> 1.7.3 (#26) react + types 18.3.1 -> 19.3.0 (#30) react-dom + types 18.3.1 -> 19.3.0 (#29) typescript 5.9.3 -> 7.0.2 (#21) @vitejs/plugin-react 4.7.0 -> 6.1.1 (#27) vite 5.4.21 -> 8.3.0 (no PR — see below) Why #27 was stuck: @vitejs/plugin-react 6 declares a peer of `vite: ^8.0.0`, and this project is on vite 5. No Dependabot PR bumped vite, so #27 could never be merged on its own — it needed a three-major vite jump that nothing was proposing. react/react-dom and their @types are likewise two pairs that have to move together. One source change was needed, and it is a latent gap rather than something the upgrade caused. TypeScript 7 rejects the side-effect CSS import in main.tsx: src/main.tsx(15,8): error TS2882: Cannot find module or type declarations for side-effect import of './styles.css'. The project never had `src/vite-env.d.ts` — the `/// <reference types="vite/client" />` file that `npm create vite` scaffolds and that declares the module shapes Vite invents at build time. TypeScript 5 let the untyped import slide; 7 does not. Added, with a comment saying so. Verified beyond "it compiles", since this is React 18 -> 19 and a rolldown-based Vite: npm run build (tsc -b && vite build) clean, 0 type errors vite preview + headless chromium React 19 mounts and renders The rendered DOM carries the real shell — header, brand, and the Cameras / Snapshots / Recordings / Local nav — so react-router works under 19. With no backend behind the preview server the page shows "Couldn't load cameras — Request failed with status 502" and the Command Center upsell card, which is the correct degraded state rather than a blank page. Chromium's console had no app-level errors or React warnings. Vite 8 builds with rolldown: 51 packages dropped from the tree and the build goes from ~1.7s to ~0.4s. Closes #21 Closes #26 Closes #27 Closes #29 Closes #30 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
All five open
/webbumps as one change, because four of them could notland separately.
hls.jsreact+@types/reactreact-dom+@types/react-domtypescript@vitejs/plugin-reactviteWhy #27 was stuck
@vitejs/plugin-react6 declares a peer ofvite: ^8.0.0, and thisproject is on vite 5. No Dependabot PR bumped vite, so #27 could never merge
on its own — it needed a three-major vite jump nothing was proposing.
react/react-domand their@typesare likewise two pairs that have tomove together.
One source change, and it's a pre-existing gap
TypeScript 7 rejects the side-effect CSS import in
main.tsx:The project never had
src/vite-env.d.ts— the/// <reference types="vite/client" />filenpm create vitescaffolds,which declares the module shapes Vite invents at build time (
*.css,import.meta.env, …). TypeScript 5 let the untyped import slide; 7 doesn't.Added, with a comment recording why.
Verification
This is React 18 → 19 and a rolldown-based Vite, so "it compiles" isn't
enough.
Build:
npm run build(tsc -b && vite build) — clean, 0 type errors.Actually rendered it: served the built bundle with
vite previewandloaded it in headless Chromium. The post-JS DOM carries the real shell:
…with the Cameras / Snapshots / Recordings / Local nav present, so
react-router works under 19. With no backend behind the preview server the
page shows "Couldn't load cameras — Request failed with status 502" plus
the Command Center upsell card — the correct degraded state, not a blank
page. Chromium's console had no app-level errors and no React warnings
(only Chromium's own GPU/sandbox infrastructure noise).
Bonus
Vite 8 builds with rolldown: 51 packages dropped from the tree, and the
build goes from ~1.7s to ~0.4s.
Closes #21
Closes #26
Closes #27
Closes #29
Closes #30
🤖 Generated with Claude Code