Le collezioni sono alla base del modello di contenuto di EmDash. Ogni collezione rappresenta un tipo di contenuto (post, pagine, prodotti) e contiene definizioni di campi che determinano la forma dei tuoi dati.
Creare collezioni
Crea le collezioni dal pannello di amministrazione in Tipi di contenuto. Ogni collezione ha:
| Proprietà | Descrizione |
|---|---|
slug | Identificatore sicuro per URL (es.: posts, products) |
label | Nome visualizzato (es.: «Blog Posts») |
labelSingular | Forma singolare (es.: «Post») |
description | Descrizione facoltativa per i redattori |
icon | Nome icona Lucide nella barra laterale dell’admin |
supports | Funzionalità come bozze, revisioni, anteprima, pianificazione, ricerca, SEO |
Funzionalità della collezione
Quando crei una collezione, attiva le funzionalità necessarie:
| Funzionalità | Descrizione |
|---|---|
drafts | Flusso bozza/pubblicato |
revisions | Cronologia dei contenuti con snapshot di versione |
preview | URL di anteprima firmate per le bozze |
scheduling | Pianificare la pubblicazione in una data futura |
// Esempio di collezione con tutte le funzionalità
{
slug: "posts",
label: "Blog Posts",
labelSingular: "Post",
supports: ["drafts", "revisions", "preview", "scheduling"]
}
Tipi di campo
EmDash supporta 15 tipi di campo mappati su tipi di colonna SQLite:
Campi di testo
string
Testo breve. Mappato sulla colonna TEXT.
{ slug: "title", type: "string", label: "Title" } text
Area di testo multilinea. Mappata sulla colonna TEXT.
{ slug: "excerpt", type: "text", label: "Excerpt" } slug
Campo identificatore sicuro per URL. Mappato sulla colonna TEXT.
{ slug: "handle", type: "slug", label: "URL Handle" } Contenuto ricco
portableText
Editor di testo ricco (TipTap/ProseMirror). Memorizzato come JSON.
{ slug: "content", type: "portableText", label: "Content" }Portable Text è un formato a blocchi che preserva la struttura senza HTML incorporato.
json
Dati JSON arbitrari. Memorizzati come JSON.
{ slug: "metadata", type: "json", label: "Custom Metadata" } Numeri
number
Numeri decimali. Mappati sulla colonna REAL.
{ slug: "price", type: "number", label: "Price" } integer
Numeri interi. Mappati sulla colonna INTEGER.
{ slug: "quantity", type: "integer", label: "Stock Quantity" } Booleani e date
boolean
Interruttore vero/falso. Mappato su INTEGER (0/1).
{ slug: "featured", type: "boolean", label: "Featured Post" } datetime
Selettore data e ora. Memorizzato come stringa ISO 8601.
{ slug: "eventDate", type: "datetime", label: "Event Date" } Selezione
select
Un’opzione da un elenco. Mappata sulla colonna TEXT.
{
slug: "status",
type: "select",
label: "Product Status",
validation: {
options: ["active", "discontinued", "coming_soon"]
}
} multiSelect
Più opzioni da un elenco. Memorizzato come array JSON.
{
slug: "features",
type: "multiSelect",
label: "Product Features",
validation: {
options: ["wireless", "waterproof", "eco-friendly"]
}
} Media e riferimenti
image
Selettore immagine dalla libreria media. Memorizza l’ID media come TEXT.
{ slug: "featuredImage", type: "image", label: "Featured Image" } file
Selettore file dalla libreria media. Memorizza l’ID media come TEXT.
{ slug: "attachment", type: "file", label: "PDF Attachment" } reference
Riferimento a una voce di un’altra collezione. Memorizza l’ID voce come TEXT.
{
slug: "author",
type: "reference",
label: "Author",
options: {
collection: "authors"
}
} Proprietà dei campi
Ogni campo supporta queste proprietà:
| Proprietà | Tipo | Descrizione |
|---|---|---|
slug | string | Nome colonna nel database |
label | string | Etichetta nell’UI admin |
type | FieldType | Uno dei 15 tipi di campo |
required | boolean | Se il campo deve avere un valore |
unique | boolean | Se i valori devono essere unici tra le voci |
defaultValue | unknown | Valore predefinito per le nuove voci |
validation | object | Regole di validazione specifiche del tipo |
widget | string | Identificatore widget personalizzato |
options | object | Configurazione specifica del widget |
sortOrder | number | Ordine di visualizzazione nell’editor |
Regole di validazione
L’oggetto validation varia in base al tipo di campo:
interface FieldValidation {
required?: boolean; // tutti i tipi
min?: number; // number, integer
max?: number; // number, integer
minLength?: number; // string, text
maxLength?: number; // string, text
pattern?: string; // string (regex)
options?: string[]; // select, multiSelect
}
Esempio con validazione:
{
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,}$"
}
}
Opzioni widget
L’oggetto options configura il comportamento UI specifico del campo:
interface FieldWidgetOptions {
rows?: number; // text (righe del textarea)
showPreview?: boolean; // image, file
collection?: string; // reference (collezione di destinazione)
allowMultiple?: boolean; // reference (riferimenti multipli)
[key: string]: unknown; // opzioni widget personalizzate
}
Esempio di campo di riferimento:
{
slug: "relatedProducts",
type: "reference",
label: "Related Products",
options: {
collection: "products",
allowMultiple: true
}
}
Interrogare le collezioni
Usa le funzioni di query fornite per recuperare i contenuti. Seguono il modello delle live collection di Astro e restituiscono risultati strutturati:
import { getEmDashCollection, getEmDashEntry } from "emdash";
// Tutte le voci — restituisce { entries, error }
const { entries: posts } = await getEmDashCollection("posts");
// Filtrare per stato
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});
// Limitare i risultati
const { entries: recent } = await getEmDashCollection("posts", {
limit: 5,
});
// Filtrare per tassonomia
const { entries: newsPosts } = await getEmDashCollection("posts", {
where: { category: "news" },
});
// Una voce per slug — restituisce { entry, error, isPreview }
const { entry: post } = await getEmDashEntry("posts", "my-post-slug");
// Gestione errori
const { entries, error } = await getEmDashCollection("posts");
if (error) {
console.error("Failed to load posts:", error);
}
Generazione dei tipi
Esegui npx emdash types per generare tipi TypeScript dal tuo schema:
// .emdash/types.ts (generato)
export interface Post {
title: string;
content: PortableTextBlock[];
excerpt?: string;
featuredImage?: string;
author: string; // ID riferimento
}
export interface Product {
title: string;
price: number;
description: PortableTextBlock[];
}
Mappatura nel database
I tipi di campo corrispondono ai tipi di colonna SQLite:
| Tipo di campo | Tipo SQLite | Note |
|---|---|---|
string | TEXT | |
text | TEXT | |
slug | TEXT | |
number | REAL | floating point 64 bit |
integer | INTEGER | intero con segno 64 bit |
boolean | INTEGER | 0 o 1 |
datetime | TEXT | formato ISO 8601 |
select | TEXT | |
multiSelect | JSON | array di stringhe |
portableText | JSON | array di blocchi |
image | TEXT | ID media |
file | TEXT | ID media |
reference | TEXT | ID voce |
json | JSON | JSON arbitrario |
Passi successivi
Modello di contenuto
Capisci l’approccio orientato al database.
Tassonomie
Organizza i contenuti con categorie e tag.
Libreria media
Gestisci immagini e file.