perf(welcome): cut first-boot cold-start + add loading affordance #20

Merged
SilverLABS merged 1 commits from fix/welcome-cold-start into main 2026-06-10 08:27:18 +00:00
Owner

Problem

On first logon the SilverOS Welcome wizard showed nothing until WebView2 had cold-started and Blazor had booted — so the entire startup cost presented as a blank window, long enough that an operator believed first boot had failed before it finally rendered.

Launch path today: autounattend FirstLogonCommands → cmd /c powershell … Start-Process …App.exe -Verb RunAs over a locked-down Explorer shell. The only loading affordance was a bare, unstyled <div>Loading...</div> that didn't appear until WebView2 was already up.

Changes

1. Immediate native splash (the "never looks hung" fix)MainPage.xaml / MainPage.xaml.cs
A native MAUI Grid overlay (SilverOS wordmark + spinner + "Preparing your setup…") sits on top of the BlazorWebView. MAUI controls render in the first frame — no WebView2 / JIT dependency — so something branded is on screen immediately. It fades out on the first successful WV2 NavigationCompleted.

2. Seamless handoffwwwroot/index.html / wwwroot/css/app.css
Replaced <div>Loading...</div> with a visually identical in-page splash (same Mercury void/electric-ice tokens). It lives inside #app, so Blazor wipes it automatically on first render. native splash → webview splash → wizard reads as one continuous loading screen, no flashes of blank.

3. ReadyToRun precompileSilverOS.Welcome.App.csproj
PublishReadyToRun=true (guarded to publish-only). Removes first-run JIT — this app runs exactly once on the slowest cold-disk path. Trimming / NativeAOT deliberately avoided (unsafe for MAUI Blazor Hybrid reflection).

4. Fixed-version WebView2 runtime, baked offlineMauiProgram.cs / build.ps1 / runtime/webview2/README.md
Addresses the unresolved risk flagged in welcome-app-spec.md:108 — IoT Enterprise LTSC frequently ships no WebView2 at all. The app now points WEBVIEW2_BROWSER_EXECUTABLE_FOLDER at a fixed-version runtime baked next to the exe; build.ps1 stages it (mirrors the drivers pattern — absent is allowed and falls back to Evergreen for VM/dev tests). Fixed-version is just files, no first-boot install step → faster and air-gap friendly. Operator instructions in the new README.

Bonus — de-flashed launchautounattend.xml
Dropped the cmd /c wrapper and added -WindowStyle Hidden, removing the console-window flash (which itself read as "broken") and one process off the critical path. Elevation (-Verb RunAs) is retained (ApplyService needs it; silent via the baked UAC policy).

Verification

  • Release build clean (0 warnings, 0 errors)
  • dotnet publish -c Release -f net9.0-windows10.0.19041.0 -r win-x64 --self-contained true (the exact build.ps1 command) succeeds; R2R RTR\0 header confirmed in App/Core/UI/framework assemblies
  • 38/38 tests pass

Not covered here / follow-ups

  • Real-hardware before/after wall-clock needs a VM/device first-boot run. The existing Diag log at C:\ProgramData\SilverMetal\welcome.log already timestamps App ctor → CreateWindow → BlazorWebViewInitialized → NavigationCompleted for a direct breakdown.
  • Operator action: vendor the fixed-version WebView2 runtime into windows/welcome/runtime/webview2/ (see README) and pin it in inputs.manifest.json before shipping LTSC media. Without it the image falls back to Evergreen (build only warns).

🤖 Generated with Claude Code

