Felder und Widgets
Jedes Feld hat name und type.
Dazu kommen optional validator (Server-Regeln) und meta (Admin-Darstellung).
Beispiele unten stammen aus content.yml, navigation.yml, medialib.yml und tag.yml.
Feldaufbau
Abschnitt betitelt „Feldaufbau“# aus content.yml — Pflichtfeld mit Pattern plus Hilfetext- name: path type: string validator: pattern: ^\/[a-z0-9\-\/]*$ required: true meta: label: { de: "Pfad", en: "Path" } helperText: de: "URL-Pfad für diese Seite, z.B. '/ueber-uns'." en: "URL path for this page, e.g. '/about-us'."namepasst auf^[0-9A-Za-z_-]+$— keine Punkte, keine Leerzeichen.objectundobject[]tragen ihre Unterfelder insubFields.- Listen hängst du per
[]an:string[],object[],file[]. meta.hide: trueversteckt Technikfelder (_pagebuilderThumbnail,_testdata).
Typ-Tabelle
Abschnitt betitelt „Typ-Tabelle“Das Schema kennt elf Typen. Das Widget wählst du in meta.widget.
| Server-Typ | Bedeutung | Widget im Starter |
|---|---|---|
string |
Text, eine Zeile | Standard; select, richtext, textarea, foreignKey, foreignMedia, color-nah via select |
string[] |
Textliste | foreignKey mit foreign: { collection: tag } (medialib.yml: tags) |
number |
Zahl | number |
number[] |
Zahlenliste | number |
boolean |
Ja/Nein | Standard-Checkbox/switch; reine Flags ohne Widget (comment.yml: active) |
object |
Gruppe | containerLessObject (kein Kasten), Standard mit Kasten |
object[] |
Liste von Gruppen | containerLessObjectArray, pagebuilder (content.yml: blocks) |
file |
Upload | file (medialib.yml), image |
file[] |
Mehrere Uploads | file |
date |
Datum/Zeit | date, datetime (content.yml: publication.from) |
any |
Alles erlaubt | json |
Alle prüfbaren Widgets aus dem Schema (field-meta.schema.json, widget-Enum, 25 Werte):
| Widget | Wofür |
|---|---|
text |
Einzeiliger Text (Standard) |
textarea |
Mehrzeiliger Text |
number |
Zahleneingabe |
checkbox, switch |
Ja/Nein-Umschalter |
select |
Dropdown aus meta.choices |
selectArray, chipArray |
Mehrfach-Auswahl als Liste bzw. Chips |
date, datetime |
Datum bzw. Datum mit Uhrzeit |
file |
Datei-Upload (auch file[]) |
image |
Bild-Upload mit Vorschau |
json |
Freies JSON (any-Felder) |
richtext, html |
Formatierter Text bzw. HTML-Quelltext |
foreignKey, foreignKeyChipArray |
Verweis auf andere Sammlung (einfach / mehrfach) |
foreignFile |
Datei-Verweis auf andere Sammlung |
foreignMedia |
Bild-Verweis auf die Mediathek |
pagebuilder |
Block-Editor für object[] |
templateProps |
Vorlagen-Parameter |
containerLessObject, containerLessObjectArray |
Gruppe(n) ohne umgebenden Kasten |
color |
Farbauswahl |
Validatoren
Abschnitt betitelt „Validatoren“Der Server prüft validator bei POST und PUT.
Leere Strings bestehen required nicht — außer mit allowZero: true.
| Schlüssel | Wirkung | Beispiel aus dem Starter |
|---|---|---|
required: true |
Feld muss gefüllt sein | content.yml: name, path; navigation.yml: language, type |
pattern |
Regulärer Ausdruck | path: ^\/[a-z0-9\-\/]*$; hash: ^[a-zA-Z0-9_-]+$ |
in |
Nur diese Werte | navigation.yml: language in ["de", "en"], type in ["header", "footer"] |
minLength / maxLength |
Zeichenlänge | elements.name: maxLength: 100; alt.de: maxLength: 500 |
min / max |
Zahlenbereich | — |
minDate / maxDate |
Datumsbereich | — |
minItems / maxItems |
Listenlänge | — |
format |
email, url, uuid oder slug |
— |
maxFileSize / minFileSize |
Dateigröße ("50MB") |
medialib.yml: file mit required: true, maxFileSize: "50MB" |
accept |
Erlaubte MIME-Typen | — |
eval |
Eigene JavaScript-Regel | — |
allowZero |
Leere Werte trotz required erlauben |
— |
Choices und Fremdschlüssel
Abschnitt betitelt „Choices und Fremdschlüssel“Feste Auswahl
Abschnitt betitelt „Feste Auswahl“meta.choices listet id plus name (de/en).
Mit widget: select wird daraus ein Dropdown.
# aus navigation.yml- name: language type: string validator: in: ["de", "en"] required: true meta: label: { de: "Sprache", en: "Language" } widget: select choices: - id: de name: { de: "Deutsch", en: "German" } - id: en name: { de: "Englisch", en: "English" }Leerer id: "" heißt „Standard/keine Auswahl” (containerWidth, padding in content.yml).
Fremdschlüssel
Abschnitt betitelt „Fremdschlüssel“meta.foreign verweist auf eine andere Sammlung.
Der Admin zeigt dann einen Auswahl-Dialog statt einem Textfeld.
# aus navigation.yml — Seite verweist auf content- name: page type: string meta: label: { de: "Seite", en: "Page" } widget: foreignKey foreign: collection: content id: id| Widget | Wofür | Beispiel |
|---|---|---|
foreignKey |
Ein Verweis (ID als String) | navigation.elements.page → content; comment.contentId → content; medialib.tags → tag |
foreignMedia |
Bild aus der Mediathek | content.yml: blocks.heroImage.image, blocks.image → medialib |
foreignFile / foreignKeyChipArray |
Datei-Verweis / Mehrfach-Verweis | laut Schema verfügbar |
Auflösen musst du den Verweis beim Lesen per lookup — siehe Lesen und suchen.
dependsOn: Felder ein- und ausblenden
Abschnitt betitelt „dependsOn: Felder ein- und ausblenden“meta.dependsOn.eval ist JavaScript.
$parent ist das umgebende Objekt — so zeigt der Pagebuilder nur passende Felder.
# aus content.yml — Unterzeile nur beim Hero-Block- name: subline type: string meta: label: { de: "Unterzeile", en: "Subline" } dependsOn: eval: $parent.type == 'hero'Weitere Muster aus content.yml zum Kopieren:
- Mehrere Typen:
$parent.type == 'features' || $parent.type == 'richtext' || $parent.type == 'accordion' || $parent.type == 'contact-form' - Negation:
$parent.type != ''(Block-Ausschalterhide)
i18n-Felder
Abschnitt betitelt „i18n-Felder“Zwei Muster kommen im Starter vor:
# aus medialib.yml — Alt-Text je Sprache- name: alt type: object meta: label: { de: "Alt-Text", en: "Alt Text" } subFields: - name: de type: string validator: maxLength: 500 - name: en type: string validator: maxLength: 500# aus content.yml (meta) — Übersetzungen gehören zusammenmeta: i18n: entry: languageField: lang groupField: translationKeyJede Sprache bekommt einen eigenen Eintrag mit gleichem translationKey.
path + lang und translationKey + lang sind je einmalig (Unique-Index).
lang selbst ist ein freier String — das Schema erzwingt kein in: [de, en].
Weitere Meta-Optionen
Abschnitt betitelt „Weitere Meta-Optionen“Je Option eine Zeile (Quelle: tibi-types/schemas/config/field-meta.schema.json):
| Option | Wirkung | Typ / Beispiel |
|---|---|---|
hideLabel |
Blendet das Feld-Label im Formular aus | boolean; hideLabel: true |
imageEditor |
Bildbearbeitung im Uploader | boolean oder { crop, rotate, flip, focalPoint, adjust, palette }; imageEditor: { crop: true, rotate: true } |
containerProps |
Feld-Wrapper (class, layout mit breakBefore, breakAfter, size mit default/small/large) |
Objekt; containerProps: { layout: { breakBefore: true } } |
inputProps |
Wird ans Eingabeelement durchgereicht (widget-spezifisch) | Objekt (additionalProperties: true) |
schemaRef |
Schema des Felds aus einem anderen Feld übernehmen | { field } + optional ref; schemaRef: { field: blocks } |
protected |
Schreibschutz vor fremdem Überschreiben (Bool oder UI-Bedingung) | boolOrUiCondition; protected: true |
drillDown |
false rendert den Pagebuilder inline statt im Overlay |
boolean; drillDown: false (siehe Pagebuilder-Anbindung) |
pageSize |
Seitengröße für paginierte Feldlisten | integer ≥ 0; pageSize: 20 |
Verifiziert am e3f92eb 2026-10-17 (tibi-svelte-starter), am 4c55f82 2026-10-17 (tibi-types), am 68b4278 2026-10-17 (tibi-server, validator.go); Meta-Ergänzungen verifiziert am 4c55f82 2026-10-17 (tibi-types: field-meta.schema.json)