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 sie bietet
AdminBrowserbasierte Verwaltung von Sammlungen, Medien, Menüs, Taxonomien und Einstellungen unter /_emdash/admin
DatenbanksammlungenVon Redakteuren verwaltete Inhalte, die zur Anfragezeit 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 Bereiche der Site außerhalb der Eintragsfelder
Site-EinstellungenGemeinsame Identitäts- und Anzeigewerte wie Titel, Tagline, Logo und Seitengröße der Paginierung
PluginsHooks, Routen, Speicher und optionale Admin-Erweiterungen

Diese Funktionen existieren neben Astro und ersetzen es nicht. Astro steuert weiterhin Routing, Layouts, Rendering, Stile und den Deployment-Adapter.

EmDash und Astro-Sammlungen

Astro-Content-Collections und EmDash-Sammlungen können nebeneinander bestehen. Verwenden Sie Astro-Sammlungen für Inhalte, die dem Repository gehören, und EmDash für Inhalte, die über /_emdash/admin verwaltet werden.

Astro-Content-CollectionEmDash-Sammlung
SpeicherDateien im ProjektSQL-Datenbank
BearbeitungRepository-WorkflowEmDash-Admin
AbfragegetCollection()getEmDashCollection()
Rich TextMarkdown oder MDXPortable Text
AuslieferungBuild-Zeit oder Live-LoaderLaufzeit-Live-Loader

Verwenden Sie beide Sammlungssysteme, wenn die Zuständigkeit unterschiedlich ist. Eine Produkt-Site kann zum Beispiel von Entwicklern verfasste Release Notes in einer Astro-Content-Collection und von Redakteuren verfasste Artikel in EmDash halten:

---
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-Ausgabe, fügen die EmDash-Integration hinzu und verwenden die Adapter für SQLite und lokalen Speicher.

Die folgende reduzierte Konfiguration enthält diese erforderlichen Bestandteile:

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 außerdem Cloudflare-Templates, die für D1 und R2 konfiguriert sind. Beginnen Sie mit dem Template für das Deployment-Ziel, anstatt die Node-Adapter von Hand zu übertragen.

Die Live-Sammlung registrieren

Die Templates stellen EmDash-Inhalte über eine einzige Astro-Live-Collection 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 über diesen Loader den angeforderten Inhaltstyp 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("Could not load posts", { 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 liefern veröffentlichte Inhalte. Ein expliziter status-Filter ist in authentifiziertem oder vorschaufähigem Code nützlich. where akzeptiert Inhaltsfelder und Taxonomienamen; die vollständigen Formen für Filter und Paginierung finden Sie unter Inhalte abfragen.

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.rewrite("/404");

const { entry: post, error, cacheHint } = await getEmDashEntry("posts", slug);
if (error) return new Response("Could not load the post", { status: 500 });
if (!post) return Astro.rewrite("/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 der Routing-Bezeichner von Astro und normalerweise der Slug. Die Inhalts-ID der Datenbank ist entry.data.id. Verwenden Sie data.id mit Hilfsfunktionen, die eine gespeicherte Inhalts-ID benötigen.

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

Sandbox-Plugins und native Plugins haben unterschiedliche Paketstrukturen. Sandbox-Plugins verwenden emdash-plugin.jsonc plus ein als Default exportiertes src/plugin.ts-Objekt. Native Plugins exportieren eine Descriptor-Factory und ein mit definePlugin() erstelltes createPlugin().

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

Nächste Schritte