Files
deepdrft/DeepDrftPublic/CLAUDE.md
T

119 lines
6.5 KiB
Markdown

# CLAUDE.md - DeepDrftPublic
Guidance for working in the DeepDrftPublic project (the Blazor Web App host).
See the root `CLAUDE.md` for full architecture overview. This file covers what is specific to this project.
## One-line purpose
The Blazor Web App host. Owns HTTP surface (one controller + render-mode wiring), MudBlazor theme prerender, TypeScript→JS audio interop, and the SQL-side `api/track/page` endpoint. **Domain logic lives in `DeepDrftData`.**
## What lives here now (only)
- `Program.cs`, `Startup.cs`: HTTP host config, DI wiring, port binding.
- `Controllers/TrackController.cs`: Single controller. `GET api/track/page?pageNumber&pageSize&sortColumn&sortDescending` → service call → `ApiResultDto<PagedResult<TrackEntity>>`.
- `Services/DarkModeService.cs`: Server-side dark-mode prerender (reads `darkMode` cookie, seeds `DarkModeSettings.IsDarkMode` via `IHttpContextAccessor`, carries to WASM via `PersistentComponentState`).
- `Components/App.razor`: Root component with `@rendermode="InteractiveAuto"`. Calls `DarkModeService.InitializeAsync()` in `OnInitialized`.
- `Components/Pages/Error.razor`: Error fallback.
- `Interop/audio/`: TypeScript sources (one module per responsibility: `AudioContextManager.ts`, `StreamDecoder.ts`, `PlaybackScheduler.ts`, `SpectrumAnalyzer.ts`, `AudioPlayer.ts`, `index.ts`). Compiled to `wwwroot/js/audio/` via `Microsoft.TypeScript.MSBuild`. `tsconfig.json` **must not** be copied to output. In dev, raw `.ts` served from `/Interop/` for source-map debugging.
- `wwwroot/`: Static assets (compiled JS, CSS, fonts, images, favicons).
## What does NOT live here anymore
- `DeepDrftContext`, `TrackRepository`, `TrackService`, `Configurations/`, `Migrations/` — all moved to `DeepDrftData`. Do not add new repositories or EF code to this project.
- Any FileDatabase code — that lives in `DeepDrftContent.Services`.
## Blazor Web App render modes
Hybrid Blazor with `AddInteractiveServerComponents()` + `AddInteractiveWebAssemblyComponents()`.
- Root component is `<Routes @rendermode="InteractiveAuto" />` from `Components/App.razor`.
- WASM render-mode loads `DeepDrftPublic.Client._Imports` as an additional assembly.
- **New routable pages go in `DeepDrftPublic.Client/Pages`, not here** — the client project owns the interactive UI.
Server-side prerender happens before WASM kicks in. Dark mode, CORS, forwarded headers, and MudBlazor setup must all tolerate this split.
## Dark-mode prerender bridge
`DarkModeService` in this project reads the `darkMode` cookie via `IHttpContextAccessor` in `App.razor`'s `OnInitialized` and seeds `DarkModeSettings.IsDarkMode`. This setting is registered in `DeepDrftPublic.Client.Startup.ConfigureDomainServices`. The setting carries over to WASM via `PersistentComponentState` in `MainLayout.razor`.
The flow ensures the first paint uses the correct theme (no flash).
## TypeScript interop pipeline
Audio interop is TypeScript, not raw JS:
- Sources live in `Interop/audio/` with one module per responsibility.
- Compiled to `wwwroot/js/` via `Microsoft.TypeScript.MSBuild`.
- `index.ts` exposes all modules onto `window.DeepDrftAudio` for Blazor to invoke.
- `tsconfig.json` configured for ES module interop and must **not** be copied to output.
- In development, raw `.ts` is served from `/Interop/` for source-map debugging.
Blazor calls TypeScript via `AudioInteropService.ts` (a JS interop wrapper in `DeepDrftPublic.Client`), which manages `DotNetObjectReference` lifetimes for progress, end-of-playback, and spectrum callbacks.
## HTTP client wiring
Mostly in `DeepDrftPublic.Client.Startup`:
- Named clients `"DeepDrft.API"` (SQL metadata) and `"DeepDrft.Content"` (binary audio).
- Base addresses passed in from `appsettings.json` (`ApiUrls:ContentApi`, `ApiUrls:SqlApi`).
- `Startup.ConfigureApiHttpClient` and `Startup.ConfigureContentServices` are static methods called from **both** the server `Program.cs` and the WASM `Program.cs` so prerender and runtime see the same DI.
Server-side `Program.cs` adds:
- MudBlazor (`AddMudServices`)
- Controllers
- Render-mode components
- SignalR tuning (if needed)
- Forwarded headers
- Calls to `Startup.ConfigureApiHttpClient` / `ConfigureContentServices` / `ConfigureDomainServices`
## Reverse-proxy support
`UseForwardedHeaders()` runs first in the pipeline. HTTPS redirect is conditionally disabled via `ForwardedHeaders:DisableHttpsRedirection` so the app can sit behind nginx without forcing HTTPS at the host level.
## The one controller
`TrackController` is thin — it just deserializes query parameters, calls `DeepDrftData.TrackService.GetPaged`, and wraps the result:
```csharp
[HttpGet("api/track/page")]
public async Task<ActionResult<ApiResultDto<PagedResult<TrackEntity>>>> GetPage(
[FromQuery] int pageNumber = 1,
[FromQuery] int pageSize = 20,
[FromQuery] string? sortColumn = null,
[FromQuery] bool sortDescending = false)
```
If you're adding new SQL endpoints, this is the file. If you're adding new logic, that goes in `DeepDrftData/TrackService.cs`.
## Development commands
```bash
# Run the web host (includes WASM from DeepDrftPublic.Client)
dotnet run --project DeepDrftPublic
# Watch during development
dotnet watch run --project DeepDrftPublic
# Build
dotnet build DeepDrftPublic
# Add migration (run from solution root; creates in DeepDrftData)
dotnet ef migrations add MigrationName --project DeepDrftData --startup-project DeepDrftPublic
```
## Configuration
- `appsettings.json`: `ApiUrls:*` (backend base addresses), `Logging:*`, `AllowedHosts`, `ForwardedHeaders`. Port binding via `Kestrel:Endpoints` or `ASPNETCORE_URLS`.
- `environment/apikey.json`: DeepDrftContent API key. Loaded via CredentialTools (not in repo).
- `environment/connections.json`: SQL `DefaultConnection` and Auth connection strings. Loaded via CredentialTools (not in repo).
- `environment/authblocks.json`: AuthBlocks settings. Loaded via CredentialTools (not in repo).
- MudBlazor theme (`MainLayout.razor` in client): bespoke light ("Charleston in the Day") and dark ("Lowcountry Summer Nights") palettes.
- No `wwwroot/` changes during normal development — TS → JS compilation is automatic.
## Important patterns
All service calls in the controller return `ResultContainer<T>` or `Result`. The controller doesn't catch — it checks `Success` and returns 200/4xx/5xx accordingly. See `DeepDrftData` for the contract.
When working with this project, focus on the host surface (controllers, middleware, config) and prerender coordination. New domain logic goes in `DeepDrftData`.