EmDash prend en charge 17 types de champs pour définir des schémas de contenu. Chaque type correspond à un type de colonne SQLite et fournit une UI d’administration adaptée.
Aperçu
Le tableau suivant liste chaque type de champ et sa colonne SQLite :
| Type | SQLite Column | Description |
|---|---|---|
string | TEXT | Saisie de texte court |
text | TEXT | Texte multiligne |
url | TEXT | Valeur URL |
number | REAL | Nombre décimal |
integer | INTEGER | Nombre entier |
boolean | INTEGER | Vrai/faux |
datetime | TEXT | Date et heure |
select | TEXT | Choix unique parmi des options |
multiSelect | JSON | Choix multiples |
portableText | JSON | Contenu rich text |
image | TEXT | Référence d’image |
file | TEXT | Référence de fichier |
reference | none | Lie des entrées d’une autre collection |
json | JSON | Données JSON arbitraires |
slug | TEXT | Identifiant sûr pour URL |
repeater | JSON | Groupe de champs répétitif |
blocks | JSON | Composition de page typée |
Types texte
string
Texte court sur une seule ligne. Utilisez-le pour les titres, noms et valeurs brèves.
{
slug: "title",
label: "Title",
type: "string",
required: true,
validation: {
minLength: 1,
maxLength: 200,
},
}
Options de validation :
minLength— Nombre minimal de caractèresmaxLength— Nombre maximal de caractèrespattern— Expression régulière à laquelle la valeur doit correspondre
L’éditeur limite la saisie à maxLength et affiche un compteur de caractères en direct par rapport aux règles de longueur.
Options du widget :
- Aucune spécifique
text
Texte brut multiligne. Utilisez-le pour les descriptions, extraits et texte brut plus long.
{
slug: "excerpt",
label: "Excerpt",
type: "text",
options: {
rows: 3,
},
}
Options de validation :
minLength— Nombre minimal de caractèresmaxLength— Nombre maximal de caractèrespattern— Expression régulière à laquelle la valeur doit correspondre
L’éditeur limite la saisie à maxLength et affiche un compteur de caractères en direct par rapport aux règles de longueur.
Options du widget :
rows— Nombre de lignes dans le textarea (défaut : 3)
url
Une adresse web. L’API de contenu rejette les valeurs qui ne sont pas des URL valides.
{
slug: "website",
label: "Website",
type: "url",
required: true,
}
Les champs URL sont stockés sous forme de texte. Utilisez plutôt un champ string lorsqu’une valeur peut être un chemin relatif comme /about, car les chemins relatifs ne sont pas des valeurs valides pour un champ url.
slug
Texte destiné à contenir une valeur de type slug. Ce type de champ personnalisé ne génère ni ne nettoie sa valeur.
{
slug: "legacy_slug",
label: "Legacy Slug",
type: "slug",
required: true,
unique: true,
}
Chaque entrée de contenu possède déjà un slug système réservé, que EmDash gère séparément pour les URL publiques. Utilisez un champ slug personnalisé uniquement lorsque le modèle de contenu a besoin d’une autre valeur de type slug stockée.
Types numériques
number
Nombre décimal. Utilisez-le pour les prix, notes et mesures.
{
slug: "price",
label: "Price",
type: "number",
required: true,
validation: {
min: 0,
max: 999999.99,
},
}
Options de validation :
min— Valeur minimalemax— Valeur maximale
L’éditeur définit min et max sur la saisie numérique et affiche la plage autorisée en dessous.
Stocké en SQLite REAL (virgule flottante 64 bits).
integer
Nombre entier. Utilisez-le pour les quantités, compteurs et valeurs d’ordre.
{
slug: "quantity",
label: "Quantity",
type: "integer",
defaultValue: 1,
validation: {
min: 0,
max: 1000,
},
}
Options de validation :
min— Valeur minimalemax— Valeur maximale
L’éditeur définit min et max sur la saisie numérique et affiche la plage autorisée en dessous.
Stocké en SQLite INTEGER.
boolean
Vrai ou faux. Utilisez-le pour les bascules et indicateurs.
{
slug: "featured",
label: "Featured",
type: "boolean",
defaultValue: false,
}
Stocké en SQLite INTEGER (0 ou 1).
Date et heure
datetime
Un instant dans le temps. Les écritures API, MCP et CLI doivent inclure Z ou un décalage UTC explicite. L’admin interprète son sélecteur date-heure dans le fuseau horaire configuré sous Settings → General.
{
slug: "publishedAt",
label: "Published At",
type: "datetime",
}
Format de stockage : 2025-01-24T12:00:00.000Z
EmDash convertit l’entrée acceptée en UTC avec des millisecondes à trois chiffres avant de la stocker. Par exemple, 2025-01-24T21:00:00+09:00 est stocké comme 2025-01-24T12:00:00.000Z. Utilisez plutôt un champ string lorsque la valeur est une date de calendrier ou une heure locale d’horloge murale plutôt qu’un instant.
Types de sélection
select
Sélection unique parmi des options prédéfinies.
{
slug: "status",
label: "Status",
type: "select",
required: true,
defaultValue: "draft",
validation: {
options: ["draft", "published", "archived"],
},
}
Options de validation :
options— Tableau optionnel de valeurs autorisées. Fournissez-le pour présenter des choix prédéfinis et rejeter les autres chaînes ; sans lui, la validation accepte n’importe quelle chaîne.
Stocké en TEXT contenant la valeur sélectionnée.
multiSelect
Sélections multiples parmi des options prédéfinies.
{
slug: "tags",
label: "Tags",
type: "multiSelect",
validation: {
options: ["news", "tutorial", "review", "opinion"],
},
}
Options de validation :
options— Tableau optionnel de valeurs autorisées. Fournissez-le pour présenter des choix prédéfinis et rejeter les autres chaînes ; sans lui, la validation accepte n’importe quel tableau de chaînes.
Stocké comme tableau JSON : ["news", "tutorial"]
Contenu enrichi
portableText
Contenu rich text au format Portable Text. Prend en charge les titres, listes, liens, images et blocs personnalisés.
{
slug: "content",
label: "Content",
type: "portableText",
required: true,
}
La valeur est stockée comme un tableau JSON de blocs Portable Text, par exemple :
[
{
"_type": "block",
"style": "normal",
"children": [{ "_type": "span", "text": "Hello world" }]
}
]
Les plugins peuvent ajouter des types de blocs personnalisés (embeds, widgets, etc.) à l’éditeur. Ils apparaissent dans le menu de commandes slash. Le rendu du bloc enregistré sur le site public nécessite un composant Astro d’un plugin natif ou d’un package companion. Voir Composants de rendu Portable Text.
Types média
image
Référence à une image téléversée. Inclut des métadonnées comme les dimensions et le texte alternatif.
{
slug: "featuredImage",
label: "Featured Image",
type: "image",
validation: {
allowedMimeTypes: ["image/jpeg", "image/png"],
},
options: {
darkVariant: true,
},
}
Options du widget :
darkVariant— Propose aux éditeurs un second emplacement pour une image affichée dans les schémas de couleurs sombres (défaut : false). Voir Dark Mode.
Options de validation :
allowedMimeTypes— Liste non vide de types MIME exacts acceptés pour le média sélectionné
La valeur est stockée comme un objet avec la référence média et ses métadonnées :
{
"id": "01HXK5MZSN...",
"src": "/_emdash/api/media/file/01HXK5MZSN...",
"alt": "Description",
"width": 1920,
"height": 1080,
"provider": "local",
"meta": {
"storageKey": "01HXK5MZSN....jpg"
}
}
Avec darkVariant activé, la valeur peut porter la contrepartie sombre sous darkVariant, dans la même forme :
{
"id": "01HXK5MZSN...",
"alt": "Architecture diagram",
"width": 1920,
"height": 1080,
"darkVariant": {
"id": "01HXK5N2QT...",
"width": 1920,
"height": 1080
}
}
file
Référence à un fichier téléversé tel qu’un document ou un PDF.
{
slug: "document",
label: "Document",
type: "file",
validation: {
allowedMimeTypes: ["application/pdf"],
},
}
Options de validation :
allowedMimeTypes— Liste non vide de types MIME exacts acceptés pour le média sélectionné
La valeur est stockée comme une référence de fournisseur avec des métadonnées mises en cache :
{
"id": "01HXK5MZSN...",
"provider": "local",
"filename": "report.pdf",
"mimeType": "application/pdf",
"meta": {
"storageKey": "01HXK5MZSN....pdf"
}
}
url et size, comme les autres champs de métadonnées mises en cache, sont optionnels. Les requêtes de contenu renvoient la
valeur persistée telle quelle et ne l’hydratent pas depuis la médiathèque. Voir
Valeurs fichier et métadonnées actuelles pour les
API de recherche canoniques lorsque vous avez besoin de métadonnées fraîches ou d’une URL spécifique au fournisseur.
Types relationnels
reference
Lie une entrée à des entrées d’une autre collection, et s’affiche comme un sélecteur d’entrées dans l’admin. Ses liens appartiennent à une relation : un objet de schéma qui joint deux collections, nomme chaque côté et limite combien d’entrées chaque côté peut lier. Relations couvre le flux de travail éditeur et admin.
Le champ suivant lie un article à une entrée de la collection authors :
{
slug: "author",
label: "Author",
type: "reference",
required: true,
validation: {
targetCollection: "authors",
multiple: false,
},
}
Validation :
targetCollection— Slug de la collection vers laquelle ce champ lie. Créer le champ crée une relation pour lui.multiple— Autoriser plus d’une entrée liée (défaut : false). À lire uniquement avectargetCollection, car la limite appartient alors à la nouvelle relation.relation— Slug d’une relation existante à laquelle se lier au lieu d’en créer une.relationSide— À quelle extrémité derelationse situe cette collection,"parent"ou"child". À définir uniquement pour une relation dont les deux extrémités sont la même collection, où les deux extrémités correspondent.
Indiquez soit targetCollection, soit relation. Un champ créé à partir de targetCollection devient l’
extrémité parent d’une relation nommée {collection}_{field}, dont le côté enfant prend le libellé du champ et
détient une entrée sauf si multiple est défini. Un champ créé à partir de relation voit cette relation depuis
l’extrémité où se situe sa collection, et la collection à l’autre extrémité est la cible du champ. Une
relation accepte un champ par extrémité, donc un second champ sur la même extrémité est rejeté. Les deux formes
stockent relation, relationSide et targetCollection sur le champ créé, et la collection
cible est fixée ensuite : pour la changer, supprimez le champ et ajoutez-en un nouveau. Renommer le
champ renomme le côté de la relation qu’il voit.
Un champ référence n’ajoute aucune colonne à la table de collection. Ses liens vivent dans
_emdash_content_references, indexés par le groupe de traduction de chaque entrée, de sorte qu’une sélection est partagée
entre les traductions d’une entrée plutôt que définie par locale. Les lectures de contenu renvoient les entrées liées
sous references, indexées par le slug du champ, plutôt que dans data. Dans un template, demandez le champ par
nom — voir Lire les champs référence.
Un champ lié à une relation ne peut pas définir indexed, car il ne stocke aucune colonne à indexer, et la recherche
du site ne le couvre pas.
Champs sans relation
Un champ référence qui ne nomme ni relation ni collection cible conserve une colonne TEXT et
y détient un ID d’entrée :
"01HXK5MZSN..."
Un champ dont options.allowMultiple est défini détient un tableau JSON d’ID d’entrées dans la même colonne :
["01HXK5MZSN...", "01HXK6NATS..."]
La colonne est lue et écrite comme n’importe quelle autre colonne texte, le schéma de collection valide la
valeur comme une chaîne, et le champ peut définir indexed et servir de filtre de liste de contenu. Il s’affiche comme une
zone de texte plutôt qu’un sélecteur.
Pour en faire un sélecteur, ouvrez le champ sous Content Types et choisissez une collection référencée.
EmDash crée la relation, copie les ID d’entrées de la colonne en tant que liens, et efface les indicateurs
searchable et indexed du champ, de sorte que les filtres de liste de contenu et la recherche du site cessent de le couvrir. La
colonne reste en place et n’est plus écrite. Relations
couvre la même étape du côté de l’éditeur.
Un site mis à jour depuis une version antérieure peut conserver des champs dans cet état. Voir Les champs référence se lient aux relations pour ce que la mise à jour lie et ce qu’elle vous laisse à lier.
Types flexibles
json
Données JSON arbitraires. Utilisez-les pour des structures imbriquées complexes, des intégrations tierces ou des données sans schéma fixe.
{
slug: "metadata",
label: "Metadata",
type: "json",
}
Stocké tel quel dans une colonne JSON SQLite.
repeater
Une liste répétitive de lignes structurées. Définissez au moins un sous-champ dans validation.subFields ; les éditeurs peuvent alors ajouter, supprimer, réordonner et modifier des lignes sans saisir de JSON brut.
Le champ suivant stocke une liste de spécifications produit :
{
slug: "specifications",
label: "Specifications",
type: "repeater",
validation: {
minItems: 1,
maxItems: 12,
subFields: [
{ slug: "label", label: "Label", type: "string", required: true },
{ slug: "value", label: "Value", type: "text", required: true },
{ slug: "source", label: "Source", type: "url" },
],
},
}
Les valeurs repeater sont stockées comme un tableau d’objets :
[
{
"label": "Weight",
"value": "1.2 kg",
"source": "https://example.com/specifications"
}
]
Les types de sous-champs autorisés sont string, text, url, number, integer, boolean, datetime, select et image. Les repeaters ne peuvent pas contenir un autre repeater ni un champ complexe comme portableText, reference ou file.
La validation repeater accepte ces propriétés :
subFields— Une ou plusieurs définitions de sous-champs. Chaque définition exigeslug,labelettype; elle peut aussi définirrequired. Un sous-champselectfournit ses choix viaoptions.minItems— Nombre minimal de lignes. Doit être zéro ou plus.maxItems— Nombre maximal de lignes. Doit être un ou plus et ne peut pas être inférieur àminItems.
blocks
Une liste ordonnée de blocs de contenu typés. Chaque type de bloc a ses propres champs et conserve des versions numérotées. Définissez les types de blocs via l’API de schéma, MCP ou un fichier seed avant de les ajouter à un champ de collection.
Le champ suivant permet aux éditeurs de composer une page à partir de blocs hero et call-to-action :
{
slug: "layout",
label: "Layout",
type: "blocks",
validation: {
allowedTypes: ["hero", "call_to_action"],
maxItems: 20,
},
}
Chaque bloc stocké porte son type, sa version et sa clé stable aux côtés des champs déclarés par cette version :
[
{
"_type": "hero",
"_version": 1,
"_key": "01K5AB3F7M9QZ2X8W4V6T1R0YH",
"heading": "Bread made slowly, by hand."
}
]
La validation blocks accepte ces propriétés :
allowedTypes— Slugs de types de blocs ordonnés disponibles pour les nouveaux blocs.retiredTypes— Types de blocs gérés par le serveur conservés pour le contenu stocké mais indisponibles pour les nouveaux blocs.minItems— Nombre minimal de blocs. L’augmenter au-dessus de zéro sur une collection peuplée nécessite une migration de contenu.maxItems— Nombre maximal de blocs, jusqu’à 100.
Un champ blocks est optionnel et vaut par défaut un tableau vide. Il ne peut pas être required, unique, searchable, indexed, ni rendu par un widget de champ personnalisé. Les définitions de blocs peuvent utiliser des champs scalaires, texte, sélection, Portable Text, image, fichier et repeater. Elles ne peuvent pas contenir de références, JSON, slugs ou blocks imbriqués.
Rendez le tableau stocké avec <Blocks value components fallback> depuis emdash/ui. Voir Construire des pages avec des blocks pour des exemples de seed, de carte de composants, de renderer manquant, d’activation et de migration.
Propriétés des champs
Tous les champs prennent en charge ces propriétés communes :
| Property | Type | Description |
|---|---|---|
slug | string | Identifiant unique (requis) |
label | string | Nom d’affichage (requis) |
type | FieldType | Type de champ (requis) |
required | boolean | Exiger une valeur (défaut : false) |
unique | boolean | Imposer l’unicité (défaut : false) |
searchable | boolean | Inclure le champ dans la recherche plein texte (défaut : false) |
indexed | boolean | Activer le tri/filtrage indexé |
translatable | boolean | Stocker une valeur par locale (défaut : true) |
defaultValue | unknown | Valeur par défaut pour les nouvelles entrées |
validation | object | Règles de validation spécifiques au type |
widget | string | Remplacement de widget personnalisé |
options | object | Configuration du widget |
sortOrder | number | Ordre d’affichage dans l’admin |
indexed est disponible pour les champs scalaires : string, url, number, integer, boolean,
datetime, select, reference et slug. Un champ indexé peut être passé comme champ orderBy
ou utilisé dans fieldFilters dans les requêtes de liste de contenu. Évitez d’indexer des champs qui ne servent pas
au tri ou au filtrage car chaque index ajoute du stockage et une surcharge d’écriture.
searchable ajoute le texte du champ à l’index de recherche plein texte de la collection. Définissez translatable: false pour les identifiants, prix, indicateurs et autres valeurs qui doivent rester identiques sur chaque traduction d’une entrée ; lorsqu’une locale modifie un champ non traduisible, EmDash synchronise la valeur vers ses entrées traduites.
Le type blocks n’utilise que slug, label, type, translatable, validation et sortOrder de cet ensemble commun. Son tableau n’est jamais obligatoire au niveau colonne et vaut toujours [] par défaut.
Slugs de champs réservés
Ces slugs sont réservés et ne peuvent pas être utilisés :
idslugstatusauthor_idprimary_byline_idcreated_atupdated_atpublished_atscheduled_atdeleted_atversionlive_revision_iddraft_revision_idtermsbylinesbyline
Types TypeScript
Importez les définitions de types de champs pour une utilisation programmatique :
import type { FieldType, Field, CreateFieldInput } from "emdash";
const fieldTypes: FieldType[] = [
"string",
"text",
"url",
"number",
"integer",
"boolean",
"datetime",
"select",
"multiSelect",
"portableText",
"image",
"file",
"reference",
"json",
"slug",
"repeater",
"blocks",
];