# Editing content How to add or change the visitor-facing content of the site. All content lives as files under `Elternbeirat.Web/Content/` — there is no database and no admin interface. Every change needs a **commit** and a **rebuild** of the image, since the content ships inside the image, not in a volume. > **Language convention.** File and folder names, front-matter keys and YAML keys > are English (`posts/`, `title:`, `start:`). The text a visitor reads stays > German — that includes the *value* after a key (`title: Vorstandsteam`) and the > Markdown body. So you write English keys with German values. The three content kinds: | Kind | Where | New entry = | |---|---|---| | Page | `Content/pages/*.md` | one Markdown file | | Post (news) | `Content/posts/*.md` | one Markdown file | | Event (calendar) | `Content/events.yml` | one entry in the list | None of these touch a `.razor` file. --- ## Pages A page is a standalone Markdown file in `Content/pages/`. The file name (without `.md`) is the slug and therefore the URL: `vorstandsteam.md` is served at `/vorstandsteam`. Front matter at the top sets the title; the body is the content: ```markdown --- title: Vorstandsteam --- # Vorstandsteam Hier stellt sich das Team vor … ``` - **Slugs have no umlauts.** Use `ueber-uns`, not `über-uns`; `foerderverein`, not `förderverein`. The visible heading in the body may of course use umlauts. - If you omit `title:`, the slug is used as the title — so always set it. - Add the new page to the navigation only if it should appear there: edit `Components/Layout/MainLayout.razor`. Pages that are only linked from other pages (like the FAQ sub-pages) do not need a nav entry. --- ## Posts (news) A post is a Markdown file in `Content/posts/`, same idea as a page but with a date. Posts show up in the news list at `/beitraege`, newest first, and each has its own URL at `/beitraege/`. ```markdown --- title: Neue Sporthalle feierlich eröffnet date: 2025-10-05 --- # Neue Sporthalle feierlich eröffnet Der Text des Beitrags … ``` - `date:` is an ISO date, **`yyyy-MM-dd`**. It drives the sort order (newest first) and the displayed date. A missing or malformed date sorts the post last rather than breaking the build. - The three most recent posts are also teased on the home page automatically — nothing to do there. --- ## Events (calendar) Events are **not** separate files. They all live in the single list `Content/events.yml`. Add an entry to the list: ```yaml - title: Elternbeiratssitzung start: "2026-10-08 19:30" location: Lehrerzimmer note: Themen bitte vorab per E-Mail einreichen. ``` Keys: | Key | Required | Meaning | |---|---|---| | `title` | yes | Short name shown in the list and calendar | | `start` | yes | When it starts — see date formats below | | `end` | no | End, for entries that span hours or days | | `location` | no | e.g. `Aula`, `Mensa` | | `note` | no | Free text shown below the entry | **Date formats** for `start` and `end`: - Date only → all-day event: `"2026-03-15"` - Date with time: `"2026-03-15 19:30"` (24-hour clock) Always keep the value in quotes so YAML treats it as text. The overview at `/termine` splits the list automatically: entries today or later appear under *Kommende Termine* (earliest first), past ones under *Vergangene Termine* (most recent first). You do not sort the file yourself — order in the YAML does not matter. Visitors can subscribe to `/termine.ics` in their own calendar app; that feed is generated from the same file, so a new entry appears there too. > A malformed `start` drops just that one entry instead of breaking the whole > page, so a typo in one event will not take the calendar down — but the entry > silently disappears. If an event does not show up, check its `start` value. --- ## Publishing a change A content change is not live until the image is rebuilt and redeployed: 1. Edit or add the file under `Content/`. 2. Check it locally with `dotnet run --project Elternbeirat.Web`. Content is read once at startup, so after editing a file **restart the process** to see the change (or use `dotnet watch` to restart on save automatically). 3. Commit the change. 4. Rebuild and redeploy the image — see [deployment](deployment.md).