Milestone-capping removal of the legacy Blazor Server / MudBlazor UI (#91 phase b). Every route it served now has SPA parity, so it is deleted. Follows docs/blazor-route-parity.md §5 (the removal runbook) and the auth-posture sign-off in docs/decisions.md (#206).
What changed
Deleted (206 files): ErsatzTV/Pages/**, Shared/**, ViewModels/** (39 edit VMs), Validators/** (10 edit-VM validators), App.razor, _Imports.razor, Locals/{Shared,Pages}/** (Blazor loc resx — Locals/Resources.* kept), wwwroot/css + wwwroot/lib, libman.json, and the orphaned MultiSelectBaseTests.cs.
Startup.cs (surgical): removed AddRazorPages/AuthorizeFolder("/"), AddServerSideBlazor, AddMudServices, AddSortable, AddCourier, the IHtmlSanitizer registration, the Blazor-attached OIDC UseAuthentication/UseAuthorization middleware (per #206), MapBlazorHub, and MapFallbackToPage("/_Host"). Renamed the branch blazor→legacy; it still co-hosts MapControllers(), /docs (Scalar), dev MapOpenApi() and the redirect middleware. Replaced the _Host fallback with a catch-allMapFallback → 302 /app, excluding /api|/artwork|/docs|/openapi (genuine 404) per #204.
Kept (must-not-break, per #206): OIDC/JWT/API-key service wiring (inert unless configured; real auth is #197), ConditionalIptvAuthorizeFilter (/iptv/*), ApiKeyAuthorizationFilter (mutating /api/*).
Pruned 9 now-unused packages (each verified zero remaining consumers) from Directory.Packages.props + ErsatzTV.csproj: MudBlazor, Heron.MudCalendar, Blazored.FluentValidation, BlazorSortable, MediatR.Courier.DependencyInjection, Markdig, HtmlSanitizer, Chronic.Core, NaturalSort.Extension. Also removed the now-dead #25 razor-Sonar NoWarn.
LegacyUiRedirects.cs: added the 14 /media/sources/* → /app/libraries/* redirects (SPA screens landed in #202) and lifted the #204-era /media/sources prefix ban.
Verification
dotnet build -c Release clean (0 errors; only the pre-existing NU1903 Microsoft.OpenApi advisory warning).
Full dotnet test ErsatzTV.sln green: ErsatzTV.Tests 1350, Core 493, Scanner 1467, Infrastructure 53, Architecture 5, FFmpeg 20 — 0 failed.
Updated Startup source-text tests + new regression tests: Blazor wiring is gone, the catch-all is wired, all 14 media-sources routes redirect.
No /api endpoint change → no OpenAPI regen; no web/ change.
Rollback
Tag blazor-final is cut on the pre-merge main commit as the first merge action (docs/decisions.md#205); restore = git checkout blazor-final (test image) or git revert this single merge commit.
Docs (same PR)
blazor-route-parity.md (phase b COMPLETE), decisions.md (removal entry), CLAUDE.md, contributing.md, README.md.
Gates before merge
Mandatory cold adversarial pass (in progress) + live-E2E redirect sweep + Fable go/no-go, then merge consent.
Milestone-capping removal of the legacy Blazor Server / MudBlazor UI (#91 phase b). Every route it served now has SPA parity, so it is deleted. Follows `docs/blazor-route-parity.md §5` (the removal runbook) and the auth-posture sign-off in `docs/decisions.md` (#206).
## What changed
- **Deleted** (206 files): `ErsatzTV/Pages/**`, `Shared/**`, `ViewModels/**` (39 edit VMs), `Validators/**` (10 edit-VM validators), `App.razor`, `_Imports.razor`, `Locals/{Shared,Pages}/**` (Blazor loc resx — `Locals/Resources.*` kept), `wwwroot/css` + `wwwroot/lib`, `libman.json`, and the orphaned `MultiSelectBaseTests.cs`.
- **`Startup.cs`** (surgical): removed `AddRazorPages`/`AuthorizeFolder("/")`, `AddServerSideBlazor`, `AddMudServices`, `AddSortable`, `AddCourier`, the `IHtmlSanitizer` registration, the Blazor-attached OIDC `UseAuthentication/UseAuthorization` middleware (per #206), `MapBlazorHub`, and `MapFallbackToPage("/_Host")`. Renamed the branch `blazor`→`legacy`; it still co-hosts `MapControllers()`, `/docs` (Scalar), dev `MapOpenApi()` and the redirect middleware. Replaced the `_Host` fallback with a **catch-all** `MapFallback` → 302 `/app`, excluding `/api|/artwork|/docs|/openapi` (genuine 404) per #204.
- **Kept** (must-not-break, per #206): OIDC/JWT/API-key **service** wiring (inert unless configured; real auth is #197), `ConditionalIptvAuthorizeFilter` (`/iptv/*`), `ApiKeyAuthorizationFilter` (mutating `/api/*`).
- **Pruned 9 now-unused packages** (each verified zero remaining consumers) from `Directory.Packages.props` + `ErsatzTV.csproj`: MudBlazor, Heron.MudCalendar, Blazored.FluentValidation, BlazorSortable, MediatR.Courier.DependencyInjection, Markdig, HtmlSanitizer, Chronic.Core, NaturalSort.Extension. Also removed the now-dead #25 razor-Sonar `NoWarn`.
- **`LegacyUiRedirects.cs`**: added the 14 `/media/sources/*` → `/app/libraries/*` redirects (SPA screens landed in #202) and lifted the #204-era `/media/sources` prefix ban.
## Verification
- `dotnet build -c Release` clean (0 errors; only the pre-existing NU1903 Microsoft.OpenApi advisory warning).
- Full `dotnet test ErsatzTV.sln` green: ErsatzTV.Tests 1350, Core 493, Scanner 1467, Infrastructure 53, Architecture 5, FFmpeg 20 — 0 failed.
- Updated Startup source-text tests + new regression tests: Blazor wiring is gone, the catch-all is wired, all 14 media-sources routes redirect.
- No `/api` endpoint change → no OpenAPI regen; no `web/` change.
## Rollback
Tag `blazor-final` is cut on the pre-merge `main` commit as the first merge action (`docs/decisions.md` #205); restore = `git checkout blazor-final` (test image) or `git revert` this single merge commit.
## Docs (same PR)
`blazor-route-parity.md` (phase b COMPLETE), `decisions.md` (removal entry), `CLAUDE.md`, `contributing.md`, `README.md`.
## Gates before merge
Mandatory cold adversarial pass (in progress) + live-E2E redirect sweep + Fable go/no-go, then merge consent.
Part of #91.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The ChicoryTV React SPA (web/, served at /app) now has full parity for every
route the Blazor UI served, so the legacy Blazor Server / MudBlazor UI is
deleted. This is the milestone-capping removal of #91 phase (b).
Deleted: ErsatzTV/Pages/**, Shared/**, ViewModels/** (39 edit VMs),
Validators/** (10 edit-VM validators), App.razor, _Imports.razor,
Locals/{Shared,Pages}/** (Blazor loc resx; Locals/Resources.* kept),
wwwroot/css + wwwroot/lib, libman.json, and the orphaned MultiSelectBaseTests.
Startup.cs (surgical, not wholesale): removed AddRazorPages/AuthorizeFolder,
AddServerSideBlazor, AddMudServices, AddSortable, AddCourier, the HtmlSanitizer
registration, the Blazor-attached OIDC UseAuthentication/UseAuthorization
middleware (per the #206 auth-posture sign-off), MapBlazorHub, and
MapFallbackToPage("/_Host"). Renamed the branch blazor->legacy; it still
co-hosts MapControllers, /docs (Scalar), dev MapOpenApi and the redirect
middleware. Replaced the _Host fallback with a catch-all (MapFallback ->
302 /app) that excludes /api|/artwork|/docs|/openapi (genuine 404) per #204.
Kept all OIDC/JWT/API-key service wiring (inert unless configured; real auth
is #197), ConditionalIptvAuthorizeFilter, ApiKeyAuthorizationFilter.
Pruned 9 now-unused packages (all verified zero remaining consumers) from
Directory.Packages.props + ErsatzTV.csproj: MudBlazor, Heron.MudCalendar,
Blazored.FluentValidation, BlazorSortable, MediatR.Courier.DependencyInjection,
Markdig, HtmlSanitizer, Chronic.Core, NaturalSort.Extension. Also removed the
now-dead #25 razor-Sonar NoWarn.
LegacyUiRedirects: added the 14 /media/sources/* -> /app/libraries/* redirects
(SPA screens landed in #202) and lifted the #204-era /media/sources prefix ban.
Tests: Release build clean; full solution suite green. Updated Startup
source-text tests + added regression coverage that Blazor wiring is gone, the
catch-all is wired, and all 14 media-sources routes redirect.
Docs: blazor-route-parity.md (phase b COMPLETE), decisions.md (removal entry),
CLAUDE.md, contributing.md, README.md all updated in this PR.
Rollback: tag blazor-final is cut on pre-merge main as the first merge action.
Part of #91.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cold-review Low-1: ErsatzTV/Extensions/NavigationManagerExtensions.cs survived
the removal — the last non-deleted .cs still importing
Microsoft.AspNetCore.Components/JSInterop and calling the deleted
blazorHelpers.scrollToFragment JS. Fully unreferenced (compiled only via the
shared framework). Removing it completes the Blazor deletion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codex-review nits: drop the now-inert "MudBlazor" Serilog level override in
appsettings.json (package removed) and reword the PlaylistController comment
that referenced the deleted Blazor MultiSelectBase.AddItemsToPlaylist path. No
behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Milestone-capping removal of the legacy Blazor Server / MudBlazor UI (#91 phase b). Every route it served now has SPA parity, so it is deleted. Follows
docs/blazor-route-parity.md §5(the removal runbook) and the auth-posture sign-off indocs/decisions.md(#206).What changed
ErsatzTV/Pages/**,Shared/**,ViewModels/**(39 edit VMs),Validators/**(10 edit-VM validators),App.razor,_Imports.razor,Locals/{Shared,Pages}/**(Blazor loc resx —Locals/Resources.*kept),wwwroot/css+wwwroot/lib,libman.json, and the orphanedMultiSelectBaseTests.cs.Startup.cs(surgical): removedAddRazorPages/AuthorizeFolder("/"),AddServerSideBlazor,AddMudServices,AddSortable,AddCourier, theIHtmlSanitizerregistration, the Blazor-attached OIDCUseAuthentication/UseAuthorizationmiddleware (per #206),MapBlazorHub, andMapFallbackToPage("/_Host"). Renamed the branchblazor→legacy; it still co-hostsMapControllers(),/docs(Scalar), devMapOpenApi()and the redirect middleware. Replaced the_Hostfallback with a catch-allMapFallback→ 302/app, excluding/api|/artwork|/docs|/openapi(genuine 404) per #204.ConditionalIptvAuthorizeFilter(/iptv/*),ApiKeyAuthorizationFilter(mutating/api/*).Directory.Packages.props+ErsatzTV.csproj: MudBlazor, Heron.MudCalendar, Blazored.FluentValidation, BlazorSortable, MediatR.Courier.DependencyInjection, Markdig, HtmlSanitizer, Chronic.Core, NaturalSort.Extension. Also removed the now-dead #25 razor-SonarNoWarn.LegacyUiRedirects.cs: added the 14/media/sources/*→/app/libraries/*redirects (SPA screens landed in #202) and lifted the #204-era/media/sourcesprefix ban.Verification
dotnet build -c Releaseclean (0 errors; only the pre-existing NU1903 Microsoft.OpenApi advisory warning).dotnet test ErsatzTV.slngreen: ErsatzTV.Tests 1350, Core 493, Scanner 1467, Infrastructure 53, Architecture 5, FFmpeg 20 — 0 failed./apiendpoint change → no OpenAPI regen; noweb/change.Rollback
Tag
blazor-finalis cut on the pre-mergemaincommit as the first merge action (docs/decisions.md#205); restore =git checkout blazor-final(test image) orgit revertthis single merge commit.Docs (same PR)
blazor-route-parity.md(phase b COMPLETE),decisions.md(removal entry),CLAUDE.md,contributing.md,README.md.Gates before merge
Mandatory cold adversarial pass (in progress) + live-E2E redirect sweep + Fable go/no-go, then merge consent.
Part of #91.
🤖 Generated with Claude Code