Files
Resume/.junie/plans/rename-website-to-web-and-convert-blazor-standalone.md
T
2026-09-09 13:38:34 -04:00

213 lines
12 KiB
Markdown

---
sessionId: session-260909-131140-mwcu
---
# Requirements
### Overview & Goals
The objective of this task is to rename the `Website` project to `Web` and migrate it from an ASP.NET Core server-hosted Blazor model to a Blazor Standalone (client-side WebAssembly) application.
Converting the resume website to a standalone WebAssembly client maximizes practical utility:
- **Zero Server Overhead:** Eliminates the ongoing cost, server compute requirements, and connection state management of Blazor Server.
- **Reliability & Availability:** Removes SignalR disconnection fragility for users viewing the resume, ensuring seamless offline and low-bandwidth reading.
- **Static Hostability:** Allows the build output to be deployed to any high-efficiency static storage or CDN provider (e.g., GitHub Pages, Cloudflare Pages, Azure Static Web Apps, AWS S3).
- **Naming Consistency:** Unifies the repository naming conventions around `Web`.
### Scope
#### In Scope
- Rename folder `Website` to `Web` and project file `Website.csproj` to `Web.csproj`.
- Update solution configuration `Resume.slnx`.
- Refactor all namespaces from `Website.*` to `Web.*`.
- Change project SDK to `Microsoft.NET.Sdk.BlazorWebAssembly`.
- Replace server package dependencies with `Microsoft.AspNetCore.Components.WebAssembly` and `Microsoft.AspNetCore.Components.WebAssembly.DevServer`.
- Add `wwwroot/index.html` as the host document.
- Migrate `Program.cs` to `WebAssemblyHostBuilder`.
- Convert `App.razor` to client router structure and purge server-only components (`ReconnectModal`, server-bound `Error.razor`).
- Update scoped CSS stylesheet references to `Web.styles.css`.
#### Out of Scope
- Altering the resume data models (`Overview.cs`, `PersonalInfo.cs`, `Skills.cs`, `WorkExperience.cs`) or resume content.
- Visual restyling of `Home.razor` or `MainLayout.razor`.
### User Stories
- As a recruiter or hiring manager viewing the resume, I want instant page load and resilient navigation without connection drops or server lag so that I can evaluate candidate qualifications smoothly.
- As a developer maintaining the site, I want a lightweight static client structure with clean `Web` naming so that deployment pipelines and local iteration are simple, cheap, and efficient.
### Functional Requirements
- The project must build and run successfully via `dotnet build` and `dotnet run`.
- Navigating to `/` must render the resume content (`Home.razor`) through `MainLayout.razor`.
- Navigating to undefined routes must display the not-found view (`NotFound.razor` / `<NotFound>`).
- Client asset loading (Bootstrap, `app.css`, scoped CSS, favicon) must resolve properly without 404 errors.
### Non-Functional Requirements
- **Efficiency:** The published output must consist strictly of static assets (WASM binaries, HTML, CSS, JS) suitable for edge distribution.
- **Compatibility:** Targets .NET 10.0 runtime with modern browser support.
# Technical Design
### Current Implementation
The application currently resides in directory `Website/` with project file `Website/Website.csproj` using `Microsoft.NET.Sdk.Web` on `net10.0`. It utilizes server-side interactive Razor Components with `WebApplication` builder, server routing, and `ReconnectModal` for SignalR circuit reconnections.
### Key Decisions
- **SDK & Package Strategy:** Transition from `Microsoft.NET.Sdk.Web` to `Microsoft.NET.Sdk.BlazorWebAssembly`. Remove `Microsoft.AspNetCore.Components.WebAssembly.Server` and install `Microsoft.AspNetCore.Components.WebAssembly` with `Microsoft.AspNetCore.Components.WebAssembly.DevServer` for seamless local debugging.
- **Client Host Document (`index.html`):** In standalone Blazor, the host page is `wwwroot/index.html` rather than `App.razor`. `index.html` will contain `#app` mount point, fallback loader, and script reference to `_framework/blazor.webassembly.js`.
- **Component Hierarchy:** Convert `App.razor` to contain the root `<Router>` component, delegating page rendering to `MainLayout` and pages.
- **Server Artifact Deletion:** Cleanly delete `ReconnectModal.razor` / `.css` / `.js` (SignalR circuit reconnects) and ASP.NET Core server-dependent `Error.razor` (`HttpContext.TraceIdentifier`).
### Proposed Changes
```
C:\Users\jonmc\Resume
├── Resume.slnx (Updated project path to Web/Web.csproj)
└── Web/ (Renamed from Website/)
├── Components/
│ ├── Layout/
│ │ ├── MainLayout.razor
│ │ └── MainLayout.razor.css
│ ├── Pages/
│ │ ├── Home.razor (Updated namespace Web.Data)
│ │ ├── Home.razor.css
│ │ └── NotFound.razor
│ ├── App.razor (Converted to client Router root)
│ └── _Imports.razor (Updated usings to Web.*)
├── Data/ (Updated namespaces to Web.Data)
│ ├── Overview.cs
│ ├── PersonalInfo.cs
│ ├── Skills.cs
│ └── WorkExperience.cs
├── Properties/
│ └── launchSettings.json (Updated profiles for WebAssembly dev server)
├── wwwroot/
│ ├── index.html (Added client host document)
│ ├── app.css
│ ├── favicon.png
│ └── lib/bootstrap/...
├── Program.cs (WebAssemblyHostBuilder startup)
└── Web.csproj (Renamed & converted to BlazorWebAssembly SDK)
```
### Data Models & Contracts
Data classes remain statically available under `Web.Data`:
- `Web.Data.Overview.Get()` -> `Overview.Data`
- `Web.Data.PersonalInfo.Get()` -> `PersonalInfo.Data`
- `Web.Data.Skills.Get()` -> `Skills.Data`
- `Web.Data.WorkExperience.Get()` -> `WorkExperience.Data`
### Entry Point Contract (`Web/Program.cs`)
```csharp
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Web;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
```
### Root Host Document (`Web/wwwroot/index.html`)
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jonathan McCaffrey - Resume</title>
<base href="/" />
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="Web.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
</head>
<body>
<div id="app">
<svg class="loading-progress">
<circle r="40%" cx="50%" cy="50%" />
<circle r="40%" cx="50%" cy="50%" />
</svg>
<div class="loading-progress-text"></div>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
```
### Project File Contract (`Web/Web.csproj`)
```xml
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>Web</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.6" PrivateAssets="all" />
</ItemGroup>
</Project>
```
# Testing
### Validation Approach
Verification focuses on compilation integrity, project file correctness, client asset resolution, and routing fidelity under the standalone execution model.
### Key Scenarios
- **Build Verification:** Run `dotnet build` on `Resume.slnx` and `Web/Web.csproj` to confirm zero compilation warnings or errors across the new namespaces.
- **Startup Execution:** Launch the project via `dotnet run --project Web/Web.csproj` and verify that the development server starts up cleanly on the configured localhost port.
- **Root Page Rendering (`/`):** Verify `index.html` loads, WebAssembly runtime bootstraps `App.razor`, and `Home.razor` displays Jonathan McCaffrey's overview, contact info, skills, and work experience.
- **Routing & Not Found (`/invalid-path`):** Verify that navigating to unmapped routes renders the `NotFound` component inside `MainLayout`.
- **Static Assets Integrity:** Check that Bootstrap, `app.css`, `Web.styles.css`, and `favicon.png` are returned with HTTP 200 responses.
### Edge Cases
- Scoped CSS bundle path changes (`Website.styles.css` -> `Web.styles.css`) properly reflected in `index.html`.
- No lingering references to `Website` in usings, project configurations, or solution metadata.
- Clean removal of `ReconnectModal` and `Error.razor` without dangling references in `App.razor` or `_Imports.razor`.
# Delivery Steps
### ✓ Step 1: Rename project files, solution references, and namespace declarations
The project directory, project file, solution definition, and all source namespaces are unified under `Web`.
- Rename the directory `Website` to `Web` and rename `Website.csproj` to `Web.csproj`.
- Update the solution file `Resume.slnx` to reference `Web/Web.csproj` instead of `Website/Website.csproj`.
- Update the `<RootNamespace>` in `Web.csproj` to `Web`.
- Refactor all C# namespace declarations in `Web/Data/Overview.cs`, `Web/Data/PersonalInfo.cs`, `Web/Data/Skills.cs`, and `Web/Data/WorkExperience.cs` from `Website.Data` to `Web.Data`.
- Refactor `@using Website.*` statements across `Web/Components/_Imports.razor`, `Web/Components/Pages/Home.razor`, and `Web/Program.cs` to `Web.*`.
- Update scoped CSS bundle link references from `Website.styles.css` to `Web.styles.css`.
### ✓ Step 2: Convert project SDK and package dependencies to Blazor Standalone
The project file is configured as a standalone Blazor WebAssembly application with client-side runtime packages and tooling.
- Update the project SDK in `Web.csproj` from `Microsoft.NET.Sdk.Web` to `Microsoft.NET.Sdk.BlazorWebAssembly`.
- Remove the server hosting package `Microsoft.AspNetCore.Components.WebAssembly.Server`.
- Add `Microsoft.AspNetCore.Components.WebAssembly` (version `10.0.*`) as a runtime package reference.
- Add `Microsoft.AspNetCore.Components.WebAssembly.DevServer` (version `10.0.*`, `PrivateAssets="all"`) for local development execution.
- Update `Web/Properties/launchSettings.json` to streamline local development profiles with the WebAssembly debug proxy and browser launch.
### ✓ Step 3: Restructure client entry point, HTML host, and Blazor component hierarchy
The application boots as a client-side WebAssembly single-page application using `index.html` and `WebAssemblyHostBuilder`.
- Create `Web/wwwroot/index.html` with root mounting target `#app`, `<HeadOutlet />` integration, static stylesheet references, and `_framework/blazor.webassembly.js`.
- Rewrite `Web/Program.cs` to initialize `WebAssemblyHostBuilder.CreateDefault(args)`, mount `App` to `#app` and `HeadOutlet` to `head::after`, configure standard scoped `HttpClient`, and execute `await builder.Build().RunAsync()`.
- Update `Web/Components/App.razor` to act as the client component router containing `<Router>`, `<Found>`, and `<NotFound>` definitions.
- Remove server-specific artifacts that are obsolete in standalone mode: `Web/Components/Layout/ReconnectModal.razor`, `ReconnectModal.razor.css`, `ReconnectModal.razor.js`, and `Web/Components/Pages/Error.razor`.
- Clean up `Web/Components/_Imports.razor` to remove server render-mode directives and include client WebAssembly namespaces.
- Move or verify client configuration files in `Web/wwwroot/` if required for client settings.