Inhaltsmodell
Verstehen Sie den datenbankorientierten Ansatz.
Sammlungen sind die Grundlage des Inhaltsmodells von EmDash. Jede Sammlung repräsentiert einen Inhaltstyp (Beiträge, Seiten, Produkte) und enthält Felddefinitionen, die die Struktur Ihrer Daten bestimmen.
Erstellen Sie Sammlungen über das Admin-Oberfläche unter Inhaltstypen. Jede Sammlung hat:
| Eigenschaft | Beschreibung |
|---|---|
slug | URL-sicherer Bezeichner (z.B. posts, products) |
label | Anzeigename (z.B. “Blogbeiträge”) |
labelSingular | Singularform (z.B. “Beitrag”) |
description | Optionale Beschreibung für Redakteure |
icon | Lucide-Icon-Name für die Admin-Seitenleiste |
supports | Funktionen wie Entwürfe, Revisionen, Vorschau, Zeitplanung, Suche, SEO |
Beim Erstellen einer Sammlung aktivieren Sie die benötigten Funktionen:
| Funktion | Beschreibung |
|---|---|
drafts | Entwurf/Veröffentlicht-Workflow aktivieren |
revisions | Inhaltsverlauf mit Versions-Snapshots verfolgen |
preview | Signierte Vorschau-URLs für Entwurfsinhalte generieren |
scheduling | Inhalte für Veröffentlichung zu einem zukünftigen Datum planen |
// Example collection with all features enabled{ slug: "posts", label: "Blog Posts", labelSingular: "Post", supports: ["drafts", "revisions", "preview", "scheduling"]}EmDash unterstützt 15 Feldtypen, die SQLite-Spaltentypen zugeordnet sind:
Kurze Texteingabe. Wird der TEXT-Spalte zugeordnet.
{ slug: "title", type: "string", label: "Title" }Mehrzeiliges Textfeld. Wird der TEXT-Spalte zugeordnet.
{ slug: "excerpt", type: "text", label: "Excerpt" }URL-sicheres Slug-Feld. Wird der TEXT-Spalte zugeordnet.
{ slug: "handle", type: "slug", label: "URL Handle" }Rich-Text-Editor (TipTap/ProseMirror). Wird als JSON gespeichert.
{ slug: "content", type: "portableText", label: "Content" }Portable Text ist ein blockbasiertes Format, das Struktur erhält, ohne HTML einzubetten.
Beliebige JSON-Daten. Wird als JSON gespeichert.
{ slug: "metadata", type: "json", label: "Custom Metadata" }Dezimalzahlen. Wird der REAL-Spalte zugeordnet.
{ slug: "price", type: "number", label: "Price" }Ganze Zahlen. Wird der INTEGER-Spalte zugeordnet.
{ slug: "quantity", type: "integer", label: "Stock Quantity" }Wahr/Falsch-Umschalter. Wird INTEGER (0/1) zugeordnet.
{ slug: "featured", type: "boolean", label: "Featured Post" }Datums- und Zeitauswahl. Wird als ISO-8601-Zeichenkette gespeichert.
{ slug: "eventDate", type: "datetime", label: "Event Date" }Einzelne Option aus einer Liste. Wird der TEXT-Spalte zugeordnet.
{ slug: "status", type: "select", label: "Produktstatus", validation: { options: ["active", "discontinued", "coming_soon"] }}Mehrere Optionen aus einer Liste. Wird als JSON-Array gespeichert.
{ slug: "features", type: "multiSelect", label: "Produktfunktionen", validation: { options: ["wireless", "waterproof", "eco-friendly"] }}Bildauswahl aus der Mediathek. Speichert Medien-ID als TEXT.
{ slug: "featuredImage", type: "image", label: "Featured Image" }Dateiauswahl aus der Mediathek. Speichert Medien-ID als TEXT.
{ slug: "attachment", type: "file", label: "PDF Attachment" }Referenz auf einen Eintrag einer anderen Sammlung. Speichert Eintrags-ID als TEXT.
{ slug: "author", type: "reference", label: "Autor", options: { collection: "authors" }}Jedes Feld unterstützt diese Eigenschaften:
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
slug | string | Spaltenname in der Datenbank |
label | string | Anzeigelabel in der Admin-UI |
type | FieldType | Einer der 15 Feldtypen |
required | boolean | Ob das Feld einen Wert haben muss |
unique | boolean | Ob Werte über Einträge hinweg eindeutig sein müssen |
defaultValue | unknown | Standardwert für neue Einträge |
validation | object | Typspezifische Validierungsregeln |
widget | string | Benutzerdefinierter Widget-Bezeichner |
options | object | Widget-spezifische Konfiguration |
sortOrder | number | Anzeigereihenfolge im Editor |
Das validation-Objekt variiert je nach Feldtyp:
interface FieldValidation { required?: boolean; // All types 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,}$" }}Das options-Objekt konfiguriert das feld-spezifische UI-Verhalten:
interface FieldWidgetOptions { rows?: number; // text (textarea rows) showPreview?: boolean; // image, file collection?: string; // reference (target collection) allowMultiple?: boolean; // reference (multiple refs) [key: string]: unknown; // Custom widget options}Beispiel-Referenzfeld:
{ slug: "relatedProducts", type: "reference", label: "Related Products", options: { collection: "products", allowMultiple: true }}Verwenden Sie die bereitgestellten Abfragefunktionen, um Inhalte abzurufen. Diese folgen Astros Live-Sammlungs-Muster und geben strukturierte Ergebnisse zurück:
import { getEmDashCollection, getEmDashEntry } from "emdash";
// Alle Einträge abrufen - gibt { entries, error } zurückconst { entries: posts } = await getEmDashCollection("posts");
// Nach Status filternconst { entries: drafts } = await getEmDashCollection("posts", { status: "draft",});
// Ergebnisse begrenzenconst { entries: recent } = await getEmDashCollection("posts", { limit: 5,});
// Nach Taxonomie filternconst { entries: newsPosts } = await getEmDashCollection("posts", { where: { category: "news" },});
// Einen einzelnen Eintrag anhand des Slugs abrufen - gibt { entry, error, isPreview } zurückconst { entry: post } = await getEmDashEntry("posts", "my-post-slug");
// Fehler behandelnconst { entries, error } = await getEmDashCollection("posts");if (error) { console.error("Failed to load posts:", error);}Führen Sie npx emdash types aus, um TypeScript-Typen aus Ihrem Schema zu generieren:
// .emdash/types.ts (generated)export interface Post { title: string; content: PortableTextBlock[]; excerpt?: string; featuredImage?: string; author: string; // reference ID}
export interface Product { title: string; price: number; description: PortableTextBlock[];}Feldtypen werden auf SQLite-Spaltentypen abgebildet:
| Feldtyp | SQLite-Typ | Anmerkungen |
|---|---|---|
string | TEXT | |
text | TEXT | |
slug | TEXT | |
number | REAL | 64-Bit-Gleitkommazahl |
integer | INTEGER | 64-Bit-Ganzzahl mit Vorzeichen |
boolean | INTEGER | 0 oder 1 |
datetime | TEXT | ISO-8601-Format |
select | TEXT | |
multiSelect | JSON | Array von Strings |
portableText | JSON | Block-Array |
image | TEXT | Medien-ID |
file | TEXT | Medien-ID |
reference | TEXT | Eintrags-ID |
json | JSON | Beliebiges JSON |
Inhaltsmodell
Verstehen Sie den datenbankorientierten Ansatz.
Taxonomien
Organisieren Sie Inhalte mit Kategorien und Tags.
Medienbibliothek
Verwalten Sie Bilder und Dateien.