EmDash für Astro-Entwickler

Auf dieser Seite

EmDash fügt einer Astro-Site eine Admin-Anwendung, datenbankgestützte Sammlungen, Medien, Menüs, Taxonomien, Einstellungen, Revisionen und Vorschauen hinzu. Seiten und Komponenten bleiben gewöhnliche Astro-Dateien.

Was EmDash hinzufügt

FunktionWas es bereitstellt
AdminBrowserbasierte Verwaltung von Sammlungen, Medien, Menüs, Taxonomien und Einstellungen unter /_emdash/admin
Datenbank-SammlungenVom Editor verwaltete Inhalte, die zur Anforderungszeit abgefragt werden
MedienbibliothekGespeicherte Bilder und Dateien mit Medienfeldwerten für Templates
Entwürfe, Revisionen und VorschauenRedaktionelle Arbeit vor der Veröffentlichung
Menüs und Widget-BereicheGeordnete, bearbeitbare Website-Bereiche außerhalb von Eintragsfeldern
Website-EinstellungenGemeinsame Identitäts- und Anzeigewerte wie Titel, Tagline, Logo und Paginierungsgröße
PluginsHooks, Routen, Speicher und optionale Admin-Erweiterungen

Diese Funktionen existieren neben Astro, anstatt es zu ersetzen. Astro steuert weiterhin Routing, Layouts, Rendering, Styles und den Deployment-Adapter.

EmDash und Astro-Sammlungen

Astro-Content-Sammlungen und EmDash-Sammlungen können koexistieren. Verwenden Sie Astro-Sammlungen für Repository-eigene Inhalte und EmDash für Inhalte, die über /_emdash/admin verwaltet werden.

Astro-Content-SammlungEmDash-Sammlung
SpeicherungDateien im ProjektSQL-Datenbank
BearbeitungRepository-WorkflowEmDash-Admin
AbfragegetCollection()getEmDashCollection()
Rich TextMarkdown oder MDXPortable Text
AuslieferungBuild-Time oder Live-LoaderRuntime-Live-Loader

Verwenden Sie beide Sammlungssysteme, wenn die Verantwortung unterschiedlich ist. Beispielsweise kann eine Produktseite von Entwicklern verfasste Release Notes in einer Astro-Content-Sammlung und von Redakteuren verfasste Artikel in EmDash aufbewahren:

---
import { getCollection } from "astro:content";
import { getEmDashCollection } from "emdash";

const [releaseNotes, { entries: articles }] = await Promise.all([
  getCollection("releases"),
  getEmDashCollection("articles", { limit: 3 }),
]);
---

Die beiden Ergebnisse bleiben getrennt. EmDash kopiert dateibasierte Einträge nicht in seine Datenbank.

Eine Site konfigurieren

Die aktuellen Node-Templates konfigurieren Astro für Server-Output, fügen die EmDash-Integration hinzu und verwenden die SQLite- und Local-Storage-Adapter.

Die folgende reduzierte Konfiguration enthält diese erforderlichen Teile:

import node from "@astrojs/node";
import react from "@astrojs/react";
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";

export default defineConfig({
  output: "server",
  adapter: node({ mode: "standalone" }),
  integrations: [
    react(),
    emdash({
      database: sqlite({ url: "file:./data.db" }),
      storage: local({
        directory: "./uploads",
        baseUrl: "/_emdash/api/media/file",
      }),
    }),
  ],
});

EmDash liefert auch Cloudflare-Templates, die für D1 und R2 konfiguriert sind. Starten Sie vom Template für das Deployment-Ziel, anstatt die Node-Adapter von Hand zu übersetzen.

Die Live-Sammlung registrieren

Die Templates stellen EmDash-Inhalte über eine Astro-Live-Sammlung namens _emdash bereit:

import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";

export const collections = {
  _emdash: defineLiveCollection({ loader: emdashLoader() }),
};

getEmDashCollection() und getEmDashEntry() wählen den angeforderten Inhaltstyp über diesen Loader aus.

Sammlungen abfragen

Die folgende Abfrage liest die zuletzt veröffentlichten Beiträge. orderBy verwendet gespeicherte Feldnamen und ordnet jedem Namen "asc" oder "desc" zu:

---
import { getEmDashCollection } from "emdash";

const { entries: posts, error, cacheHint } = await getEmDashCollection("posts", {
  orderBy: { published_at: "desc" },
  limit: 10,
});

if (error) return new Response("Beiträge konnten nicht geladen werden", { status: 500 });
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---

{posts.map((post) => (
  <article>
    <h2><a href={`/posts/${post.id}`}>{post.data.title}</a></h2>
  </article>
))}

Anonyme Abfragen geben veröffentlichte Inhalte zurück. Ein expliziter status-Filter ist nützlich in authentifiziertem oder vorschaufähigem Code. where akzeptiert Inhaltsfelder und Taxonomienamen; siehe Inhalte abfragen für die vollständigen Filter- und Paginierungsformen.

Einen Eintrag abfragen

Übergeben Sie einen Slug oder eine Datenbank-ID an getEmDashEntry(). Die folgende Route verwendet ihren URL-Slug:

---
import { decodeSlug, getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";

const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.redirect("/404");

const { entry: post, error, cacheHint } = await getEmDashEntry("posts", slug);
if (error) return new Response("Beitrag konnte nicht geladen werden", { status: 500 });
if (!post) return Astro.redirect("/404");
if (Astro.cache?.enabled) Astro.cache.set(cacheHint);
---

<article>
  <h1>{post.data.title}</h1>
  <PortableText value={post.data.content} />
</article>

Die zurückgegebene entry.id ist Astros Routen-Bezeichner und ist normalerweise der Slug. Die Datenbank-Inhalts-ID ist entry.data.id. Verwenden Sie data.id mit Hilfsfunktionen, die eine gespeicherte Inhalts-ID erfordern.

Dynamische CMS-Funktionen verwenden

EmDash exportiert Server-Hilfsfunktionen für Daten, die nicht zu einem einzelnen Sammlungseintrag gehören:

---
import { getMenu, getSiteSettings } from "emdash";
import { WidgetArea } from "emdash/ui";

const [menu, settings] = await Promise.all([
  getMenu("primary"),
  getSiteSettings(),
]);
---

<header>
  <a href="/">{settings.title}</a>
  <nav>
    {menu?.items.map((item) => <a href={item.url}>{item.label}</a>)}
  </nav>
</header>

<main><slot /></main>
<aside><WidgetArea name="sidebar" /></aside>

Ein Plugin-Format wählen

Sandboxed und native Plugins haben unterschiedliche Paketstrukturen. Sandboxed Plugins verwenden emdash-plugin.jsonc plus ein standardmäßig exportiertes src/plugin.ts-Objekt. Native Plugins exportieren eine Deskriptor-Factory und createPlugin(), erstellt mit definePlugin().

Lesen Sie Ein Plugin-Format wählen, bevor Sie ein Plugin hinzufügen. Kopieren Sie kein natives definePlugin()-Beispiel in ein Sandboxed-Paket.

Nächste Schritte