Files
Elternbeirat/docs/architektur.md
T

3.5 KiB

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