Files
Elternbeirat/docs/architektur.md
T

73 lines
3.5 KiB
Markdown

# 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 |