Collections & Felder

Auf dieser Seite

Collections sind die Basis von EmDashs Inhaltsmodell. Jede Collection steht für einen Inhaltstyp (Beiträge, Seiten, Produkte) und enthält Felddefinitionen, die die Form deiner Daten festlegen.

Collections anlegen

Collections legst du im Admin unter Inhaltstypen an. Jede Collection hat:

EmDash-Inhaltstypen: Seiten, Beiträge und eigene Collections mit Features
EigenschaftBeschreibung
slugURL-sicherer Bezeichner (z. B. posts, products)
labelAnzeigename (z. B. „Blog Posts“)
labelSingularSingularform (z. B. „Post“)
descriptionOptionale Beschreibung für Redakteurinnen
iconLucide-Icon-Name für die Admin-Seitenleiste
supportsFeatures wie Entwürfe, Revisionen, Vorschau, Planung, Suche, SEO

Collection-Features

Beim Anlegen einer Collection aktivierst du die benötigten Features:

FeatureBeschreibung
draftsEntwurf/Veröffentlicht-Workflow
revisionsInhaltshistorie mit Versions-Snapshots
previewSignierte Vorschau-URLs für Entwürfe
schedulingVeröffentlichung zu einem späteren Zeitpunkt planen
// Beispiel-Collection mit allen Features
{
  slug: "posts",
  label: "Blog Posts",
  labelSingular: "Post",
  supports: ["drafts", "revisions", "preview", "scheduling"]
}

Feldtypen

EmDash unterstützt 15 Feldtypen, die SQLite-Spaltentypen zugeordnet werden:

Textfelder

string

Kurzes Textfeld. Entspricht Spalte TEXT.

{ slug: "title", type: "string", label: "Title" }

text

Mehrzeiliges Textfeld. Entspricht Spalte TEXT.

{ slug: "excerpt", type: "text", label: "Excerpt" }

slug

URL-sicheres Slug-Feld. Entspricht Spalte TEXT.

{ slug: "handle", type: "slug", label: "URL Handle" }

Rich Content

portableText

Rich-Text-Editor (TipTap/ProseMirror). Als JSON gespeichert.

{ slug: "content", type: "portableText", label: "Content" }

Portable Text ist ein blockbasiertes Format, das Struktur ohne eingebettetes HTML erhält.

json

Beliebige JSON-Daten. Als JSON gespeichert.

{ slug: "metadata", type: "json", label: "Custom Metadata" }

Zahlen

number

Dezimalzahlen. Entspricht Spalte REAL.

{ slug: "price", type: "number", label: "Price" }

integer

Ganze Zahlen. Entspricht Spalte INTEGER.

{ slug: "quantity", type: "integer", label: "Stock Quantity" }

Booleans & Daten

boolean

Ja/Nein-Schalter. Entspricht INTEGER (0/1).

{ slug: "featured", type: "boolean", label: "Featured Post" }

datetime

Datums- und Zeitauswahl. Als ISO-8601-String gespeichert.

{ slug: "eventDate", type: "datetime", label: "Event Date" }

Auswahl

select

Eine Option aus einer Liste. Entspricht Spalte TEXT.

{
  slug: "status",
  type: "select",
  label: "Product Status",
  validation: {
    options: ["active", "discontinued", "coming_soon"]
  }
}

multiSelect

Mehrere Optionen aus einer Liste. Als JSON-Array gespeichert.

{
  slug: "features",
  type: "multiSelect",
  label: "Product Features",
  validation: {
    options: ["wireless", "waterproof", "eco-friendly"]
  }
}

Medien & Referenzen

image

Bildauswahl aus der Medienbibliothek. Speichert Medien-ID als TEXT.

{ slug: "featuredImage", type: "image", label: "Featured Image" }

file

Dateiauswahl aus der Medienbibliothek. Speichert Medien-ID als TEXT.

{ slug: "attachment", type: "file", label: "PDF Attachment" }

reference

Verweis auf einen Eintrag einer anderen Collection. Speichert Eintrags-ID als TEXT.

