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:
| Eigenschaft | Beschreibung |
|---|---|
slug | URL-sicherer Bezeichner (z. B. posts, products) |
label | Anzeigename (z. B. „Blog Posts“) |
labelSingular | Singularform (z. B. „Post“) |
description | Optionale Beschreibung für Redakteurinnen |
icon | Lucide-Icon-Name für die Admin-Seitenleiste |
supports | Features wie Entwürfe, Revisionen, Vorschau, Planung, Suche, SEO |
Collection-Features
Beim Anlegen einer Collection aktivierst du die benötigten Features:
| Feature | Beschreibung |
|---|---|
drafts | Entwurf/Veröffentlicht-Workflow |
revisions | Inhaltshistorie mit Versions-Snapshots |
preview | Signierte Vorschau-URLs für Entwürfe |
scheduling | Verö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:
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
slug | string | Spaltenname in der Datenbank |
label | string | Anzeige-Label in der Admin-UI |
type | FieldType | Einer der 15 Feldtypen |
required | boolean | Ob das Feld einen Wert braucht |
unique | boolean | Ob Werte projektweit eindeutig sein müssen |
defaultValue | unknown | Standardwert für neue Einträge |
validation | object | Typspezifische Validierungsregeln |
widget | string | ID eines Custom-Widgets |
options | object | Widget-spezifische Konfiguration |
sortOrder | number | Anzeigereihenfolge 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:
| Feldtyp | SQLite-Typ | Hinweis |
|---|---|---|
string | TEXT | |
text | TEXT | |
slug | TEXT | |
number | REAL | 64-Bit-Gleitkomma |
integer | INTEGER | 64-Bit-Ganzzahl mit Vorzeichen |
boolean | INTEGER | 0 oder 1 |
datetime | TEXT | ISO-8601-Format |
select | TEXT | |
multiSelect | JSON | String-Array |
portableText | JSON | Block-Array |
image | TEXT | Medien-ID |
file | TEXT | Medien-ID |
reference | TEXT | Eintrags-ID |
json | JSON | Beliebiges JSON |
Nächste Schritte
Inhaltsmodell
Datenbank-zuerst-Ansatz verstehen.
Taxonomien
Inhalte mit Kategorien und Schlagwörtern ordnen.
Medienbibliothek
Bilder und Dateien verwalten.