Les collections sont la base du modèle de contenu d’EmDash. Chaque collection représente un type de contenu (articles, pages, produits) et contient des définitions de champs qui déterminent la forme de vos données.
Créer des collections
Créez des collections depuis le panneau d’administration, sous Types de contenu. Chaque collection comporte :
| Propriété | Description |
|---|---|
slug | Identifiant adapté aux URL (ex. posts, products) |
label | Libellé affiché (ex. « Blog Posts ») |
labelSingular | Forme au singulier (ex. « Post ») |
description | Description facultative pour les éditeur·rice·s |
icon | Nom d’icône Lucide pour la barre latérale de l’admin |
supports | Fonctionnalités : brouillons, révisions, aperçu, planification, recherche, SEO |
Fonctionnalités de collection
Lors de la création d’une collection, activez les fonctionnalités nécessaires :
| Fonctionnalité | Description |
|---|---|
drafts | Workflow brouillon/publié |
revisions | Historique du contenu avec instantanés de version |
preview | URL d’aperçu signées pour les brouillons |
scheduling | Planifier une publication à une date ultérieure |
// Exemple de collection avec toutes les fonctionnalités
{
slug: "posts",
label: "Blog Posts",
labelSingular: "Post",
supports: ["drafts", "revisions", "preview", "scheduling"]
}
Types de champs
EmDash prend en charge 15 types de champs, mappés sur des types de colonnes SQLite :
Champs texte
string
Texte court. Mappé sur la colonne TEXT.
{ slug: "title", type: "string", label: "Title" } text
Zone de texte multiligne. Mappée sur la colonne TEXT.
{ slug: "excerpt", type: "text", label: "Excerpt" } slug
Champ d’identifiant URL sécurisé. Mappé sur la colonne TEXT.
{ slug: "handle", type: "slug", label: "URL Handle" } Contenu riche
portableText
Éditeur de texte enrichi (TipTap/ProseMirror). Stocké en JSON.
{ slug: "content", type: "portableText", label: "Content" }Portable Text est un format par blocs qui préserve la structure sans HTML intégré.
json
Données JSON arbitraires. Stockées en JSON.
{ slug: "metadata", type: "json", label: "Custom Metadata" } Nombres
number
Nombres décimaux. Mappés sur la colonne REAL.
{ slug: "price", type: "number", label: "Price" } integer
Entiers. Mappés sur la colonne INTEGER.
{ slug: "quantity", type: "integer", label: "Stock Quantity" } Booléens et dates
boolean
Interrupteur vrai/faux. Mappé sur INTEGER (0/1).
{ slug: "featured", type: "boolean", label: "Featured Post" } datetime
Sélecteur de date et heure. Stocké en chaîne ISO 8601.
{ slug: "eventDate", type: "datetime", label: "Event Date" } Sélection
select
Une option dans une liste. Mappée sur la colonne TEXT.
{
slug: "status",
type: "select",
label: "Product Status",
validation: {
options: ["active", "discontinued", "coming_soon"]
}
} multiSelect
Plusieurs options dans une liste. Stocké en tableau JSON.
{
slug: "features",
type: "multiSelect",
label: "Product Features",
validation: {
options: ["wireless", "waterproof", "eco-friendly"]
}
} Médias et références
image
Sélecteur d’image depuis la médiathèque. Stocke l’ID média en TEXT.
{ slug: "featuredImage", type: "image", label: "Featured Image" } file
Sélecteur de fichier depuis la médiathèque. Stocke l’ID média en TEXT.
{ slug: "attachment", type: "file", label: "PDF Attachment" } reference
Référence vers une entrée d’une autre collection. Stocke l’ID d’entrée en TEXT.
{
slug: "author",
type: "reference",
label: "Author",
options: {
collection: "authors"
}
} Propriétés des champs
Chaque champ prend en charge ces propriétés :
| Propriété | Type | Description |
|---|---|---|
slug | string | Nom de colonne en base |
label | string | Libellé dans l’UI d’admin |
type | FieldType | L’un des 15 types de champs |
required | boolean | Champ obligatoire ou non |
unique | boolean | Valeurs uniques entre les entrées ou non |
defaultValue | unknown | Valeur par défaut pour les nouvelles entrées |
validation | object | Règles de validation propres au type |
widget | string | Identifiant de widget personnalisé |
options | object | Configuration propre au widget |
sortOrder | number | Ordre d’affichage dans l’éditeur |
Règles de validation
L’objet validation varie selon le type de champ :
interface FieldValidation {
required?: boolean; // tous les 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
}
Exemple avec validation :
{
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,}$"
}
}
Options de widget
L’objet options configure le comportement d’UI propre au champ :
interface FieldWidgetOptions {
rows?: number; // text (lignes du textarea)
showPreview?: boolean; // image, file
collection?: string; // reference (collection cible)
allowMultiple?: boolean; // reference (plusieurs références)
[key: string]: unknown; // options de widget personnalisées
}
Exemple de champ de référence :
{
slug: "relatedProducts",
type: "reference",
label: "Related Products",
options: {
collection: "products",
allowMultiple: true
}
}
Interroger les collections
Utilisez les fonctions de requête fournies pour récupérer le contenu. Elles suivent le modèle des collections en direct d’Astro et renvoient des résultats structurés :
import { getEmDashCollection, getEmDashEntry } from "emdash";
// Toutes les entrées — renvoie { entries, error }
const { entries: posts } = await getEmDashCollection("posts");
// Filtrer par statut
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});
// Limiter les résultats
const { entries: recent } = await getEmDashCollection("posts", {
limit: 5,
});
// Filtrer par taxonomie
const { entries: newsPosts } = await getEmDashCollection("posts", {
where: { category: "news" },
});
// Une entrée par slug — renvoie { entry, error, isPreview }
const { entry: post } = await getEmDashEntry("posts", "my-post-slug");
// Gestion des erreurs
const { entries, error } = await getEmDashCollection("posts");
if (error) {
console.error("Failed to load posts:", error);
}
Génération de types
Exécutez npx emdash types pour générer des types TypeScript à partir de votre schéma :
// .emdash/types.ts (généré)
export interface Post {
title: string;
content: PortableTextBlock[];
excerpt?: string;
featuredImage?: string;
author: string; // ID de référence
}
export interface Product {
title: string;
price: number;
description: PortableTextBlock[];
}
Correspondance en base
Les types de champs correspondent aux types de colonnes SQLite :
| Type de champ | Type SQLite | Notes |
|---|---|---|
string | TEXT | |
text | TEXT | |
slug | TEXT | |
number | REAL | flottant 64 bits |
integer | INTEGER | entier signé 64 bits |
boolean | INTEGER | 0 ou 1 |
datetime | TEXT | format ISO 8601 |
select | TEXT | |
multiSelect | JSON | tableau de chaînes |
portableText | JSON | tableau de blocs |
image | TEXT | ID média |
file | TEXT | ID média |
reference | TEXT | ID d’entrée |
json | JSON | JSON arbitraire |
Étapes suivantes
Modèle de contenu
Comprendre l’approche orientée base de données.
Taxonomies
Organiser le contenu avec des catégories et étiquettes.
Médiathèque
Gérer images et fichiers.