17 KiB
Frontend Dependency Upgrade Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Upgrade the Bete frontend to the newest feasible Rust/WASM dependency and build-tool surface, including pre-releases when verified.
Architecture: The frontend is a Leptos CSR WASM app in the services/frontend Cargo workspace. The upgrade is intentionally narrow: update manifests/tooling, refresh Cargo.lock, repair only compiler-required compatibility issues, and verify both local Trunk builds and the production proxy Docker build path.
Tech Stack: Rust, Cargo workspace, Leptos CSR, Trunk, wasm-bindgen/web-sys, Docker proxy image, pnpm root scripts.
Global Constraints
- Attempt newest visible releases, including pre-releases, for the main frontend stack.
- Prefer the newest version that passes verification over forcing a broken latest version.
- Initial target versions:
leptos = "0.9.0-alpha",leptos-use = "0.19",lucide-leptos = "3.23",trunk = "0.22.0-beta.1". - The current frontend toolchain is
nightly-2026-06-01; raise it if needed to satisfy Rust1.90.0requirements from Trunk beta. - Preserve dashboard behavior; do not redesign UI, change backend APIs, or do unrelated refactors.
- Keep edits scoped to manifests, lockfile, build tooling, and compatibility changes directly caused by the upgrade.
- Do not create implementation commits unless the user explicitly grants commit permission for implementation changes in this session.
File Structure
- Modify:
services/frontend/rust-toolchain.toml— pins the Rust toolchain andwasm32-unknown-unknowntarget for local frontend builds. - Modify:
services/frontend/frontend/Cargo.toml— direct dependency declarations for the Leptos CSR app. - Modify:
services/frontend/shared-types/Cargo.toml— direct dependency declarations for frontend-shared serde types. - Modify:
services/frontend/Cargo.lock— resolved frontend Cargo workspace dependency graph. - Modify:
infra/docker/Dockerfile.proxy— production build path that compiles the frontend WASM bundle and servesdistfrom nginx. - Inspect only unless needed:
.gitlab-ci.yml— CI already builds the proxy Docker image; only modify if Dockerfile changes require CI variables or arguments. - Compatibility edits may modify Rust files under
services/frontend/frontend/src/**/*.rsonly when the upgraded crates require API syntax changes.
Task 1: Establish baseline and choose deterministic build tool pins
Files:
- Inspect:
services/frontend/rust-toolchain.toml - Inspect:
services/frontend/frontend/Cargo.toml - Inspect:
infra/docker/Dockerfile.proxy - Modify: none in this task
Interfaces:
-
Consumes: Existing frontend workspace and root scripts.
-
Produces: Baseline command results and confirmed target pins for Task 2.
-
Step 1: Record current git state
git status --short
Expected: clean except for this plan file if it has not yet been committed. If there are unrelated user changes, stop and report them before editing dependency files.
- Step 2: Run current frontend typecheck baseline
pnpm run typecheck:web
Expected: PASS before dependency edits. If this fails before edits, save the output and report that the baseline is already broken.
- Step 3: Run current frontend release build baseline
pnpm run build:web
Expected: PASS before dependency edits. If this fails before edits, save the output and report that the baseline is already broken.
- Step 4: Confirm latest target metadata
cargo info leptos
cargo info leptos-use
cargo info lucide-leptos
cargo info trunk
Expected: metadata includes at least these target versions unless newer releases appeared during implementation:
leptos 0.9.0-alpha
leptos-use 0.19.0
lucide-leptos 3.23.0
trunk 0.22.0-beta.1
If newer versions appear, use the same max-feasible policy: attempt the newest visible version, including pre-release, then fall back only if verification fails.
Task 2: Update frontend toolchain and deterministic Docker Trunk install
Files:
- Modify:
services/frontend/rust-toolchain.toml - Modify:
infra/docker/Dockerfile.proxy - Inspect:
.gitlab-ci.yml
Interfaces:
-
Consumes: Target Trunk version from Task 1.
-
Produces: A deterministic local/Docker build-tool surface for dependency compilation.
-
Step 1: Replace the frontend toolchain pin
Edit services/frontend/rust-toolchain.toml to this content:
[toolchain]
channel = "nightly-2026-07-04"
components = ["rust-src", "rustc-dev"]
targets = ["wasm32-unknown-unknown"]
Rationale: the frontend currently has no #![feature(...)] gates, but keeping nightly avoids changing compiler channel semantics while moving past the Rust 1.90.0 requirement advertised by Trunk beta.
- Step 2: Verify the selected toolchain exists
cd services/frontend && rustup show active-toolchain && rustc --version
Expected: active toolchain is nightly-2026-07-04 or rustup installs it and then reports a Rust version at or above 1.90.0-nightly.
If nightly-2026-07-04 is unavailable, use the newest installed or installable nightly at or after 2026-07-04 that satisfies Rust 1.90.0 and update services/frontend/rust-toolchain.toml to that exact date.
- Step 3: Pin Trunk in the production proxy Dockerfile
In infra/docker/Dockerfile.proxy, replace:
RUN cargo install trunk --locked
with:
RUN cargo install trunk --version 0.22.0-beta.1 --locked
- Step 4: Inspect CI for required changes
grep -n "build-proxy\|Dockerfile.proxy\|SERVICE_NAME" .gitlab-ci.yml
Expected: CI builds infra/docker/Dockerfile.$SERVICE_NAME with SERVICE_NAME: proxy, so no .gitlab-ci.yml change is required.
If CI does not build Dockerfile.proxy, update the CI job so build-proxy builds infra/docker/Dockerfile.proxy and keep the existing image tags.
- Step 5: Check formatting of edited non-Rust files
git diff -- services/frontend/rust-toolchain.toml infra/docker/Dockerfile.proxy .gitlab-ci.yml
Expected: diff only changes the toolchain channel and Trunk install version unless CI inspection revealed a real mismatch.
Task 3: Upgrade Cargo manifests and refresh the frontend lockfile
Files:
- Modify:
services/frontend/frontend/Cargo.toml - Modify:
services/frontend/shared-types/Cargo.toml - Modify:
services/frontend/Cargo.lock
Interfaces:
-
Consumes: Toolchain and Docker Trunk pin from Task 2.
-
Produces: Updated Cargo dependency declarations and resolved lockfile for Task 4.
-
Step 1: Update direct frontend app dependencies
Edit the [dependencies] section in services/frontend/frontend/Cargo.toml to keep the existing dependency list and set these version requirements:
leptos = { version = "0.9.0-alpha", features = ["csr"] }
leptos-use = "0.19"
lucide-leptos = "3.23"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
js-sys = "0.3"
web-sys = { version = "0.3", features = [
"WebSocket",
"MessageEvent",
"CloseEvent",
"ErrorEvent",
"CanvasRenderingContext2d",
"AudioContext",
"AudioBuffer",
"AudioBufferSourceNode",
"AudioDestinationNode",
"AudioNode",
"AudioProcessingEvent",
"MediaStreamAudioSourceNode",
"ScriptProcessorNode",
"Window",
"Document",
"Element",
"HtmlElement",
"HtmlSelectElement",
"KeyboardEvent",
"Storage",
"IntersectionObserver",
"ResizeObserver",
"Url",
"Headers",
"Request",
"RequestInit",
"RequestMode",
"Response",
"HtmlInputElement",
"HtmlAudioElement",
"HtmlCanvasElement",
"MediaDevices",
"MediaStream",
"MediaStreamConstraints",
"MediaStreamTrack",
"Navigator",
"console",
] }
gloo-net = "0.6"
gloo-timers = "0.3"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde-wasm-bindgen = "0.6"
wasm-logger = "0.2"
console_error_panic_hook = "0.1"
regex = "1"
Do not remove shared-types = { path = "../shared-types" }.
- Step 2: Keep shared-types serde on latest compatible major
Confirm services/frontend/shared-types/Cargo.toml still contains:
[dependencies]
serde = { version = "1", features = ["derive"] }
No change is required unless cargo update reports a resolver issue.
- Step 3: Refresh the frontend workspace lockfile
cd services/frontend && cargo update
Expected: services/frontend/Cargo.lock updates to resolved versions compatible with the new manifest requirements.
- Step 4: Check direct resolved versions
cargo tree --manifest-path services/frontend/frontend/Cargo.toml -e normal --depth 1
Expected: direct tree includes the newest feasible resolved versions, ideally:
leptos v0.9.0-alpha
leptos-use v0.19.0
lucide-leptos v3.23.0
If Cargo cannot resolve leptos 0.9.0-alpha with leptos-use 0.19, try the newest mutually compatible pair and record the resolver error and fallback pair in the final report.
Task 4: Run compiler-driven compatibility repairs
Files:
- Modify as needed:
services/frontend/frontend/src/**/*.rs - Modify as needed:
services/frontend/frontend/Cargo.tomlonly for documented fallback versions - Modify as needed:
services/frontend/Cargo.lockafter fallback changes
Interfaces:
-
Consumes: Upgraded dependency graph from Task 3.
-
Produces: A compiling Leptos frontend with behavior-preserving source compatibility fixes.
-
Step 1: Run the upgraded typecheck
pnpm run typecheck:web
Expected: either PASS, or FAIL with concrete compiler errors from upgraded Leptos/tooling.
- Step 2: Apply compatibility fix pattern A for Leptos mount changes if needed
If the compiler reports that leptos::mount::mount_to_body(app::App) no longer matches the expected signature, edit services/frontend/frontend/src/lib.rs from:
// Mount the Leptos app to the body
leptos::mount::mount_to_body(app::App);
to:
// Mount the Leptos app to the body
leptos::mount::mount_to_body(|| leptos::view! { <app::App /> });
Then rerun:
pnpm run typecheck:web
Expected: the mount signature error disappears.
- Step 3: Apply compatibility fix pattern B for removed empty-view hacks if needed
If the compiler reports errors around statements like let _: () = view! { <></> }; or converting () into a view, replace the empty branch with an explicit empty view.
For services/frontend/frontend/src/features/live/components/voice_connection_card.rs, replace:
} else {
let _: () = view! { <></> };
().into_any()
}
with:
} else {
view! { <></> }.into_any()
}
Then rerun:
pnpm run typecheck:web
Expected: the empty-view conversion error disappears.
- Step 4: Apply compatibility fix pattern C for signal constructor changes if needed
If the compiler reports that RwSignal::new(...) is unavailable or deprecated as an error under Leptos alpha, convert local signal creation to the Leptos function form.
Example replacement in services/frontend/frontend/src/app.rs:
let auth = AuthContext {
authenticated: RwSignal::new(false),
password: RwSignal::new(String::new()),
};
becomes:
let auth = AuthContext {
authenticated: RwSignal::new(false),
password: RwSignal::new(String::new()),
};
Expected: no edit is needed unless the compiler makes this an error. If it is an error and Leptos documents a replacement such as RwSignal::new_with_options or signal, apply the smallest mechanical change consistently to all reported sites and rerun pnpm run typecheck:web.
- Step 5: Apply compatibility fix pattern D for event and property macro changes if needed
If the compiler reports view! macro errors around event/property syntax, keep the current behavior and update only the reported syntax. Typical sites include:
on:click=move |_| active_tab.set(tab4.clone())
prop:value=selected_guild
class:btn=true
style:background=move || if active_tab.get() == tab2 { "var(--surface-overlay)" } else { "" }
For each compiler-reported macro error, change only the syntax required by the new macro and rerun:
pnpm run typecheck:web
Expected: each macro error is removed without changing UI classes, inline styles, event behavior, or signal reads.
- Step 6: Decide fallback if alpha migration exceeds scope
If leptos 0.9.0-alpha causes broad API breakage across many components and the typecheck cannot be repaired with behavior-preserving mechanical edits, fall back to newest stable Leptos visible in cargo info leptos or documented by Cargo metadata.
Use these commands to test the fallback:
cd services/frontend
cargo update -p leptos --precise 0.8.14
cargo update
cd ../..
pnpm run typecheck:web
Expected: fallback version typechecks after minimal compatibility repairs. Record the attempted alpha error summary and selected fallback in the final report.
- Step 7: Finish with a passing typecheck
pnpm run typecheck:web
Expected: PASS.
Task 5: Verify release build, lint/test scope, and production Docker path
Files:
- Inspect:
package.json - Inspect:
.gitlab-ci.yml - Inspect/modify only if required:
infra/docker/Dockerfile.proxy
Interfaces:
-
Consumes: Compiling upgraded frontend from Task 4.
-
Produces: Verification evidence for the final response.
-
Step 1: Run the frontend release build
pnpm run build:web
Expected: PASS and Trunk writes release assets to services/frontend/frontend/dist.
- Step 2: Run root lint if relevant to changed files
pnpm run lint
Expected: PASS. If Biome does not cover the changed Rust/TOML/Docker files and running lint is not useful, report that it was skipped and why.
- Step 3: Run tests if relevant
pnpm run test
Expected: PASS if tests are runnable in this environment. If tests are unrelated to the frontend Rust workspace or fail for pre-existing service reasons, report the exact result and do not claim all tests pass.
- Step 4: Verify the production proxy Docker build path if Docker is available
docker build -f infra/docker/Dockerfile.proxy .
Expected: PASS and the build reaches the nginx runner stage after compiling the frontend WASM bundle.
If Docker is unavailable, permission-denied, or impractical in this environment, report that Docker verification was skipped with the exact error and rely on the passing local Trunk release build as the minimum production-path proxy.
- Step 5: Inspect final dependency and build-tool diff
git diff -- services/frontend/rust-toolchain.toml services/frontend/frontend/Cargo.toml services/frontend/shared-types/Cargo.toml services/frontend/Cargo.lock infra/docker/Dockerfile.proxy .gitlab-ci.yml services/frontend/frontend/src
Expected: diff contains only dependency/toolchain/build pin changes and compatibility edits required by the upgrade.
Task 6: Final review and report
Files:
- Inspect: all changed files from
git status --short - Modify: none unless review finds a concrete issue
Interfaces:
-
Consumes: Verification evidence from Task 5.
-
Produces: Final user-facing summary with versions, fallbacks, and verification results.
-
Step 1: Summarize changed files
git status --short
Expected: changed files are limited to the plan, frontend manifests/lockfile/toolchain, Dockerfile/CI if needed, and frontend Rust compatibility edits if needed.
- Step 2: Check resolved direct frontend versions
cargo tree --manifest-path services/frontend/frontend/Cargo.toml -e normal --depth 1
Expected: output shows the final resolved versions for leptos, leptos-use, lucide-leptos, and support crates.
- Step 3: Prepare final response
Include this information:
- Dependency targets attempted: leptos, leptos-use, lucide-leptos, trunk.
- Final resolved versions: copied from cargo tree/cargo metadata.
- Toolchain version: copied from services/frontend/rust-toolchain.toml and rustc --version.
- Fallbacks: none, or exact attempted version -> selected version with reason.
- Verification: exact commands run and PASS/FAIL/SKIPPED status.
- Docker: built successfully, or skipped with exact environment limitation.
- Step 4: Stop before committing implementation changes unless permission was granted
git diff --stat
Expected: final diff is ready for the user to review. Do not run git commit unless the user explicitly asks for a commit.