EmDash è configurato attraverso due file: astro.config.mjs per l’integrazione e src/live.config.ts per le collezioni di contenuto.
Integrazione Astro
Configura EmDash come integrazione Astro in astro.config.mjs:
import { defineConfig } from "astro/config";
import emdash, { local, s3 } from "emdash/astro";
import { sqlite, libsql } from "emdash/db";
export default defineConfig({
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
plugins: [],
}),
],
});
Opzioni di integrazione
database
Richiesto. Configurazione dell’adattatore database. Scegli un adattatore:
// SQLite (Node.js)
database: sqlite({ url: "file:./data.db" });
// PostgreSQL
database: postgres({ connectionString: process.env.DATABASE_URL });
// libSQL
database: libsql({
url: process.env.LIBSQL_DATABASE_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
});
// Cloudflare D1 (importare da @emdash-cms/cloudflare)
database: d1({ binding: "DB" });
Vedi Opzioni Database per dettagli.
storage
Richiesto. Configurazione dell’adattatore di archiviazione media. Scegli un adattatore:
// File system locale (sviluppo)
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
});
// Binding R2 (Cloudflare Workers)
storage: r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev", // opzionale
});
// Compatibile S3 (qualsiasi piattaforma)
storage: s3()
// O con valori espliciti
storage: s3({
endpoint: "https://s3.amazonaws.com",
bucket: "my-bucket",
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
region: "us-east-1", // opzionale, predefinito: "auto"
publicUrl: "https://cdn.example.com", // opzionale
});
Vedi Opzioni di Archiviazione per dettagli.
objectCache
Opzionale. Memorizza nella cache i risultati delle query di contenuto e configurazione in un archivio chiave/valore. Disabilitato quando omesso. Scegli un adattatore:
// Cloudflare KV (condiviso tra tutti gli isolate)
import { kvCache } from "@emdash-cms/cloudflare";
objectCache: kvCache({ binding: "CACHE" });
// In memoria (Node.js / sviluppo)
import { memoryCache } from "emdash/astro";
objectCache: memoryCache();
Vedi Object Cache per configurazione e opzioni.
plugins
Opzionale. Array di plugin EmDash:
import seoPlugin from "@emdash-cms/plugin-seo";
plugins: [seoPlugin()];
fonts
Opzionale. Configurazione dei font dell’interfaccia di amministrazione.
Per impostazione predefinita, EmDash carica Noto Sans tramite l’API Font di Astro. I font vengono scaricati da Google al momento della compilazione e auto-ospitati. Il font base copre gli script latino, cirillico, greco, devanagari e vietnamita.
Per aggiungere supporto per sistemi di scrittura aggiuntivi, passa i nomi degli script:
emdash({
fonts: {
scripts: ["arabic", "japanese"],
},
})
Gli script disponibili sono arabic, armenian, bengali, chinese-simplified, chinese-traditional, chinese-hongkong, devanagari, ethiopic, farsi, georgian, gujarati, gurmukhi, hebrew, japanese, kannada, khmer, korean, lao, malayalam, myanmar, oriya, sinhala, tamil, telugu, thai e tibetan.
Imposta a false per disabilitare completamente l’iniezione dei font e usare i font di sistema:
emdash({
fonts: false,
})
Il CSS admin utilizza la variabile CSS --font-emdash.
auth
Opzionale. Un adattatore di autenticazione. Il login integrato di EmDash utilizza le passkey; impostare auth le sostituisce con un provider esterno. L’adattatore Cloudflare Access, access(), è fornito da @emdash-cms/cloudflare:
import { access } from "@emdash-cms/cloudflare";
emdash({
auth: access({
teamDomain: "myteam.cloudflareaccess.com",
audience: "your-app-audience-tag",
roleMapping: {
Admins: 50,
Editors: 40,
},
}),
});
Opzioni per access():
| Opzione | Tipo | Predefinito | Descrizione |
|---|---|---|---|
teamDomain | string | richiesto | Il tuo dominio team di Cloudflare Access |
audience | string | — | Tag Application Audience (AUD). Su Workers, preferisci audienceEnvVar. |
audienceEnvVar | string | "CF_ACCESS_AUDIENCE" | Variabile d’ambiente da cui leggere il tag audience a runtime |
autoProvision | boolean | true | Creare un utente EmDash al primo login |
defaultRole | number | 30 | Livello di ruolo per utenti non mappati da roleMapping |
syncRoles | boolean | false | Riapplicare roleMapping a ogni login invece che solo al provisioning |
roleMapping | object | — | Mappare nomi di gruppi IdP ai livelli di ruolo EmDash; prima corrispondenza vince |
authProviders
Opzionale. Un array di provider di login collegabili (livello superiore, accanto a auth):
import { github } from "emdash/auth/providers/github";
import { google } from "emdash/auth/providers/google";
import { atproto } from "@emdash-cms/auth-atproto";
emdash({
authProviders: [github(), google(), atproto()],
});
Provider integrati:
github()— leggeEMDASH_OAUTH_GITHUB_CLIENT_ID/EMDASH_OAUTH_GITHUB_CLIENT_SECRET.google()— leggeEMDASH_OAUTH_GOOGLE_CLIENT_ID/EMDASH_OAUTH_GOOGLE_CLIENT_SECRET.atproto()— Login account Atmosphere (Bluesky e la rete AT Protocol). Nessuna variabile d’ambiente necessaria. Accetta{ allowedDIDs, allowedHandles, defaultRole }. Vedi la guida login Atmosphere.
siteUrl
Opzionale. L’origine pubblica lato browser per il sito (schema + host + porta opzionale, nessun percorso).
Dietro un proxy inverso che termina TLS, Astro.url restituisce l’indirizzo interno (http://localhost:4321) invece di quello pubblico (https://cms.example.com). Questo rompe passkey, CSRF, redirect OAuth, redirect login, scoperta MCP, export snapshot, sitemap, robots.txt e dati strutturati JSON-LD. Imposta siteUrl per risolvere tutto in una volta.
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
siteUrl: "https://cms.example.com",
});
Quando siteUrl non è impostato nella configurazione, EmDash controlla le variabili d’ambiente nell’ordine: EMDASH_SITE_URL, poi SITE_URL.
Su Cloudflare Workers, il fallback della variabile d’ambiente legge process.env, che è vuoto a meno che il flag di compatibilità nodejs_compat_populate_process_env sia abilitato:
// wrangler.jsonc
{
"compatibility_flags": ["nodejs_compat", "nodejs_compat_populate_process_env"],
"vars": { "EMDASH_SITE_URL": "https://cms.example.com" },
}
Verifica passkey multi-origine
siteUrl definisce un singolo origine canonico. Dichiara origini aggiuntivi accettati tramite allowedOrigins in astro.config.mjs o la variabile d’ambiente EMDASH_ALLOWED_ORIGINS:
emdash({
siteUrl: "https://example.com",
allowedOrigins: ["https://preview.example.com"],
})
EMDASH_SITE_URL=https://example.com
EMDASH_ALLOWED_ORIGINS=https://preview.example.com,https://staging.example.com
Configurazione proxy inverso
Astro riflette X-Forwarded-* solo quando l’host pubblico è consentito. Configura security.allowedDomains per il nome host che i tuoi utenti utilizzano.
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
export default defineConfig({
security: {
allowedDomains: [
{ hostname: "cms.example.com", protocol: "https" },
{ hostname: "cms.example.com", protocol: "http" },
],
},
vite: {
server: {
allowedHosts: ["cms.example.com"],
},
},
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
siteUrl: "https://cms.example.com",
}),
],
});
trustedProxyHeaders
Opzionale. Header di cui fidarsi per la risoluzione dell’IP client dietro un proxy inverso. Usato dai limiti di frequenza auth e dall’endpoint pubblico dei commenti.
emdash({
database: sqlite({ url: "file:./data.db" }),
trustedProxyHeaders: ["x-real-ip"],
});
maxUploadSize
Opzionale. Dimensione massima consentita per il caricamento di file multimediali in byte. Predefinito 52_428_800 (50 MB):
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
maxUploadSize: 100 * 1024 * 1024, // 100 MB
});
toolbar
Opzionale. Controlla come viene consegnata la barra degli strumenti dell’editor. Predefinito "server".
| Valore | Comportamento |
|---|---|
"server" (predefinito) | La barra degli strumenti viene iniettata lato server in ogni risposta HTML per un editor autenticato. |
"client" | L’HTML pubblico è identico per ogni visitatore. Un piccolo script bootstrap mostra una pillola “Edit”. |
false | Non rendere mai la barra degli strumenti. |
emdash({
toolbar: "client",
})
experimental
Opzionale. Funzionalità opt-in il cui comportamento può cambiare in una release minore.
experimental.registry
Opzionale. Punta i flussi di navigazione e installazione plugin del dashboard admin a un registro plugin federato.
emdash({
sandboxRunner: "@emdash-cms/sandbox-cloudflare",
experimental: {
registry: {
aggregatorUrl: "https://registry.emdashcms.com",
acceptLabelers: "did:plc:emdashverification",
policy: {
minimumReleaseAge: "48h",
minimumReleaseAgeExclude: ["did:plc:yourfirstpartydid"],
},
},
},
});
Adattatori database
import { sqlite, libsql, postgres } from "emdash/db";
sqlite(config)
| Opzione | Tipo | Descrizione |
|---|---|---|
url | string | Percorso file con prefisso file: |
libsql(config)
| Opzione | Tipo | Descrizione |
|---|---|---|
url | string | URL del database |
authToken | string | Token di auth (opzionale per file locali) |
postgres(config)
| Opzione | Tipo | Descrizione |
|---|---|---|
connectionString | string | URL di connessione PostgreSQL |
host | string | Host del database |
port | number | Porta del database |
database | string | Nome del database |
user | string | Utente del database |
password | string | Password del database |
ssl | boolean | Abilitare SSL |
pool.min | number | Dimensione minima del pool (predefinito: 0) |
pool.max | number | Dimensione massima del pool (predefinito: 10) |
d1(config)
Cloudflare D1. Importare da @emdash-cms/cloudflare.
| Opzione | Tipo | Predefinito | Descrizione |
|---|---|---|---|
binding | string | — | Nome del binding D1 da wrangler.jsonc |
session | string | "disabled" | Modalità di replicazione lettura: "disabled", "auto" o "primary-first" |
bookmarkCookie | string | "__em_d1_bookmark" | Nome cookie per i segnalibri di sessione |
Adattatori di archiviazione
import emdash, { local, s3 } from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";
local(config)
| Opzione | Tipo | Descrizione |
|---|---|---|
directory | string | Percorso della directory |
baseUrl | string | URL base per servire i file |
r2(config)
| Opzione | Tipo | Descrizione |
|---|---|---|
binding | string | Nome del binding R2 |
publicUrl | string | URL pubblica opzionale |
s3(config?)
Archiviazione compatibile S3. Tutti i campi sono opzionali.
Prerequisito: installa @aws-sdk/client-s3 e @aws-sdk/s3-request-presigner.
| Opzione | Tipo | Descrizione |
|---|---|---|
endpoint | string | URL endpoint S3 (S3_ENDPOINT) |
bucket | string | Nome bucket (S3_BUCKET) |
accessKeyId | string | Chiave di accesso (S3_ACCESS_KEY_ID) |
secretAccessKey | string | Chiave segreta (S3_SECRET_ACCESS_KEY) |
region | string | Regione, predefinito "auto" (S3_REGION) |
publicUrl | string | URL CDN opzionale (S3_PUBLIC_URL) |
Adattatori di object cache
kvCache(config)
Backend Cloudflare KV. Importare da @emdash-cms/cloudflare.
kvCache({
binding: "CACHE",
defaultTtl: 3600,
revalidate: 1000,
timeout: 2000,
keyPrefix: "em",
})
memoryCache(config?)
Backend in-process per Node.js. Importare da emdash/astro.
memoryCache({
defaultTtl: 3600,
revalidate: 1000,
maxEntries: 1000,
keyPrefix: "em",
})
Collezioni live
import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";
export const collections = {
_emdash: defineLiveCollection({
loader: emdashLoader(),
}),
};
Opzioni del loader
La funzione emdashLoader() non accetta argomenti:
emdashLoader();
Variabili d’ambiente
| Variabile | Descrizione |
|---|---|
EMDASH_SITE_URL | Origine pubblica lato browser (ricade su SITE_URL) |
EMDASH_ALLOWED_ORIGINS | Lista separata da virgole di origini aggiuntivi accettati dalla verifica passkey. |
EMDASH_DATABASE_URL | Sovrascrivere l’URL del database |
EMDASH_ENCRYPTION_KEY | Chiave per cifrare i segreti dei plugin a riposo. |
EMDASH_PREVIEW_SECRET | Sostituzione opzionale per il segreto HMAC di anteprima. |
EMDASH_IP_SALT | Sostituzione opzionale per il salt dell’hash IP del commentatore. |
EMDASH_AUTH_SECRET | Legacy. Usato come sorgente di salt IP se impostato. |
EMDASH_TURNSTILE_SECRET_KEY | Chiave segreta Cloudflare Turnstile. |
EMDASH_URL | URL EmDash remota per la sincronizzazione dello schema |
npx emdash secrets generate
Configurazione package.json
{
"emdash": {
"label": "My Blog Template",
"seed": ".emdash/seed.json",
"url": "https://my-site.pages.dev"
}
}
Configurazione TypeScript
{
"compilerOptions": {
"paths": {
"@emdash-cms/types": ["./.emdash/types.ts"]
}
}
}
npx emdash types