{
  slug: "author",
  type: "reference",
  label: "Author",
  options: {
    collection: "authors"
  }
}

Feldeigenschaften

Jedes Feld unterstützt diese Eigenschaften:

EigenschaftTypBeschreibung
slugstringSpaltenname in der Datenbank
labelstringAnzeige-Label in der Admin-UI
typeFieldTypeEiner der 15 Feldtypen
requiredbooleanOb das Feld einen Wert braucht
uniquebooleanOb Werte projektweit eindeutig sein müssen
defaultValueunknownStandardwert für neue Einträge
validationobjectTypspezifische Validierungsregeln
widgetstringID eines Custom-Widgets
optionsobjectWidget-spezifische Konfiguration
sortOrdernumberAnzeigereihenfolge im Editor

Validierungsregeln

Das Objekt validation hängt vom Feldtyp ab:

interface FieldValidation {
	required?: boolean; // alle Typen
	min?: number; // number, integer
	max?: number; // number, integer
	minLength?: number; // string, text
	maxLength?: number; // string, text
	pattern?: string; // string (Regex)
	options?: string[]; // select, multiSelect
}

Beispiel mit Validierung:

{
  slug: "email",
  type: "string",
  label: "Email Address",
  required: true,
  unique: true,
  validation: {
    pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
  }
}

Widget-Optionen

Das Objekt options steuert feldspezifisches UI-Verhalten:

interface FieldWidgetOptions {
	rows?: number; // text (Textarea-Zeilen)
	showPreview?: boolean; // image, file
	collection?: string; // reference (Ziel-Collection)
	allowMultiple?: boolean; // reference (mehrere Verweise)
	[key: string]: unknown; // Custom-Widget-Optionen
}

Beispiel Referenzfeld:

{
  slug: "relatedProducts",
  type: "reference",
  label: "Related Products",
  options: {
    collection: "products",
    allowMultiple: true
  }
}

Collections abfragen

Nutze die mitgelieferten Abfragefunktionen für Inhalte. Sie folgen dem Live-Collections-Muster von Astro und liefern strukturierte Ergebnisse:

import { getEmDashCollection, getEmDashEntry } from "emdash";

// Alle Einträge – liefert { entries, error }
const { entries: posts } = await getEmDashCollection("posts");

// Nach Status filtern
const { entries: drafts } = await getEmDashCollection("posts", {
	status: "draft",
});

// Ergebnis begrenzen
const { entries: recent } = await getEmDashCollection("posts", {
	limit: 5,
});

// Nach Taxonomie filtern
const { entries: newsPosts } = await getEmDashCollection("posts", {
	where: { category: "news" },
});

// Einzelner Eintrag per Slug – liefert { entry, error, isPreview }
const { entry: post } = await getEmDashEntry("posts", "my-post-slug");

// Fehler behandeln
const { entries, error } = await getEmDashCollection("posts");
if (error) {
	console.error("Failed to load posts:", error);
}

Typgenerierung

Führe npx emdash types aus, um TypeScript-Typen aus deinem Schema zu erzeugen:

// .emdash/types.ts (generiert)
export interface Post {
	title: string;
	content: PortableTextBlock[];
	excerpt?: string;
	featuredImage?: string;
	author: string; // Referenz-ID
}

export interface Product {
	title: string;
	price: number;
	description: PortableTextBlock[];
}

Abbildung auf die Datenbank

Feldtypen werden SQLite-Spaltentypen zugeordnet:

FeldtypSQLite-TypHinweis
stringTEXT
textTEXT
slugTEXT
numberREAL64-Bit-Gleitkomma
integerINTEGER64-Bit-Ganzzahl mit Vorzeichen
booleanINTEGER0 oder 1
datetimeTEXTISO-8601-Format
selectTEXT
multiSelectJSONString-Array
portableTextJSONBlock-Array
imageTEXTMedien-ID
fileTEXTMedien-ID
referenceTEXTEintrags-ID
jsonJSONBeliebiges JSON

Nächste Schritte