refactor(split): rename DeepDrftWeb -> DeepDrftPublic and DeepDrftWeb.Client -> DeepDrftPublic.Client (Phase 4)

This commit is contained in:
Daniel Harvey
2026-05-19 23:06:16 -04:00
parent a981a99978
commit e5b4a79727
83 changed files with 116 additions and 116 deletions
+2 -2
View File
@@ -9,8 +9,8 @@ public static class CmsStartup
// CMS-specific services registered here as implementation waves land. // CMS-specific services registered here as implementation waves land.
// //
// Note: ITrackService (and its dependencies: TrackRepository, DeepDrftContext) is registered // Note: ITrackService (and its dependencies: TrackRepository, DeepDrftContext) is registered
// by DeepDrftWeb.Startup.ConfigureDomainServices, not here. The CMS RCL runs inside the // by DeepDrftPublic.Startup.ConfigureDomainServices, not here. The CMS RCL runs inside the
// DeepDrftWeb host, which wires those up before this method is called. A standalone CMS // DeepDrftPublic host, which wires those up before this method is called. A standalone CMS
// host would need to register ITrackService separately. // host would need to register ITrackService separately.
return services; return services;
} }
@@ -121,7 +121,7 @@ public class TrackController : ControllerBase
} }
// POST api/track/upload: raw WAV in (multipart/form-data) + metadata → unpersisted TrackEntity out. // POST api/track/upload: raw WAV in (multipart/form-data) + metadata → unpersisted TrackEntity out.
// Used by the CMS upload flow on DeepDrftWeb; that host proxies the upload here so it never // Used by the CMS upload flow on DeepDrftPublic; that host proxies the upload here so it never
// touches the vault disk path directly (Option B in CMS-PLAN §5). // touches the vault disk path directly (Option B in CMS-PLAN §5).
// //
// RequestSizeLimit/MultipartBodyLengthLimit set to 1 GB: WAV uploads can be tens to hundreds // RequestSizeLimit/MultipartBodyLengthLimit set to 1 GB: WAV uploads can be tens to hundreds
+3 -3
View File
@@ -8,13 +8,13 @@ public class DeepDrftContextFactory : IDesignTimeDbContextFactory<DeepDrftContex
public DeepDrftContext CreateDbContext(string[] args) public DeepDrftContext CreateDbContext(string[] args)
{ {
// Load the real connection string from environment/connections.json — the same // Load the real connection string from environment/connections.json — the same
// file DeepDrftWeb's Program.cs loads via CredentialTools. When EF tools run with // file DeepDrftPublic's Program.cs loads via CredentialTools. When EF tools run with
// --startup-project DeepDrftWeb, the working directory resolves there, so this // --startup-project DeepDrftPublic, the working directory resolves there, so this
// relative path works without any env var configuration. // relative path works without any env var configuration.
const string relPath = "environment/connections.json"; const string relPath = "environment/connections.json";
if (!File.Exists(relPath)) if (!File.Exists(relPath))
throw new FileNotFoundException( throw new FileNotFoundException(
$"'{relPath}' not found. Run EF commands with --startup-project DeepDrftWeb " + $"'{relPath}' not found. Run EF commands with --startup-project DeepDrftPublic " +
$"from the solution root (current dir: {Directory.GetCurrentDirectory()}).", relPath); $"from the solution root (current dir: {Directory.GetCurrentDirectory()}).", relPath);
using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(relPath)); using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(relPath));
+2 -2
View File
@@ -1,8 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftWeb", "DeepDrftWeb\DeepDrftWeb.csproj", "{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftPublic", "DeepDrftPublic\DeepDrftPublic.csproj", "{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftWeb.Client", "DeepDrftWeb.Client\DeepDrftWeb.Client.csproj", "{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftPublic.Client", "DeepDrftPublic.Client\DeepDrftPublic.Client.csproj", "{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftModels", "DeepDrftModels\DeepDrftModels.csproj", "{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftModels", "DeepDrftModels\DeepDrftModels.csproj", "{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}"
EndProject EndProject
+1 -1
View File
@@ -7,7 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<!-- EF Core kept in sync with DeepDrftData / DeepDrftWeb so the same DbContext registration compiles. --> <!-- EF Core kept in sync with DeepDrftData / DeepDrftPublic so the same DbContext registration compiles. -->
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.7" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" />
+2 -2
View File
@@ -120,7 +120,7 @@ builder.Services.Configure<ForwardedHeadersOptions>(options =>
}); });
// Controllers: discovers CMS mutation controllers (CmsUploadController, CmsEditController, // Controllers: discovers CMS mutation controllers (CmsUploadController, CmsEditController,
// CmsDeleteController) and the AuthBlocks surface. Matches DeepDrftWeb precedent. // CmsDeleteController) and the AuthBlocks surface. Matches DeepDrftPublic precedent.
builder.Services.AddControllers(); builder.Services.AddControllers();
// InteractiveServer only — no WASM render mode on the CMS host. // InteractiveServer only — no WASM render mode on the CMS host.
@@ -179,7 +179,7 @@ app.MapRazorComponents<App>()
app.Run(); app.Run();
// Local helper — mirrors DeepDrftWeb.Startup.GetKestrelUrl. Kept inline because this host's // Local helper — mirrors DeepDrftPublic.Startup.GetKestrelUrl. Kept inline because this host's
// only consumer is right here; promoting to a shared library would be premature. // only consumer is right here; promoting to a shared library would be premature.
static string GetKestrelUrl(WebApplicationBuilder builder) static string GetKestrelUrl(WebApplicationBuilder builder)
{ {
@@ -1,6 +1,6 @@
# CLAUDE.md - DeepDrftWeb.Client # CLAUDE.md - DeepDrftPublic.Client
Guidance for working in the DeepDrftWeb.Client project (the Blazor WebAssembly assembly). Guidance for working in the DeepDrftPublic.Client project (the Blazor WebAssembly assembly).
See the root `CLAUDE.md` for full architecture overview. This file covers what is specific to this project. See the root `CLAUDE.md` for full architecture overview. This file covers what is specific to this project.
@@ -76,7 +76,7 @@ Both are configured with JSON serializer settings (case-insensitive property mat
- `DarkModeSettings` (`Common/`): `[PersistentState]`-annotated class with `IsDarkMode` property. Registered scoped in `Startup.ConfigureDomainServices`. Single source of truth in the client. - `DarkModeSettings` (`Common/`): `[PersistentState]`-annotated class with `IsDarkMode` property. Registered scoped in `Startup.ConfigureDomainServices`. Single source of truth in the client.
- `DarkModeServiceBase`: Holds the cookie name constant (`"darkMode"`). - `DarkModeServiceBase`: Holds the cookie name constant (`"darkMode"`).
- `DarkModeCookieService`: Reads/writes the cookie via JS (`document.cookie` interop). Calls `DarkModeSettings.IsDarkMode = value` when the cookie changes or user toggles the button. - `DarkModeCookieService`: Reads/writes the cookie via JS (`document.cookie` interop). Calls `DarkModeSettings.IsDarkMode = value` when the cookie changes or user toggles the button.
- Server-side `DarkModeService` (in `DeepDrftWeb`, **not here**): Reads the cookie during prerender, seeds the `DarkModeSettings` instance, rounds it through `PersistentComponentState` to the client. - Server-side `DarkModeService` (in `DeepDrftPublic`, **not here**): Reads the cookie during prerender, seeds the `DarkModeSettings` instance, rounds it through `PersistentComponentState` to the client.
- `MainLayout.razor`: Wraps entire layout in `CascadingValue` of `DarkModeSettings`, so all children see the current dark-mode state. The dark-mode toggle button (hand-rolled lit/unlit gas-lamp icon from `DDIcons.cs`) calls `DarkModeCookieService.ToggleDarkModeAsync()`. - `MainLayout.razor`: Wraps entire layout in `CascadingValue` of `DarkModeSettings`, so all children see the current dark-mode state. The dark-mode toggle button (hand-rolled lit/unlit gas-lamp icon from `DDIcons.cs`) calls `DarkModeCookieService.ToggleDarkModeAsync()`.
The flow ensures the first paint uses the correct theme (no flash), and toggling the button persists the setting to a 365-day cookie. The flow ensures the first paint uses the correct theme (no flash), and toggling the button persists the setting to a 365-day cookie.
@@ -91,20 +91,20 @@ Component state lives in ViewModels (registered scoped in DI). Components render
## Theming convention ## Theming convention
- Bespoke `PaletteLight` / `PaletteDark` defined inline in `MainLayout.razor` (MudBlazor theme objects). - Bespoke `PaletteLight` / `PaletteDark` defined inline in `MainLayout.razor` (MudBlazor theme objects).
- CSS classes prefixed `deepdrft-` live in `DeepDrftWeb/wwwroot/styles/deepdrft-styles.css` (shared across server and client). - CSS classes prefixed `deepdrft-` live in `DeepDrftPublic/wwwroot/styles/deepdrft-styles.css` (shared across server and client).
- Custom SVG icons: `Common/DDIcons.cs` (hand-rolled gas-lamp, etc.). - Custom SVG icons: `Common/DDIcons.cs` (hand-rolled gas-lamp, etc.).
## Development commands ## Development commands
```bash ```bash
# The client runs as part of the DeepDrftWeb host: # The client runs as part of the DeepDrftPublic host:
dotnet run --project DeepDrftWeb dotnet run --project DeepDrftPublic
# Watch during development (rebuilds WASM as you change .cs/.razor/.ts files): # Watch during development (rebuilds WASM as you change .cs/.razor/.ts files):
dotnet watch run --project DeepDrftWeb dotnet watch run --project DeepDrftPublic
# Build just the client (for verification): # Build just the client (for verification):
dotnet build DeepDrftWeb.Client dotnet build DeepDrftPublic.Client
# Run client-specific tests (if any; currently none exist): # Run client-specific tests (if any; currently none exist):
dotnet test DeepDrftTests/ dotnet test DeepDrftTests/
@@ -113,7 +113,7 @@ dotnet test DeepDrftTests/
## Configuration ## Configuration
- `Program.cs`: Entry point. Calls `Startup.ConfigureApiHttpClient` (registers named clients), `ConfigureContentServices` (same), `ConfigureDomainServices` (registers services like `TracksViewModel`, `DarkModeSettings`, `AudioPlayerService`). - `Program.cs`: Entry point. Calls `Startup.ConfigureApiHttpClient` (registers named clients), `ConfigureContentServices` (same), `ConfigureDomainServices` (registers services like `TracksViewModel`, `DarkModeSettings`, `AudioPlayerService`).
- Both `Startup` methods are static and called from **both** the server `DeepDrftWeb/Program.cs` and the client `Program.cs`, ensuring prerender and runtime DI are identical. - Both `Startup` methods are static and called from **both** the server `DeepDrftPublic/Program.cs` and the client `Program.cs`, ensuring prerender and runtime DI are identical.
- No `appsettings.json` in the WASM assembly — config comes from the server `appsettings.json` via HTTP or is hardcoded. - No `appsettings.json` in the WASM assembly — config comes from the server `appsettings.json` via HTTP or is hardcoded.
## Important patterns ## Important patterns
@@ -5,7 +5,7 @@ using System.Text.Json;
using System.Web; using System.Web;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace DeepDrftWeb.Client.Clients; namespace DeepDrftPublic.Client.Clients;
public class TrackClient public class TrackClient
{ {
@@ -1,7 +1,7 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using NetBlocks.Models; using NetBlocks.Models;
namespace DeepDrftWeb.Client.Clients; namespace DeepDrftPublic.Client.Clients;
public class TrackMediaResponse : IDisposable public class TrackMediaResponse : IDisposable
{ {
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
namespace DeepDrftWeb.Client.Common; namespace DeepDrftPublic.Client.Common;
public class DarkModeSettings() public class DarkModeSettings()
{ {
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing; using Microsoft.AspNetCore.Components.Routing;
namespace DeepDrftWeb.Client.Controls; namespace DeepDrftPublic.Client.Controls;
public partial class AppNavLink : ComponentBase public partial class AppNavLink : ComponentBase
{ {
@@ -1,9 +1,9 @@
using DeepDrftWeb.Client.Services; using DeepDrftPublic.Client.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using MudBlazor; using MudBlazor;
using MudBlazor.Services; using MudBlazor.Services;
namespace DeepDrftWeb.Client.Controls.AudioPlayerBar; namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
public partial class AudioPlayerBar : ComponentBase, IAsyncDisposable public partial class AudioPlayerBar : ComponentBase, IAsyncDisposable
{ {
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using MudBlazor; using MudBlazor;
namespace DeepDrftWeb.Client.Controls.AudioPlayerBar; namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
public partial class PlayerControls : ComponentBase public partial class PlayerControls : ComponentBase
{ {
@@ -1,4 +1,4 @@
@namespace DeepDrftWeb.Client.Controls.AudioPlayerBar @namespace DeepDrftPublic.Client.Controls.AudioPlayerBar
<div class="spectrum-container @(IsVisible ? "" : "hidden")"> <div class="spectrum-container @(IsVisible ? "" : "hidden")">
<div class="spectrum-bars"> <div class="spectrum-bars">
@@ -1,7 +1,7 @@
using DeepDrftWeb.Client.Services; using DeepDrftPublic.Client.Services;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
namespace DeepDrftWeb.Client.Controls.AudioPlayerBar; namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
public partial class SpectrumVisualizer : ComponentBase, IAsyncDisposable public partial class SpectrumVisualizer : ComponentBase, IAsyncDisposable
{ {
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
namespace DeepDrftWeb.Client.Controls.AudioPlayerBar; namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
public partial class TimestampLabel : ComponentBase public partial class TimestampLabel : ComponentBase
{ {
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using MudBlazor; using MudBlazor;
namespace DeepDrftWeb.Client.Controls.AudioPlayerBar; namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
public partial class VolumeControls : ComponentBase public partial class VolumeControls : ComponentBase
{ {
@@ -1,9 +1,9 @@
using DeepDrftWeb.Client.Services; using DeepDrftPublic.Client.Services;
using DeepDrftWeb.Client.Clients; using DeepDrftPublic.Client.Clients;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace DeepDrftWeb.Client.Controls; namespace DeepDrftPublic.Client.Controls;
public partial class AudioPlayerProvider : ComponentBase, IAsyncDisposable public partial class AudioPlayerProvider : ComponentBase, IAsyncDisposable
{ {
@@ -1,5 +1,5 @@
@using DeepDrftWeb.Client.Common @using DeepDrftPublic.Client.Common
@using DeepDrftWeb.Client.Services @using DeepDrftPublic.Client.Services
@implements IAsyncDisposable @implements IAsyncDisposable
<nav class="@NavClass"> <nav class="@NavClass">
@@ -1,7 +1,7 @@
@using DeepDrftWeb.Client.Controls @using DeepDrftPublic.Client.Controls
@using DeepDrftWeb.Client.Controls.AudioPlayerBar @using DeepDrftPublic.Client.Controls.AudioPlayerBar
@using DeepDrftWeb.Client.Services @using DeepDrftPublic.Client.Services
@using DeepDrftWeb.Client.Common @using DeepDrftPublic.Client.Common
@using DeepDrftShared.Client.Common @using DeepDrftShared.Client.Common
@using Microsoft.AspNetCore.Components @using Microsoft.AspNetCore.Components
@inherits LayoutComponentBase @inherits LayoutComponentBase
@@ -0,0 +1,5 @@
@using DeepDrftPublic.Client.Controls
@@ -1,6 +1,6 @@
using MudBlazor; using MudBlazor;
namespace DeepDrftWeb.Client.Layout; namespace DeepDrftPublic.Client.Layout;
public class PageRoute public class PageRoute
{ {
@@ -1,6 +1,6 @@
@page "/" @page "/"
@rendermode InteractiveAuto @rendermode InteractiveAuto
@using DeepDrftWeb.Client.Services @using DeepDrftPublic.Client.Services
<PageTitle>Deep DRFT - Electronic Music Collective</PageTitle> <PageTitle>Deep DRFT - Electronic Music Collective</PageTitle>
@@ -1,10 +1,10 @@
using DeepDrftModels.Entities; using DeepDrftModels.Entities;
using DeepDrftWeb.Client.Services; using DeepDrftPublic.Client.Services;
using DeepDrftWeb.Client.ViewModels; using DeepDrftPublic.Client.ViewModels;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Models.Common; using Models.Common;
namespace DeepDrftWeb.Client.Pages; namespace DeepDrftPublic.Client.Pages;
public partial class TracksView : ComponentBase public partial class TracksView : ComponentBase
{ {
@@ -1,4 +1,4 @@
using DeepDrftWeb.Client; using DeepDrftPublic.Client;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MudBlazor.Services; using MudBlazor.Services;
@@ -1,6 +1,6 @@
using Microsoft.JSInterop; using Microsoft.JSInterop;
namespace DeepDrftWeb.Client.Services; namespace DeepDrftPublic.Client.Services;
public class AudioInteropService : IAsyncDisposable public class AudioInteropService : IAsyncDisposable
{ {
@@ -1,10 +1,10 @@
using DeepDrftModels.Entities; using DeepDrftModels.Entities;
using DeepDrftWeb.Client.Clients; using DeepDrftPublic.Client.Clients;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using NetBlocks.Models; using NetBlocks.Models;
using System.Buffers; using System.Buffers;
namespace DeepDrftWeb.Client.Services; namespace DeepDrftPublic.Client.Services;
public abstract class AudioPlayerService : IPlayerService, IAsyncDisposable public abstract class AudioPlayerService : IPlayerService, IAsyncDisposable
{ {
@@ -1,7 +1,7 @@
using DeepDrftWeb.Client.Common; using DeepDrftPublic.Client.Common;
using Microsoft.JSInterop; using Microsoft.JSInterop;
namespace DeepDrftWeb.Client.Services; namespace DeepDrftPublic.Client.Services;
public class DarkModeCookieService(DarkModeSettings darkModeSetting, IJSRuntime js) : DarkModeServiceBase public class DarkModeCookieService(DarkModeSettings darkModeSetting, IJSRuntime js) : DarkModeServiceBase
{ {
@@ -1,4 +1,4 @@
namespace DeepDrftWeb.Client.Services; namespace DeepDrftPublic.Client.Services;
public abstract class DarkModeServiceBase public abstract class DarkModeServiceBase
{ {
@@ -2,7 +2,7 @@ using DeepDrftModels.Entities;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using NetBlocks.Models; using NetBlocks.Models;
namespace DeepDrftWeb.Client.Services; namespace DeepDrftPublic.Client.Services;
public interface IPlayerService public interface IPlayerService
{ {
@@ -1,9 +1,9 @@
using DeepDrftModels.Entities; using DeepDrftModels.Entities;
using DeepDrftWeb.Client.Clients; using DeepDrftPublic.Client.Clients;
using System.Buffers; using System.Buffers;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace DeepDrftWeb.Client.Services; namespace DeepDrftPublic.Client.Services;
public class StreamingAudioPlayerService : AudioPlayerService, IStreamingPlayerService public class StreamingAudioPlayerService : AudioPlayerService, IStreamingPlayerService
{ {
@@ -1,6 +1,6 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace DeepDrftWeb.Client.Services; namespace DeepDrftPublic.Client.Services;
public static class StreamingErrorHandler public static class StreamingErrorHandler
{ {
@@ -1,10 +1,10 @@
using DeepDrftWeb.Client.Clients; using DeepDrftPublic.Client.Clients;
using DeepDrftWeb.Client.Common; using DeepDrftPublic.Client.Common;
using DeepDrftWeb.Client.Services; using DeepDrftPublic.Client.Services;
using DeepDrftWeb.Client.ViewModels; using DeepDrftPublic.Client.ViewModels;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace DeepDrftWeb.Client; namespace DeepDrftPublic.Client;
public static class Startup public static class Startup
{ {
@@ -1,8 +1,8 @@
using DeepDrftModels.Entities; using DeepDrftModels.Entities;
using DeepDrftWeb.Client.Clients; using DeepDrftPublic.Client.Clients;
using Models.Common; using Models.Common;
namespace DeepDrftWeb.Client.ViewModels; namespace DeepDrftPublic.Client.ViewModels;
public class TracksViewModel public class TracksViewModel
{ {
@@ -9,7 +9,7 @@
@using MudBlazor @using MudBlazor
@using MudBlazor.Services @using MudBlazor.Services
@using MudBlazor.ThemeManager @using MudBlazor.ThemeManager
@using DeepDrftWeb.Client.Common @using DeepDrftPublic.Client.Common
@using DeepDrftShared.Client.Common @using DeepDrftShared.Client.Common
@using DeepDrftShared.Client.Components @using DeepDrftShared.Client.Components
@layout DeepDrftWeb.Client.Layout.MainLayout @layout DeepDrftPublic.Client.Layout.MainLayout

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

@@ -1,12 +1,12 @@
# CLAUDE.md - DeepDrftWeb # CLAUDE.md - DeepDrftPublic
Guidance for working in the DeepDrftWeb project (the Blazor Web App host). 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. See the root `CLAUDE.md` for full architecture overview. This file covers what is specific to this project.
## One-line purpose ## 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 `DeepDrftWeb.Services`.** 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) ## What lives here now (only)
@@ -20,7 +20,7 @@ The Blazor Web App host. Owns HTTP surface (one controller + render-mode wiring)
## What does NOT live here anymore ## 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. - `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`. - Any FileDatabase code — that lives in `DeepDrftContent.Services`.
## Blazor Web App render modes ## Blazor Web App render modes
@@ -28,14 +28,14 @@ The Blazor Web App host. Owns HTTP surface (one controller + render-mode wiring)
Hybrid Blazor with `AddInteractiveServerComponents()` + `AddInteractiveWebAssemblyComponents()`. Hybrid Blazor with `AddInteractiveServerComponents()` + `AddInteractiveWebAssemblyComponents()`.
- Root component is `<Routes @rendermode="InteractiveAuto" />` from `Components/App.razor`. - Root component is `<Routes @rendermode="InteractiveAuto" />` from `Components/App.razor`.
- WASM render-mode loads `DeepDrftWeb.Client._Imports` as an additional assembly. - WASM render-mode loads `DeepDrftPublic.Client._Imports` as an additional assembly.
- **New routable pages go in `DeepDrftWeb.Client/Pages`, not here** — the client project owns the interactive UI. - **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. 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 ## 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`. `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). The flow ensures the first paint uses the correct theme (no flash).
@@ -49,11 +49,11 @@ Audio interop is TypeScript, not raw JS:
- `tsconfig.json` configured for ES module interop and must **not** be copied to output. - `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. - 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. 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 ## HTTP client wiring
Mostly in `DeepDrftWeb.Client.Startup`: Mostly in `DeepDrftPublic.Client.Startup`:
- Named clients `"DeepDrft.API"` (SQL metadata) and `"DeepDrft.Content"` (binary audio). - Named clients `"DeepDrft.API"` (SQL metadata) and `"DeepDrft.Content"` (binary audio).
- Base addresses passed in from `appsettings.json` (`ApiUrls:ContentApi`, `ApiUrls:SqlApi`). - Base addresses passed in from `appsettings.json` (`ApiUrls:ContentApi`, `ApiUrls:SqlApi`).
@@ -73,7 +73,7 @@ Server-side `Program.cs` adds:
## The one controller ## The one controller
`TrackController` is thin — it just deserializes query parameters, calls `DeepDrftWeb.Services.TrackService.GetPaged`, and wraps the result: `TrackController` is thin — it just deserializes query parameters, calls `DeepDrftData.TrackService.GetPaged`, and wraps the result:
```csharp ```csharp
[HttpGet("api/track/page")] [HttpGet("api/track/page")]
@@ -84,22 +84,22 @@ public async Task<ActionResult<ApiResultDto<PagedResult<TrackEntity>>>> GetPage(
[FromQuery] bool sortDescending = false) [FromQuery] bool sortDescending = false)
``` ```
If you're adding new SQL endpoints, this is the file. If you're adding new logic, that goes in `DeepDrftWeb.Services/TrackService.cs`. 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 ## Development commands
```bash ```bash
# Run the web host (includes WASM from DeepDrftWeb.Client) # Run the web host (includes WASM from DeepDrftPublic.Client)
dotnet run --project DeepDrftWeb dotnet run --project DeepDrftPublic
# Watch during development # Watch during development
dotnet watch run --project DeepDrftWeb dotnet watch run --project DeepDrftPublic
# Build # Build
dotnet build DeepDrftWeb dotnet build DeepDrftPublic
# Add migration (run from solution root; creates in DeepDrftWeb.Services) # Add migration (run from solution root; creates in DeepDrftData)
dotnet ef migrations add MigrationName --project DeepDrftWeb.Services --startup-project DeepDrftWeb dotnet ef migrations add MigrationName --project DeepDrftData --startup-project DeepDrftPublic
``` ```
## Configuration ## Configuration
@@ -113,6 +113,6 @@ dotnet ef migrations add MigrationName --project DeepDrftWeb.Services --startup-
## Important patterns ## 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 `DeepDrftWeb.Services` for the contract. 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 `DeepDrftWeb.Services`. When working with this project, focus on the host surface (controllers, middleware, config) and prerender coordination. New domain logic goes in `DeepDrftData`.
@@ -1,4 +1,4 @@
@using DeepDrftWeb.Services @using DeepDrftPublic.Services
@using DeepDrftShared.Client.Components @using DeepDrftShared.Client.Components
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@@ -10,7 +10,7 @@
<DeepDrftFontLinks /> <DeepDrftFontLinks />
<link href="_@Assets["content/MudBlazor.ThemeManager/MudBlazorThemeManager.css"]" rel="stylesheet" /> <link href="_@Assets["content/MudBlazor.ThemeManager/MudBlazorThemeManager.css"]" rel="stylesheet" />
<link href=@Assets["_content/MudBlazor/MudBlazor.min.css"] rel="stylesheet" /> <link href=@Assets["_content/MudBlazor/MudBlazor.min.css"] rel="stylesheet" />
<link rel="stylesheet" href="@Assets["DeepDrftWeb.styles.css"]"/> <link rel="stylesheet" href="@Assets["DeepDrftPublic.styles.css"]"/>
<link rel="stylesheet" href="@Assets["_content/DeepDrftShared.Client/styles/deepdrft-tokens.css"]" /> <link rel="stylesheet" href="@Assets["_content/DeepDrftShared.Client/styles/deepdrft-tokens.css"]" />
<link rel="stylesheet" href="styles/deepdrft-styles.css" /> <link rel="stylesheet" href="styles/deepdrft-styles.css" />
<ImportMap /> <ImportMap />
@@ -1,7 +1,7 @@
<Router AppAssembly="typeof(App).Assembly" <Router AppAssembly="typeof(App).Assembly"
AdditionalAssemblies="new[] { typeof(DeepDrftWeb.Client._Imports).Assembly }"> AdditionalAssemblies="new[] { typeof(DeepDrftPublic.Client._Imports).Assembly }">
<Found Context="routeData"> <Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(DeepDrftWeb.Client.Layout.MainLayout)" /> <RouteView RouteData="routeData" DefaultLayout="typeof(DeepDrftPublic.Client.Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" /> <FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found> </Found>
<NotFound> <NotFound>
@@ -8,6 +8,6 @@
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using MudBlazor @using MudBlazor
@using MudBlazor.Services @using MudBlazor.Services
@using DeepDrftWeb @using DeepDrftPublic
@using DeepDrftWeb.Client @using DeepDrftPublic.Client
@using DeepDrftWeb.Components @using DeepDrftPublic.Components
@@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Mvc;
using Models.Common; using Models.Common;
using NetBlocks.Models; using NetBlocks.Models;
namespace DeepDrftWeb.Controllers; namespace DeepDrftPublic.Controllers;
[ApiController] [ApiController]
[Route("api/[controller]")] [Route("api/[controller]")]
@@ -21,7 +21,7 @@
<!-- Npgsql 10.0.1 requires Microsoft.EntityFrameworkCore >= 10.0.4; keep in sync --> <!-- Npgsql 10.0.1 requires Microsoft.EntityFrameworkCore >= 10.0.4; keep in sync -->
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.1" />
<ProjectReference Include="..\DeepDrftModels\DeepDrftModels.csproj" /> <ProjectReference Include="..\DeepDrftModels\DeepDrftModels.csproj" />
<ProjectReference Include="..\DeepDrftWeb.Client\DeepDrftWeb.Client.csproj" /> <ProjectReference Include="..\DeepDrftPublic.Client\DeepDrftPublic.Client.csproj" />
<ProjectReference Include="..\DeepDrftData\DeepDrftData.csproj" /> <ProjectReference Include="..\DeepDrftData\DeepDrftData.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="10.0.7" />
</ItemGroup> </ItemGroup>
@@ -1,6 +1,6 @@
using DeepDrftWeb; using DeepDrftPublic;
using MudBlazor.Services; using MudBlazor.Services;
using DeepDrftWeb.Components; using DeepDrftPublic.Components;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using NetBlocks.Utilities.Environment; using NetBlocks.Utilities.Environment;
@@ -10,7 +10,7 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddMudServices(); builder.Services.AddMudServices();
// Required credential files — must exist before the app will start. // Required credential files — must exist before the app will start.
// In dev: create the files under DeepDrftWeb/environment/ (gitignored). // In dev: create the files under DeepDrftPublic/environment/ (gitignored).
// In prod: systemd CREDENTIALS_DIRECTORY points to encrypted credential blobs. // In prod: systemd CREDENTIALS_DIRECTORY points to encrypted credential blobs.
// - environment/connections.json: { "ConnectionStrings": { "DefaultConnection": "..." } } // - environment/connections.json: { "ConnectionStrings": { "DefaultConnection": "..." } }
// AuthBlocks and the DeepDrftContent API key now live on DeepDrftManager; // AuthBlocks and the DeepDrftContent API key now live on DeepDrftManager;
@@ -20,9 +20,9 @@ builder.Configuration.AddJsonFile(connectionsPath, optional: false, reloadOnChan
var contentApiUrl = builder.Configuration["ApiUrls:ContentApi"] ?? throw new Exception("Content API URL is not configured"); var contentApiUrl = builder.Configuration["ApiUrls:ContentApi"] ?? throw new Exception("Content API URL is not configured");
DeepDrftWeb.Client.Startup.ConfigureApiHttpClient(builder.Services, builder.GetKestrelUrl()); DeepDrftPublic.Client.Startup.ConfigureApiHttpClient(builder.Services, builder.GetKestrelUrl());
DeepDrftWeb.Client.Startup.ConfigureDomainServices(builder.Services); DeepDrftPublic.Client.Startup.ConfigureDomainServices(builder.Services);
DeepDrftWeb.Client.Startup.ConfigureContentServices(builder.Services, contentApiUrl); DeepDrftPublic.Client.Startup.ConfigureContentServices(builder.Services, contentApiUrl);
Startup.ConfigureDomainServices(builder); Startup.ConfigureDomainServices(builder);
@@ -114,7 +114,7 @@ app.MapControllers();
app.MapRazorComponents<App>() app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode() .AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode() .AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(DeepDrftWeb.Client._Imports).Assembly); .AddAdditionalAssemblies(typeof(DeepDrftPublic.Client._Imports).Assembly);
app.Run(); app.Run();
@@ -1,7 +1,7 @@
using DeepDrftWeb.Client.Common; using DeepDrftPublic.Client.Common;
using DeepDrftWeb.Client.Services; using DeepDrftPublic.Client.Services;
namespace DeepDrftWeb.Services; namespace DeepDrftPublic.Services;
public class DarkModeService(DarkModeSettings darkModeSettings, IHttpContextAccessor httpAccessor) : DarkModeServiceBase public class DarkModeService(DarkModeSettings darkModeSettings, IHttpContextAccessor httpAccessor) : DarkModeServiceBase
{ {
@@ -1,10 +1,10 @@
using DeepDrftData; using DeepDrftData;
using DeepDrftData.Data; using DeepDrftData.Data;
using DeepDrftData.Repositories; using DeepDrftData.Repositories;
using DeepDrftWeb.Services; // DarkModeService namespace (within this host project) using DeepDrftPublic.Services; // DarkModeService namespace (within this host project)
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace DeepDrftWeb; namespace DeepDrftPublic;
public static class Startup public static class Startup
{ {
@@ -15,7 +15,7 @@ public static class Startup
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
// Add Server Prerendering Theming Support // Add Server Prerendering Theming Support
// DarkModeSettings is registered in DeepDrftWeb.Client.Startup.ConfigureDomainServices // DarkModeSettings is registered in DeepDrftPublic.Client.Startup.ConfigureDomainServices
builder.Services builder.Services
.AddHttpContextAccessor() .AddHttpContextAccessor()
.AddScoped<DarkModeService>(); .AddScoped<DarkModeService>();

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

@@ -1,7 +1,7 @@
/* DeepDrft design tokens shared palette layer. /* DeepDrft design tokens shared palette layer.
Consumed by both DeepDrftWeb (public site, light + dark) and the CMS host Consumed by both DeepDrftPublic (public site, light + dark) and the CMS host
(light only). Page-specific styling lives in the consuming host's own (light only). Page-specific styling lives in the consuming host's own
stylesheet (e.g. DeepDrftWeb/wwwroot/styles/deepdrft-styles.css). */ stylesheet (e.g. DeepDrftPublic/wwwroot/styles/deepdrft-styles.css). */
/* Light theme - wireframe palette (navy / green / warm off-white) */ /* Light theme - wireframe palette (navy / green / warm off-white) */
:root { :root {
-5
View File
@@ -1,5 +0,0 @@
@using DeepDrftWeb.Client.Controls
+2 -2
View File
@@ -3,8 +3,8 @@ eval $(ssh-agent -s)
ssh-add /c/.ssh/deepdrft_dch6_ed25519 ssh-add /c/.ssh/deepdrft_dch6_ed25519
CONTENT_PROJ="DeepDrftContent" CONTENT_PROJ="DeepDrftContent"
WEB_PROJ="DeepDrftWeb" WEB_PROJ="DeepDrftPublic"
WEB_SERVICES_PROJ="DeepDrftWeb.Services" WEB_SERVICES_PROJ="DeepDrftData"
CONTENT_APP="deepdrft-content.tar.gz" CONTENT_APP="deepdrft-content.tar.gz"
WEB_APP="deepdrft-web.tar.gz" WEB_APP="deepdrft-web.tar.gz"