EmDash unterstützt 17 Feldtypen zur Definition von Inhaltsschemata. Jeder Typ wird auf einen SQLite-Spaltentyp abgebildet und stellt eine passende Admin-UI bereit.
Überblick
Die folgende Tabelle listet jeden Feldtyp und seine SQLite-Spalte:
| Type | SQLite Column | Description |
|---|---|---|
string | TEXT | Kurze Texteingabe |
text | TEXT | Mehrzeiliger Text |
url | TEXT | URL-Wert |
number | REAL | Dezimalzahl |
integer | INTEGER | Ganze Zahl |
boolean | INTEGER | Wahr/Falsch |
datetime | TEXT | Datum und Uhrzeit |
select | TEXT | Einzelauswahl aus Optionen |
multiSelect | JSON | Mehrfachauswahl |
portableText | JSON | Rich-Text-Inhalt |
image | TEXT | Bildreferenz |
file | TEXT | Dateireferenz |
reference | none | Verknüpft Einträge einer anderen Collection |
json | JSON | Beliebige JSON-Daten |
slug | TEXT | URL-sicherer Bezeichner |
repeater | JSON | Wiederholende Feldgruppe |
blocks | JSON | Typisierte Seitenkomposition |
Texttypen
string
Kurzer einzeiliger Text. Für Titel, Namen und kurze Werte.
{
slug: "title",
label: "Title",
type: "string",
required: true,
validation: {
minLength: 1,
maxLength: 200,
},
}
Validierungsoptionen:
minLength— Minimale ZeichenanzahlmaxLength— Maximale Zeichenanzahlpattern— Regulärer Ausdruck, dem der Wert entsprechen muss
Der Editor begrenzt die Eingabe auf maxLength und zeigt einen Live-Zeichenzähler gegenüber den Längenregeln.
Widget-Optionen:
- Keine spezifischen
text
Mehrzeiliger Klartext. Für Beschreibungen, Auszüge und längeren Klartext.
{
slug: "excerpt",
label: "Excerpt",
type: "text",
options: {
rows: 3,
},
}
Validierungsoptionen:
minLength— Minimale ZeichenanzahlmaxLength— Maximale Zeichenanzahlpattern— Regulärer Ausdruck, dem der Wert entsprechen muss
Der Editor begrenzt die Eingabe auf maxLength und zeigt einen Live-Zeichenzähler gegenüber den Längenregeln.
Widget-Optionen:
rows— Anzahl der Zeilen im Textarea (Standard: 3)
url
Eine Webadresse. Die Content-API lehnt Werte ab, die keine gültigen URLs sind.
{
slug: "website",
label: "Website",
type: "url",
required: true,
}
URL-Felder werden als Text gespeichert. Verwenden Sie stattdessen ein string-Feld, wenn der Wert ein relativer Pfad wie /about sein kann, weil relative Pfade für ein url-Feld keine gültigen Werte sind.
slug
Text, der einen slug-ähnlichen Wert halten soll. Dieser benutzerdefinierte Feldtyp erzeugt oder bereinigt den Wert nicht.
{
slug: "legacy_slug",
label: "Legacy Slug",
type: "slug",
required: true,
unique: true,
}
Jeder Inhaltseintrag hat bereits einen reservierten System-slug, den EmDash separat für öffentliche URLs verwaltet. Verwenden Sie ein benutzerdefiniertes slug-Feld nur, wenn das Inhaltsmodell einen weiteren gespeicherten slug-ähnlichen Wert braucht.
Zahlentypen
number
Dezimalzahl. Für Preise, Bewertungen und Maße.
{
slug: "price",
label: "Price",
type: "number",
required: true,
validation: {
min: 0,
max: 999999.99,
},
}
Validierungsoptionen:
min— Minimalwertmax— Maximalwert
Der Editor setzt min und max am Zahleneingabefeld und zeigt den erlaubten Bereich darunter.
Gespeichert als SQLite REAL (64-Bit-Gleitkomma).
integer
Ganze Zahl. Für Mengen, Zähler und Reihenfolgewerte.
{
slug: "quantity",
label: "Quantity",
type: "integer",
defaultValue: 1,
validation: {
min: 0,
max: 1000,
},
}
Validierungsoptionen:
min— Minimalwertmax— Maximalwert
Der Editor setzt min und max am Zahleneingabefeld und zeigt den erlaubten Bereich darunter.
Gespeichert als SQLite INTEGER.
boolean
Wahr oder falsch. Für Umschalter und Flags.
{
slug: "featured",
label: "Featured",
type: "boolean",
defaultValue: false,
}
Gespeichert als SQLite INTEGER (0 oder 1).
Datum und Uhrzeit
datetime
Ein Zeitpunkt. API-, MCP- und CLI-Schreibvorgänge müssen Z oder einen expliziten UTC-Offset enthalten. Die Admin interpretiert ihren Datums-/Zeit-Picker in der unter Settings → General konfigurierten Zeitzone.
{
slug: "publishedAt",
label: "Published At",
type: "datetime",
}
Speicherformat: 2025-01-24T12:00:00.000Z
EmDash konvertiert akzeptierte Eingaben vor dem Speichern in UTC mit dreistelligen Millisekunden. Beispielsweise wird 2025-01-24T21:00:00+09:00 als 2025-01-24T12:00:00.000Z gespeichert. Verwenden Sie stattdessen ein string-Feld, wenn der Wert ein Kalenderdatum oder eine lokale Wanduhrzeit und kein Zeitpunkt ist.
Auswahltypen
select
Einzelauswahl aus vordefinierten Optionen.
{
slug: "status",
label: "Status",
type: "select",
required: true,
defaultValue: "draft",
validation: {
options: ["draft", "published", "archived"],
},
}
Validierungsoptionen:
options— Optionales Array erlaubter Werte. Angeben, um vordefinierte Auswahlmöglichkeiten anzubieten und andere Strings abzulehnen; ohne Angabe akzeptiert die Validierung jeden String.
Gespeichert als TEXT mit dem ausgewählten Wert.
multiSelect
Mehrfachauswahl aus vordefinierten Optionen.
{
slug: "tags",
label: "Tags",
type: "multiSelect",
validation: {
options: ["news", "tutorial", "review", "opinion"],
},
}
Validierungsoptionen:
options— Optionales Array erlaubter Werte. Angeben, um vordefinierte Auswahlmöglichkeiten anzubieten und andere Strings abzulehnen; ohne Angabe akzeptiert die Validierung jedes String-Array.
Gespeichert als JSON-Array: ["news", "tutorial"]
Rich Content
portableText
Rich-Text-Inhalt im Portable-Text-Format. Unterstützt Überschriften, Listen, Links, Bilder und benutzerdefinierte Blöcke.
{
slug: "content",
label: "Content",
type: "portableText",
required: true,
}
Der Wert wird als JSON-Array von Portable-Text-Blöcken gespeichert, zum Beispiel:
[
{
"_type": "block",
"style": "normal",
"children": [{ "_type": "span", "text": "Hello world" }]
}
]
Plugins können dem Editor benutzerdefinierte Blocktypen (Embeds, Widgets usw.) hinzufügen. Diese erscheinen im Slash-Befehlsmenü. Das Rendern des gespeicherten Blocks auf der öffentlichen Site erfordert eine Astro-Komponente aus einem nativen Plugin oder Companion-Paket. Siehe Portable-Text-Rendering-Komponenten.
Medientypen
image
Referenz auf ein hochgeladenes Bild. Enthält Metadaten wie Abmessungen und Alt-Text.
{
slug: "featuredImage",
label: "Featured Image",
type: "image",
validation: {
allowedMimeTypes: ["image/jpeg", "image/png"],
},
options: {
darkVariant: true,
},
}
Widget-Optionen:
darkVariant— Bietet Editoren einen zweiten Slot für ein Bild in dunklen Farbschemas (Standard: false). Siehe Dark Mode.
Validierungsoptionen:
allowedMimeTypes— Nicht-leere Liste exakter MIME-Typen, die für die ausgewählten Medien akzeptiert werden
Der Wert wird als Objekt mit Medienreferenz und Metadaten gespeichert:
{
"id": "01HXK5MZSN...",
"src": "/_emdash/api/media/file/01HXK5MZSN...",
"alt": "Description",
"width": 1920,
"height": 1080,
"provider": "local",
"meta": {
"storageKey": "01HXK5MZSN....jpg"
}
}
Mit aktiviertem darkVariant kann der Wert das dunkle Gegenstück unter darkVariant im gleichen Format tragen:
{
"id": "01HXK5MZSN...",
"alt": "Architecture diagram",
"width": 1920,
"height": 1080,
"darkVariant": {
"id": "01HXK5N2QT...",
"width": 1920,
"height": 1080
}
}
file
Referenz auf eine hochgeladene Datei wie ein Dokument oder PDF.
{
slug: "document",
label: "Document",
type: "file",
validation: {
allowedMimeTypes: ["application/pdf"],
},
}
Validierungsoptionen:
allowedMimeTypes— Nicht-leere Liste exakter MIME-Typen, die für die ausgewählten Medien akzeptiert werden
Der Wert wird als Provider-Referenz mit zwischengespeicherten Metadaten gespeichert:
{
"id": "01HXK5MZSN...",
"provider": "local",
"filename": "report.pdf",
"mimeType": "application/pdf",
"meta": {
"storageKey": "01HXK5MZSN....pdf"
}
}
url und size sind wie die anderen zwischengespeicherten Metadatenfelder optional. Inhaltsabfragen geben den
persistierten Wert unverändert zurück und hydrieren ihn nicht aus der Medienbibliothek. Siehe
Dateiwerte und aktuelle Metadaten für die
kanonischen Lookup-APIs, wenn Sie frische Metadaten oder eine provider-spezifische URL brauchen.
Relationstypen
reference
Verknüpft einen Eintrag mit Einträgen einer anderen Collection und erscheint in der Admin als Eintragsauswahl. Die Verknüpfungen gehören zu einer Relation: einem Schemaobjekt, das zwei Collections verbindet, jede Seite benennt und begrenzt, wie viele Einträge jede Seite verknüpfen darf. Relations behandelt den Editor- und Admin-Workflow.
Das folgende Feld verknüpft einen Beitrag mit einem Eintrag der Collection authors:
{
slug: "author",
label: "Author",
type: "reference",
required: true,
validation: {
targetCollection: "authors",
multiple: false,
},
}
Validierung:
targetCollection— Slug der Collection, zu der dieses Feld verknüpft. Das Anlegen des Felds erzeugt eine Relation dafür.multiple— Mehr als einen verknüpften Eintrag erlauben (Standard: false). Nur zusammen mittargetCollectionlesen, weil das Limit dann zur neuen Relation gehört.relation— Slug einer bestehenden Relation, an die gebunden werden soll, statt eine neue zu erzeugen.relationSide— An welchem Ende vonrelationdiese Collection sitzt,"parent"oder"child". Nur setzen für eine Relation, deren beide Enden dieselbe Collection sind, wo beide Enden übereinstimmen.
Geben Sie entweder targetCollection oder relation an. Ein aus targetCollection erzeugtes Feld wird zum
Elternende einer Relation namens {collection}_{field}, deren Kindseite das Label des Felds übernimmt und
einen Eintrag hält, sofern multiple nicht gesetzt ist. Ein aus relation erzeugtes Feld betrachtet diese Relation vom
Ende aus, an dem seine Collection sitzt, und die Collection am anderen Ende ist das Ziel des Felds. Eine
Relation akzeptiert ein Feld pro Ende; ein zweites Feld über dasselbe Ende wird abgelehnt. Beide Formen
speichern relation, relationSide und targetCollection am erzeugten Feld, und die Ziel-
Collection ist danach fest: zum Ändern das Feld löschen und ein neues hinzufügen. Das Umbenennen des
Felds benennt die Seite der Relation um, die es betrachtet.
Ein Referenzfeld fügt der Collection-Tabelle keine Spalte hinzu. Seine Verknüpfungen liegen in
_emdash_content_references, keyed nach der Übersetzungsgruppe jedes Eintrags, sodass eine Auswahl über
die Übersetzungen eines Eintrags geteilt wird statt pro Locale gesetzt. Inhaltslesungen geben die verknüpften Einträge
unter references, keyed nach Feld-Slug, zurück statt in data. In einem Template das Feld nach
Namen abfragen — siehe Referenzfelder lesen.
Ein an eine Relation gebundenes Feld kann indexed nicht setzen, weil es keine Spalte zum Indexieren speichert, und die Site-
Suche deckt es nicht ab.
Felder ohne Relation
Ein Referenzfeld, das weder Relation noch Ziel-Collection nennt, behält eine TEXT-Spalte und
hält darin eine Eintrags-ID:
"01HXK5MZSN..."
Ein Feld, dessen options.allowMultiple gesetzt ist, hält ein JSON-Array von Eintrags-IDs in derselben Spalte:
["01HXK5MZSN...", "01HXK6NATS..."]
Die Spalte wird wie jede andere Textspalte gelesen und geschrieben, das Collection-Schema validiert den
Wert als String, und das Feld kann indexed setzen und als Inhaltslistenfilter wirken. Es erscheint als
Textfeld statt als Auswahl.
Um es zu einem Picker zu machen, öffnen Sie das Feld unter Content Types und wählen Sie eine referenzierte Collection.
EmDash erzeugt die Relation, kopiert die Eintrags-IDs in der Spalte als Verknüpfungen hinein und löscht die Flags
searchable und indexed des Felds, sodass Inhaltslistenfilter und Site-Suche es nicht mehr abdecken. Die
Spalte bleibt stehen und wird nicht mehr beschrieben. Relations
behandelt denselben Schritt aus Sicht des Editors.
Eine von einer früheren Version aktualisierte Site kann Felder in diesem Zustand halten. Siehe Referenzfelder binden an Relationen dazu, was das Update bindet und was Sie selbst binden müssen.
Flexible Typen
json
Beliebige JSON-Daten. Für komplexe verschachtelte Strukturen, Drittanbieter-Integrationen oder Daten ohne festes Schema.
{
slug: "metadata",
label: "Metadata",
type: "json",
}
Gespeichert unverändert in einer SQLite-JSON-Spalte.
repeater
Eine wiederholende Liste strukturierter Zeilen. Definieren Sie mindestens ein Unterfeld in validation.subFields; Editoren können dann Zeilen hinzufügen, entfernen, umordnen und bearbeiten, ohne Roh-JSON einzugeben.
Das folgende Feld speichert eine Liste von Produktspezifikationen:
{
slug: "specifications",
label: "Specifications",
type: "repeater",
validation: {
minItems: 1,
maxItems: 12,
subFields: [
{ slug: "label", label: "Label", type: "string", required: true },
{ slug: "value", label: "Value", type: "text", required: true },
{ slug: "source", label: "Source", type: "url" },
],
},
}
Repeater-Werte werden als Array von Objekten gespeichert:
[
{
"label": "Weight",
"value": "1.2 kg",
"source": "https://example.com/specifications"
}
]
Erlaubte Unterfeldtypen sind string, text, url, number, integer, boolean, datetime, select und image. Repeater dürfen keinen weiteren Repeater und kein komplexes Feld wie portableText, reference oder file enthalten.
Repeater-Validierung akzeptiert diese Eigenschaften:
subFields— Eine oder mehrere Unterfelddefinitionen. Jede Definition erfordertslug,labelundtype; sie kann auchrequiredsetzen. Einselect-Unterfeld liefert seine Auswahl überoptions.minItems— Minimale Anzahl Zeilen. Muss null oder größer sein.maxItems— Maximale Anzahl Zeilen. Muss eins oder größer sein und darf nicht kleiner alsminItemssein.
blocks
Eine geordnete Liste typisierter Inhaltsblöcke. Jeder Blocktyp hat eigene Felder und behält nummerierte Versionen. Definieren Sie Blocktypen über die Schema-API, MCP oder eine Seed-Datei, bevor Sie sie einem Collection-Feld hinzufügen.
Das folgende Feld erlaubt Editoren, eine Seite aus Hero- und Call-to-Action-Blöcken zusammenzusetzen:
{
slug: "layout",
label: "Layout",
type: "blocks",
validation: {
allowedTypes: ["hero", "call_to_action"],
maxItems: 20,
},
}
Jeder gespeicherte Block trägt Typ, Version und stabilen Schlüssel neben den von dieser Version deklarierten Feldern:
[
{
"_type": "hero",
"_version": 1,
"_key": "01K5AB3F7M9QZ2X8W4V6T1R0YH",
"heading": "Bread made slowly, by hand."
}
]
Blocks-Validierung akzeptiert diese Eigenschaften:
allowedTypes— Geordnete Blocktyp-Slugs, die für neue Blöcke verfügbar sind.retiredTypes— Vom Server verwaltete Blocktypen, die für gespeicherten Inhalt behalten, aber für neue Blöcke nicht verfügbar sind.minItems— Minimale Anzahl Blöcke. Eine Erhöhung über null bei einer befüllten Collection erfordert eine Inhaltsmigration.maxItems— Maximale Anzahl Blöcke, bis zu 100.
Ein Blocks-Feld ist optional und standardmäßig ein leeres Array. Es kann nicht required, unique, searchable, indexed oder von einem benutzerdefinierten Feld-Widget gerendert werden. Blockdefinitionen können Skalar-, Text-, Auswahl-, Portable-Text-, Bild-, Datei- und Repeater-Felder verwenden. Sie dürfen keine Referenzen, JSON, Slugs oder verschachtelte Blocks enthalten.
Rendern Sie das gespeicherte Array mit <Blocks value components fallback> aus emdash/ui. Siehe Seiten mit Blocks bauen für Seed-, Komponentenmap-, Missing-Renderer-, Aktivierungs- und Migrationsbeispiele.
Feldeigenschaften
Alle Felder unterstützen diese gemeinsamen Eigenschaften:
| Property | Type | Description |
|---|---|---|
slug | string | Eindeutiger Bezeichner (erforderlich) |
label | string | Anzeigename (erforderlich) |
type | FieldType | Feldtyp (erforderlich) |
required | boolean | Wert erfordern (Standard: false) |
unique | boolean | Eindeutigkeit erzwingen (Standard: false) |
searchable | boolean | Feld in die Volltextsuche aufnehmen (Standard: false) |
indexed | boolean | Indexiertes Sortieren/Filtern aktivieren |
translatable | boolean | Wert pro Locale speichern (Standard: true) |
defaultValue | unknown | Standardwert für neue Einträge |
validation | object | Typspezifische Validierungsregeln |
widget | string | Benutzerdefinierte Widget-Überschreibung |
options | object | Widget-Konfiguration |
sortOrder | number | Anzeigereihenfolge in der Admin |
indexed ist für Skalarfelder verfügbar: string, url, number, integer, boolean,
datetime, select, reference und slug. Ein indexiertes Feld kann als orderBy-
Feld übergeben oder in fieldFilters in Inhaltslistenabfragen verwendet werden. Vermeiden Sie das Indexieren von Feldern, die nicht zum
Sortieren oder Filtern genutzt werden, weil jeder Index Speicher- und Schreibaufwand erzeugt.
searchable fügt den Text des Felds dem Volltextsuchindex der Collection hinzu. Setzen Sie translatable: false für Bezeichner, Preise, Flags und andere Werte, die über jede Übersetzung eines Eintrags gleich bleiben müssen; wenn eine Locale ein nicht übersetzbares Feld ändert, synchronisiert EmDash den Wert zu seinen übersetzten Einträgen.
Der Typ blocks verwendet aus diesem gemeinsamen Satz nur slug, label, type, translatable, validation und sortOrder. Sein Array ist nie spaltenpflichtig und standardmäßig immer [].
Reservierte Feld-Slugs
Diese Slugs sind reserviert und können nicht verwendet werden:
idslugstatusauthor_idprimary_byline_idcreated_atupdated_atpublished_atscheduled_atdeleted_atversionlive_revision_iddraft_revision_idtermsbylinesbyline
TypeScript-Typen
Importieren Sie die Feldtypdefinitionen für die programmatische Nutzung:
import type { FieldType, Field, CreateFieldInput } from "emdash";
const fieldTypes: FieldType[] = [
"string",
"text",
"url",
"number",
"integer",
"boolean",
"datetime",
"select",
"multiSelect",
"portableText",
"image",
"file",
"reference",
"json",
"slug",
"repeater",
"blocks",
];