Du brauchst eine neue Collection. In den meisten Systemen heißt das: Migration schreiben, Datenbank anfassen, deployen. In RustyCMS legst du eine JSON5-Datei in types/ ab. Der Watcher sieht sie, lädt sie, und ab dann gibt es die Collection — mit REST-Endpoints, Admin-Formular und Validierung. Änderst du ein Feld, gilt es sofort.
Eine Datei, eine Collection
// types/blog_post.json5
{
name: "blog_post",
strict: true,
fields: {
title: { type: "string", required: true, maxLength: 200 },
body: { type: "content", format: "markdown", required: true },
tags: { type: "array", items: { type: "string" } },
author: { type: "reference", collection: "person" },
published: { type: "boolean", default: false },
created_at: { type: "datetime", auto: true, readonly: true },
}
}
Feldtypen: string, number, integer, boolean, datetime, array, object, reference (auf Wunsch polymorph über mehrere Collections), referenceOrInline, multiSelect mit enum, image und file mit MIME-Whitelist. Texte bekommen type: "content" mit format markdown, richtext, html oder plain — das entscheidet über Editor und Rendering. HTML wird beim Speichern bereinigt: kein <script>, keine on*-Handler, außer du lockerst es ausdrücklich.
Felder, die nur erscheinen, wenn sie gebraucht werden
showIf blendet ein Feld im Admin-Formular ein, wenn ein Geschwisterfeld einen bestimmten Wert hat — das Datum nur bei type: "termin", der Teaser bei allem anderen. Die Redaktion sieht nur, was zum gewählten Typ gehört. API und Validierung bleiben unberührt, das Feld wird immer gespeichert.
date: { type: "datetime", showIf: { field: "type", eq: "termin" } },
Einmal definieren, überall verwenden
Ein Schema mit reusable: true ist ein Partial: Layout-Optionen, SEO-Felder, ein Adressblock. Jedes andere Schema bindet es per useFields an ein Objektfeld, die Felder werden beim Laden inline übernommen. extends erbt ganze Schemas, einzeln oder mehrere; pick, omit und partial schneiden das Ergebnis zu. strict: true weist unbekannte Felder beim Schreiben ab, statt sie still mitzuschleppen.
Validierung, die nicht erst im Frontend auffällt
required, min/max, minLength/maxLength, pattern, enum, unique, minItems/maxItems — verschachtelt bis in Array-Items. Geprüft wird an drei Stellen: beim Schreiben über die API, per validate-CLI ohne laufenden Server (Exit-Code 1 bei Fehlern, also CI-tauglich) und in der Admin-UI, wo jeder fehlerhafte Eintrag direkt zum Editor verlinkt.
validate --content-dir ./content --collections post,page
Autocomplete im Editor
Ein Export schreibt aus jedem Schema eine JSON-Schema-Datei. VS Code oder Cursor prüfen damit Content-Dateien beim Tippen — Pflichtfelder, Enum-Werte, Längenlimits als Unterstreichung, bevor irgendetwas gespeichert ist.
Was nicht passiert
Eine Schema-Änderung schreibt keine bestehenden Einträge um. Wer ein Feld umbenennt oder löscht, macht das mit einer Migration — bewusst getrennt, damit kein Edit an einer Datei still Content verändert.