feat(01-03): implement echo chat UI with MudBlazor
Add ChatGPT-style chat interface using MudBlazor components. User messages display on the right (purple), bot echoes "success msg!" on the left. Includes app bar, centered 768px layout, bottom-anchored messages, and documented inline comments on every Blazor concept introduced. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
96
ARCHITECTURE.md
Normal file
96
ARCHITECTURE.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Architecture Decisions
|
||||
|
||||
## Blazor Hosting Model: Server vs WebAssembly
|
||||
|
||||
### How They Differ
|
||||
|
||||
| Aspect | Blazor Server | Blazor WASM |
|
||||
|--------|--------------|-------------|
|
||||
| Code runs | On the server | In the browser |
|
||||
| UI updates | Via SignalR WebSocket (server pushes diffs) | Locally in browser (no round-trip) |
|
||||
| Calling backend services | Direct — code is already server-side | Needs HTTP calls if accessing server resources |
|
||||
| Offline capable | No (requires persistent connection) | Yes |
|
||||
| Startup speed | Fast | Slower (downloads .NET runtime to browser) |
|
||||
|
||||
### Decision: Blazor WASM
|
||||
|
||||
This project uses **Blazor WebAssembly (standalone)** with a separate ASP.NET Core Web API backend.
|
||||
|
||||
## When Do You Need a Separate API Project?
|
||||
|
||||
There are two distinct concerns that are easy to conflate:
|
||||
|
||||
### 1. Consuming an External API (e.g. OpenAI)
|
||||
|
||||
Both Blazor Server and WASM can call external APIs directly from C# — no controller needed. The difference is **where that code executes**:
|
||||
|
||||
- **Blazor Server**: Code runs on the server. A service class calls OpenAI directly. API keys live safely in server memory. No controller, no exposed endpoint required.
|
||||
- **Blazor WASM**: Code runs in the browser. You *can* call OpenAI directly, but any **API key would be embedded in the browser download** — anyone could inspect it via browser dev tools. This is the primary reason to add a backend proxy.
|
||||
|
||||
### 2. Exposing an API Endpoint (e.g. ChatAgent.Api)
|
||||
|
||||
This is a separate concern. You expose an API endpoint when:
|
||||
|
||||
- Another application needs to communicate with your chat system
|
||||
- You want a REST API for mobile clients, scripts, or integrations
|
||||
- You need a server-side proxy to protect secrets from the browser (the WASM case above)
|
||||
|
||||
**Key insight:** You don't need an API endpoint to *use* an external service. You only need one in WASM to **keep secrets out of the browser**.
|
||||
|
||||
### 3. Component Updates Do Not Require an API
|
||||
|
||||
In both hosting models, Blazor components update themselves locally:
|
||||
|
||||
- Components hold state in fields/properties
|
||||
- Calling `StateHasChanged()` triggers a re-render
|
||||
- Components can call injected C# services directly
|
||||
- No HTTP round-trip is needed for UI updates
|
||||
|
||||
For example, a chat component that echoes "success msg!" back needs no API at all — a simple injected service handles it entirely within the client project.
|
||||
|
||||
## API Key Management Scenarios
|
||||
|
||||
The need for an API project in WASM depends on how secrets are managed:
|
||||
|
||||
| Scenario | WASM needs API project? | Why |
|
||||
|----------|------------------------|-----|
|
||||
| Raw API key in config | Yes | To keep the key out of browser-downloadable code |
|
||||
| Azure Key Vault | Yes | Browser sandbox cannot access Key Vault or managed identity |
|
||||
| API Management gateway (Azure APIM) with token auth | No | WASM calls the gateway directly; gateway handles auth via managed identity |
|
||||
| Blazor Server (any scenario) | No | Code is already server-side; secrets never leave the server |
|
||||
|
||||
### Enterprise Pattern: API Gateway
|
||||
|
||||
In enterprise environments, a common pattern avoids the need for a custom API proxy entirely:
|
||||
|
||||
1. An **API Management gateway** (e.g. Azure APIM) sits in front of the external service (e.g. OpenAI)
|
||||
2. The gateway authenticates via managed identity and handles secret retrieval
|
||||
3. The gateway exposes a public endpoint requiring only a subscription key or OAuth token
|
||||
4. WASM calls the gateway directly — no secrets in the browser, no custom API project needed
|
||||
|
||||
The "proxy" becomes infrastructure rather than application code.
|
||||
|
||||
## Current Project Structure
|
||||
|
||||
```
|
||||
ChatAgent.sln
|
||||
src/
|
||||
ChatAgent.Client/ -- Blazor WASM (standalone)
|
||||
Pages/ -- Routable page components
|
||||
Layout/ -- MainLayout, NavMenu
|
||||
Services/ -- Client-side services (e.g. ChatApiClient)
|
||||
Program.cs -- Client entry point, DI registration
|
||||
ChatAgent.Api/ -- ASP.NET Core Web API (backend proxy)
|
||||
Controllers/ -- API controllers (e.g. HealthController)
|
||||
Program.cs -- Server entry point, middleware config
|
||||
ChatAgent.Shared/ -- Models shared between Client and Api
|
||||
Models/ -- DTOs (e.g. HealthResponse)
|
||||
```
|
||||
|
||||
### Why Three Projects?
|
||||
|
||||
- **ChatAgent.Client**: The Blazor WASM app running in the browser
|
||||
- **ChatAgent.Api**: Exists to proxy requests that require server-side secrets (e.g. future OpenAI calls). Not needed for basic component interactions.
|
||||
- **ChatAgent.Shared**: Models referenced by both Client and Api, avoiding duplication
|
||||
|
||||
For the initial "echo success" phase, only ChatAgent.Client is actively used. The Api and Shared projects exist to support future integration with external services that require secret management.
|
||||
Reference in New Issue
Block a user