## Problem On first logon the SilverOS Welcome wizard showed **nothing** until WebView2 had cold-started and Blazor had booted — so the entire startup cost presented as a blank window, long enough that an operator believed first boot had failed before it finally rendered. Launch path today: `autounattend` FirstLogonCommands → `cmd /c powershell … Start-Process …App.exe -Verb RunAs` over a locked-down Explorer shell. The only loading affordance was a bare, unstyled `<div>Loading...</div>` that didn't appear until WebView2 was *already* up. ## Changes **1. Immediate native splash (the "never looks hung" fix)** — `MainPage.xaml` / `MainPage.xaml.cs` A native MAUI `Grid` overlay (SilverOS wordmark + spinner + "Preparing your setup…") sits on top of the `BlazorWebView`. MAUI controls render in the first frame — no WebView2 / JIT dependency — so something branded is on screen immediately. It fades out on the first successful WV2 `NavigationCompleted`. **2. Seamless handoff** — `wwwroot/index.html` / `wwwroot/css/app.css` Replaced `<div>Loading...</div>` with a **visually identical** in-page splash (same Mercury void/electric-ice tokens). It lives inside `#app`, so Blazor wipes it automatically on first render. native splash → webview splash → wizard reads as one continuous loading screen, no flashes of blank. **3. ReadyToRun precompile** — `SilverOS.Welcome.App.csproj` `PublishReadyToRun=true` (guarded to publish-only). Removes first-run JIT — this app runs exactly once on the slowest cold-disk path. Trimming / NativeAOT deliberately avoided (unsafe for MAUI Blazor Hybrid reflection). **4. Fixed-version WebView2 runtime, baked offline** — `MauiProgram.cs` / `build.ps1` / `runtime/webview2/README.md` Addresses the unresolved risk flagged in `welcome-app-spec.md:108` — IoT Enterprise LTSC frequently ships **no** WebView2 at all. The app now points `WEBVIEW2_BROWSER_EXECUTABLE_FOLDER` at a fixed-version runtime baked next to the exe; `build.ps1` stages it (mirrors the drivers pattern — absent is allowed and falls back to Evergreen for VM/dev tests). Fixed-version is just files, no first-boot install step → faster **and** air-gap friendly. Operator instructions in the new README. **Bonus — de-flashed launch** — `autounattend.xml` Dropped the `cmd /c` wrapper and added `-WindowStyle Hidden`, removing the console-window flash (which itself read as "broken") and one process off the critical path. Elevation (`-Verb RunAs`) is retained (ApplyService needs it; silent via the baked UAC policy). ## Verification - ✅ Release build clean (0 warnings, 0 errors) - ✅ `dotnet publish -c Release -f net9.0-windows10.0.19041.0 -r win-x64 --self-contained true` (the exact build.ps1 command) succeeds; **R2R `RTR\0` header confirmed** in App/Core/UI/framework assemblies - ✅ 38/38 tests pass ## Not covered here / follow-ups - **Real-hardware before/after wall-clock** needs a VM/device first-boot run. The existing `Diag` log at `C:\ProgramData\SilverMetal\welcome.log` already timestamps `App ctor → CreateWindow → BlazorWebViewInitialized → NavigationCompleted` for a direct breakdown. - **Operator action:** vendor the fixed-version WebView2 runtime into `windows/welcome/runtime/webview2/` (see README) and pin it in `inputs.manifest.json` before shipping LTSC media. Without it the image falls back to Evergreen (build only warns). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
SilverLABS added 1 commit 2026-06-10 08:06:28 +00:00
perf(welcome): cut first-boot cold-start + add loading affordance
All checks were successful
Build SilverMetal Enhanced - Windows ISO / build (pull_request) Successful in 4m46s
30a168e853
The Welcome wizard showed nothing until WebView2 cold-started and Blazor
booted, so the whole startup cost presented as a blank window long enough
that operators thought first boot had failed.

- Native MAUI splash overlay (renders in the first frame, no WebView2/JIT
  dependency) + a visually identical in-page splash inside #app, so the
  native -> webview -> Blazor handoff reads as one continuous loading
  screen. Fades out on first successful WV2 NavigationCompleted.
- PublishReadyToRun=true (publish-only) to remove first-run JIT on the
  one-shot cold-disk path. R2R header verified present after publish.
- Fixed-version WebView2 runtime baked offline next to the exe (build.ps1
  stages it, app points WEBVIEW2_BROWSER_EXECUTABLE_FOLDER at it). Removes
  the Evergreen registry probe and the LTSC "no WebView2 at all" risk flagged
  in welcome-app-spec.md; air-gap friendly. Absent => falls back to Evergreen.
- De-flash launch: drop the `cmd /c` wrapper and add -WindowStyle Hidden in
  autounattend FirstLogonCommands (kills the console flash + one process).

Verified: Release build clean, win-x64 self-contained publish succeeds with
R2R confirmed, 38/38 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SilverLABS merged commit bd215cba54 into main 2026-06-10 08:27:18 +00:00
SilverLABS deleted branch fix/welcome-cold-start 2026-06-10 08:27:18 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: SilverLABS/SilverMetal#20