4.2 KiB
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:
---
title: Vorstandsteam
---
# Vorstandsteam
Hier stellt sich das Team vor …
- Slugs have no umlauts. Use
ueber-uns, notüber-uns;foerderverein, notfö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/<slug>.
---
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:
- 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
startdrops 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 itsstartvalue.
Publishing a change
A content change is not live until the image is rebuilt and redeployed:
- Edit or add the file under
Content/. - 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 usedotnet watchto restart on save automatically). - Commit the change.
- Rebuild and redeploy the image — see deployment.