Rewrite all folder-level CLAUDE.md files; update root

net10.0 throughout; corrected EntryKey field name; documented *.Services split.
Two new files (DeepDrftWeb.Services, DeepDrftContent.Services). FileDatabase
README inaccuracies fixed (ImageVault, project target).
This commit is contained in:
Daniel Harvey
2026-05-16 21:45:56 -04:00
parent de0909f38f
commit 7cf3d965b6
10 changed files with 1233 additions and 869 deletions
+87 -117
View File
@@ -1,145 +1,115 @@
# CLAUDE.md - DeepDrftWeb
This file provides guidance to Claude Code (claude.ai/code) when working with the DeepDrftWeb project.
Guidance for working in the DeepDrftWeb project (the Blazor Web App host).
## Project Overview
See the root `CLAUDE.md` for full architecture overview. This file covers what is specific to this project.
DeepDrftWeb is the main web application using **Blazor Server/WebAssembly hybrid** architecture with **MudBlazor** UI framework. It serves as the front-end interface for the DeepDrft music management system.
## One-line purpose
## Architecture
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 `DeepDrftWeb.Services`.**
### Technology Stack
- **Blazor Hybrid**: Interactive Server + WebAssembly components
- **MudBlazor**: Material Design UI framework
- **Entity Framework Core**: SQLite database access
- **ASP.NET Core 9.0**: Web framework
## What lives here now (only)
### Project Structure
```
DeepDrftWeb/
├── Components/ # Blazor components (.razor files)
│ ├── App.razor # Root application component
│ ├── Pages/ # Page components
│ └── _Imports.razor # Global using statements
├── Controllers/ # MVC API controllers
├── Data/ # Database layer
│ ├── DeepDrftContext.cs # EF DbContext
│ ├── Configurations/ # EF configurations
│ ├── Migrations/ # EF migrations
│ └── Repositories/ # Data access layer
├── Services/ # Business logic layer
└── Program.cs # Application entry point
```
- `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).
## Key Patterns
## What does NOT live here anymore
- `DeepDrftContext`, `TrackRepository`, `TrackService`, `Configurations/`, `Migrations/` — all moved to `DeepDrftWeb.Services`. 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 `DeepDrftWeb.Client._Imports` as an additional assembly.
- **New routable pages go in `DeepDrftWeb.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 `DeepDrftWeb.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 `DeepDrftWeb.Client`), which manages `DotNetObjectReference` lifetimes for progress, end-of-playback, and spectrum callbacks.
## HTTP client wiring
Mostly in `DeepDrftWeb.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 `DeepDrftWeb.Services.TrackService.GetPaged`, and wraps the result:
### Service Architecture
```csharp
// Three-layer pattern: Controller → Service → Repository
TrackController TrackService TrackRepository DeepDrftContext
[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)
```
### Result Pattern
All service methods return `ResultContainer<T>` or `Result` for consistent error handling:
```csharp
public async Task<ResultContainer<TrackEntity?>> GetById(long id)
{
try
{
var track = await _repository.GetById(id);
return ResultContainer<TrackEntity?>.CreatePassResult(track);
}
catch (Exception e)
{
return ResultContainer<TrackEntity?>.CreateFailResult(e.Message);
}
}
```
If you're adding new SQL endpoints, this is the file. If you're adding new logic, that goes in `DeepDrftWeb.Services/TrackService.cs`.
### Paging Support
Uses `PagingParameters<T>` and `PagedResult<T>` from DeepDrftModels for consistent pagination:
```csharp
var parameters = new PagingParameters<TrackEntity>()
{
Page = pageNumber,
PageSize = pageSize,
OrderBy = entity => entity.TrackName,
IsDescending = sortDescending
};
```
## Development commands
## Development Commands
### Running the Application
```bash
# Run web application
# Run the web host (includes WASM from DeepDrftWeb.Client)
dotnet run --project DeepDrftWeb
# Watch for changes during development
# Watch during development
dotnet watch run --project DeepDrftWeb
```
### Entity Framework
```bash
# Add migration
dotnet ef migrations add MigrationName --project DeepDrftWeb
# Update database
dotnet ef database update --project DeepDrftWeb
# Drop database
dotnet ef database drop --project DeepDrftWeb
```
### Building
```bash
# Build project
# Build
dotnet build DeepDrftWeb
# Clean build
dotnet clean DeepDrftWeb && dotnet build DeepDrftWeb
# Add migration (run from solution root; creates in DeepDrftWeb.Services)
dotnet ef migrations add MigrationName --project DeepDrftWeb.Services --startup-project DeepDrftWeb
```
## Configuration
### Database Connection
- **Connection String**: `appsettings.json``ConnectionStrings.DefaultConnection`
- **Database Location**: `../Database/deepdrft.db` (SQLite)
- **Context**: `DeepDrftContext` with `TrackEntity` DbSet
- `appsettings.json`: `ConnectionStrings:DefaultConnection` (SQLite path), `ApiUrls:*` (backend base addresses), logging, logging config. Port binding via `Kestrel:Endpoints` or `ASPNETCORE_URLS`.
- 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.
### Service Registration
Key services registered in `Startup.ConfigureDomainServices()`:
- `DeepDrftContext` (EF DbContext)
- `TrackRepository` (Scoped)
- `TrackService` (Scoped)
## Important patterns
### HttpClient Setup
Configured for API communication with DeepDrftContent:
```csharp
builder.Services.AddHttpClient("DeepDrft.API", client =>
client.BaseAddress = new Uri(Startup.GetKestrelUrl(builder)));
```
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 `DeepDrftWeb.Services` for the contract.
## Important Notes
### Blazor Hybrid Architecture
- Server-side rendering with interactive components
- WebAssembly components from `DeepDrftWeb.Client`
- Shared assemblies for interactive modes
### MudBlazor Integration
- UI framework providing Material Design components
- Registered via `builder.Services.AddMudServices()`
### Repository Pattern
- Clean separation of concerns
- Async operations throughout
- CRUD operations for TrackEntity
### URL Configuration
Dynamic URL resolution via `Startup.GetKestrelUrl()` supporting:
- `ASPNETCORE_URLS` environment variable
- `Kestrel:Endpoints` configuration
- Development defaults (https://localhost:5001)
When working with this project, focus on maintaining the established patterns for service layer interaction, result handling, and Blazor component structure.
When working with this project, focus on the host surface (controllers, middleware, config) and prerender coordination. New domain logic goes in `DeepDrftWeb.Services`.