6.0 KiB
6.0 KiB
Phase 5: Blazor Hybrid Host + Theme + Localization
Status: ⬜ Not Started Parent plan: PLAN.md Domain: frontend Implementer: Opus + frontend-design skill
Objective
Create the WPF + BlazorWebView host that loads Marathon.UI (Razor Class Library),
establish the design system / theme using MudBlazor, set up bilingual (RU/EN)
localization end-to-end, and wire up DI to compose Application + Infrastructure layers.
Tasks
- In
src/Marathon.Hosts.WpfBlazor/Marathon.Hosts.WpfBlazor.csproj:- Set
<UseWPF>true</UseWPF>,<UseWindowsForms>false</UseWindowsForms> - SDK:
Microsoft.NET.Sdk.Razor(so Razor + WPF interop works) - Add packages:
Microsoft.AspNetCore.Components.WebView.WpfMudBlazorMicrosoft.Extensions.HostingSerilog.Extensions.HostingSerilog.Sinks.FileSerilog.Sinks.Console
- Set
- In
src/Marathon.UI/Marathon.UI.csproj:- SDK:
Microsoft.NET.Sdk.Razor <TargetFramework>net8.0</TargetFramework>with WebView for Razor Components- Add
MudBlazor(so components in this RCL can use MudBlazor)
- SDK:
- Create
Marathon.UI/_Imports.razorwith namespace and component imports (Microsoft.AspNetCore.Components.*, MudBlazor, project namespaces). - Create
Marathon.UI/wwwroot/index.html(Blazor host HTML for the WebView). - Create
Marathon.UI/MainLayout.razorwith MudBlazorMudLayout+MudAppBar+MudDrawernavigation. Include locale switcher (RU/EN) in the AppBar. - Create
Marathon.UI/Pages/Home.razorplaceholder dashboard. - Create
Marathon.UI/Pages/Settings.razor— bound to allappsettings.jsonoptions (ScrapingOptions, WorkerOptions, StorageOptions, AnomalyOptions, LocalizationOptions). Live save viaIOptionsMonitor+ writing back toappsettings.Local.json. - Establish theme tokens in
Marathon.UI/Theme/MarathonTheme.cs— distinctive palette per frontend-design guidance, NOT generic AI-default. Include:- Primary, secondary, accent
- Surface tones for light + dark mode
- Typography stack (RU-friendly font for Cyrillic — e.g., Inter or Manrope which have full Cyrillic coverage)
- Spacing scale, radius scale, shadow scale as CSS variables in a
app.css
- Wire MudBlazor theme via
MudThemeProviderinMainLayout.razor. - Localization:
- Add
Microsoft.Extensions.LocalizationtoMarathon.UI - Create
Marathon.UI/Resources/SharedResource.cs(marker class forIStringLocalizer) - Add
Marathon.UI/Resources/SharedResource.ru.resxandSharedResource.en.resxwith all UI strings used in this phase + placeholders for later phases - Configure supported cultures in host:
ru-RU,en-US - Locale switcher persists choice to
appsettings.Local.jsonand reloads UI
- Add
- In
src/Marathon.Hosts.WpfBlazor/MainWindow.xaml:- Single
BlazorWebViewfilling the window HostPage="wwwroot/index.html"RootComponentsadd<RootComponent Selector="#app" ComponentType="{x:Type ui:MainLayout}" />
- Single
- In
src/Marathon.Hosts.WpfBlazor/App.xaml.cs:- Build
IHostviaHost.CreateApplicationBuilder() - Call
services.AddMarathonInfrastructure(config) - Call
services.AddMarathonApplication(config) - Call
services.AddWpfBlazorWebView() - Add MudBlazor:
services.AddMudServices() - Configure Serilog (rolling file at
./logs/marathon-.log, console) - Start the host on
OnStartup, stop onOnExit
- Build
- Add
appsettings.jsontoMarathon.Hosts.WpfBlazor/(move from Phase 3 if placed there) with all sections. Addappsettings.Development.jsontemplate. - Tests in
Marathon.UI.Tests(using bUnit):- Test:
MainLayoutrenders without errors - Test: locale switcher changes culture
- Test: theme tokens are applied (CSS variables present in DOM)
- Test:
Files to Modify/Create
src/Marathon.UI/_Imports.razorsrc/Marathon.UI/MainLayout.razorsrc/Marathon.UI/Pages/Home.razor,Pages/Settings.razorsrc/Marathon.UI/Theme/MarathonTheme.cs,Theme/app.csssrc/Marathon.UI/wwwroot/index.htmlsrc/Marathon.UI/Resources/SharedResource.{cs,ru.resx,en.resx}src/Marathon.UI/Components/LocaleSwitcher.razorsrc/Marathon.Hosts.WpfBlazor/App.xaml,App.xaml.cssrc/Marathon.Hosts.WpfBlazor/MainWindow.xaml,MainWindow.xaml.cssrc/Marathon.Hosts.WpfBlazor/appsettings.json,appsettings.Development.jsonsrc/Marathon.Hosts.WpfBlazor/Properties/AssemblyInfo.cstests/Marathon.UI.Tests/MainLayoutTests.cs,LocaleSwitcherTests.cs
Acceptance Criteria
- Host project compiles (Big Bang smoke check).
Marathon.UIis a clean RCL — usable from any host (verifies portability).- Theme is distinct, not generic — implementer should follow
frontend-designskill guidance for typography, color, motion, spatial composition. - Locale switcher works (toggles between RU and EN strings on the same page).
- Settings page surfaces every configurable parameter from
appsettings.json.
Notes
- This phase is parallelizable with Phases 2 and 3 (only depends on Phase 1 Domain, but the orchestrator can run all three after Phase 1 completes).
- The frontend-design skill content is provided to the agent in
FRONTEND_DESIGN_SKILLcontext block. Follow it precisely. - Use Cyrillic-friendly fonts (Inter, Manrope, IBM Plex Sans, JetBrains Mono).
- For BlazorWebView in WPF, the project SDK MUST be
Microsoft.NET.Sdk.Razorand the OutputType set toWinExewith WPF enabled.
Review Checklist
- Compiles
Marathon.UIreferences no host-specific code (BlazorWebView, WPF)- Theme not generic — distinctive palette + typography
- All
appsettings.jsonkeys reachable via the Settings page - RU + EN both renderable (placeholder strings ok for later phases)
- Accessibility: keyboard navigation in nav drawer, focus indicators