Sections built from typed blocks¶
Context and Problem Statement¶
A website version had eight fixed sections (Unsere Geschichte, Tagesablauf, Anreise, Empfehlungen, Geschenkideen, Hochzeitsgesellschaft, Galerie, Häufige Fragen), each with its own item fields and its own layout. Couples could not add a section, put a few words above the wedding party or place the brunch in a section of its own: only "Unsere Geschichte" held text. A fully free page builder would fix that but break theming, because the site looks designed only while every piece of content has a known, designed layout. The schedule also lived in two places: events belonged to the wedding, but each version kept a list of hidden events, and events had a manual order.
Considered Options¶
- Keep the fixed sections and add a free text field to each
- A free-form page builder (columns, free positioning, per-block styling)
- Sections as a title plus an ordered list of typed blocks from a small, fixed set
Decision Outcome¶
Chosen option: "Sections as a title plus an ordered list of typed blocks".
- There are seven block types, each with fixed fields and its own designed layout: Text, Termin (event), Person (with an optional text), Ort (with Art: hotel, parking, arrival, activity, other), Link, Frage & Antwort and Bild. Consecutive blocks of one type render as one group (one card grid, one gallery, one event list). Themes keep styling block types, never arbitrary combinations.
website_sectionsrows have an id, a position, a required title, visibility and the block type a template section suggests while empty.section_blockshang off a section (cascade) with a position and ajsonbdatacolumn validated by a zod discriminated union ontype(src/domain/sections.ts).- Today's eight sections are the standard template: a new wedding's first website and "Aus Vorlage erstellen" (a new website version) start from it, with the translated titles written in. "+ Abschnitt" adds an empty section or one template section. Template sections start empty, except Tagesablauf, which shows all events.
- Events stay the wedding's (
wedding_events) and get their own area, the Ablauf. An event block references events and never copies them:eventId: nullshows the whole Ablauf (including events added later), an id shows one event. Deleting an event deletes the single-event blocks that point to it, in every version.websites.hidden_event_idsandwedding_events.positionare gone: a version shows an event exactly where an event block puts it, and events are always listed chronologically (date, then start time). - Section anchors and editor routes use the section id (
#s-<id>,/hochzeiten/<id>/website/<websiteId>/<sectionId>), so two sections may share a title.
Consequences¶
- Good, because every field of the old items has a home in a block, and the couple can arrange sections and blocks freely without leaving the designed layouts.
- Good, because an event's time and place exist exactly once; the invitations, the response form and every website version read the same row.
- Good, because the account export writes sections with their blocks in order.
- Bad, because a version that should leave some events out has to use single-event blocks instead of "Alle Termine".
- Neutral: no data migration; the migration drops the old fixed sections (no instance holds real data yet).