# Architecture decisions Why the site is built the way it is. Read this before questioning one of these decisions — each records the reasoning, not just the choice. Operational how-to lives in `docs/deployment.md`; open work lives in `tasks/`. > **Note on scope.** These decisions describe stage 1: a static information site > with content as files. The move to editor-based content maintenance > (`tasks/001-redaktion-ohne-entwickler.md`) deliberately revisits AE-2 and AE-3 — > when that lands, update this file. ## AE-1: Blazor with static server-side rendering, not WebAssembly **Decision:** Blazor Web App with interactivity mode *None* (pure static SSR). Target framework .NET 10 (LTS). **Rationale:** Blazor WASM loads several MB of runtime before the first visible letter, serves search engines and link previews (WhatsApp, Signal, Messenger — the main distribution channel among parents) an empty shell, and provides no value on a pure information site. Static SSR delivers finished HTML, needs no JavaScript, and costs around 60 MB of RAM in the container. **Consequence:** Interactivity can be added later per component (`@rendermode InteractiveServer` on exactly that one component), without changing the architecture. Never global. ## AE-2: Content as files in the repo, not in a database **Decision:** Page content as Markdown with YAML frontmatter, events as structured YAML (`Content/events.yml`), documents as PDF under `wwwroot`. **Rationale:** No DB backup, no migration schema, no consistency problems between files and database. Changes are commits and are therefore traceable and reversible. For a site with ~10 subpages and a few events per year, anything else is overhead. **Consequence:** Text changes require a commit and a redeploy. With an expected five changes a year that is acceptable — and the reason the editor expansion (`tasks/001`) is treated as a separate stage. ## AE-3: Content is baked into the image, not mounted as a volume **Decision:** `Content/` and `wwwroot/` are part of the image. **Rationale:** Mounted content from the appdata share could be edited directly on the NAS, but that is exactly when the repo and the live state drift apart — and the "backup = `git clone`" property from AE-2 would be worthless. **Consequence:** No quick fix on the live system. Typos are corrected properly via a commit. Note: the content is read once at startup and cached — there is **no** `FileSystemWatcher` (a change needs a restart / `dotnet watch`). ## AE-4: TLS and certificates exclusively in the Nginx Proxy Manager **Decision:** The container speaks only HTTP on port 8080 and has **no** port mapping to the outside. NPM terminates TLS and is the only path to the container. **Rationale:** Matches the pattern already established in the home lab (`cloud.anticarnist.de`). Certificate management stays in one place. **Consequence (important):** In `Program.cs`, **no** `UseHttpsRedirection()` and **no** `UseHsts()` — otherwise a redirect loop behind the proxy. NPM sets HSTS. `UseForwardedHeaders` with emptied `KnownNetworks`/`KnownProxies` is correct because the container has no port mapping and is reachable only through NPM. ## Rejected alternatives (for AE-1) | Alternative | Why not | |---|---| | Blazor WASM | Payload, SEO, link previews, no benefit | | ASP.NET Core MVC/Razor Pages | Works too, but Razor Components are the more modern model | | Statiq.Web (C# SSG) → nginx | Leanest to operate, but every text change forces a build. Kept as a fallback. | | Astro/Hugo | More mature SSG ecosystem, but unfamiliar territory |