Référence des types de champs

Sur cette page

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 :

TypeSQLite ColumnDescription
stringTEXTSaisie de texte court
textTEXTTexte multiligne
urlTEXTValeur URL
numberREALNombre décimal
integerINTEGERNombre entier
booleanINTEGERVrai/faux
datetimeTEXTDate et heure
selectTEXTChoix unique parmi des options
multiSelectJSONChoix multiples
portableTextJSONContenu rich text
imageTEXTRéférence d’image
fileTEXTRéférence de fichier
referencenoneLie des entrées d’une autre collection
jsonJSONDonnées JSON arbitraires
slugTEXTIdentifiant sûr pour URL
repeaterJSONGroupe de champs répétitif
blocksJSONComposition 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ères
  • maxLength — Nombre maximal de caractères
  • pattern — 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ères
  • maxLength — Nombre maximal de caractères
  • pattern — 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 minimale
  • max — 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 minimale
  • max — 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 avec targetCollection, 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é de relation se 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 exige slug, label et type ; elle peut aussi définir required. Un sous-champ select fournit ses choix via options.
  • 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 :

PropertyTypeDescription
slugstringIdentifiant unique (requis)
labelstringNom d’affichage (requis)
typeFieldTypeType de champ (requis)
requiredbooleanExiger une valeur (défaut : false)
uniquebooleanImposer l’unicité (défaut : false)
searchablebooleanInclure le champ dans la recherche plein texte (défaut : false)
indexedbooleanActiver le tri/filtrage indexé
translatablebooleanStocker une valeur par locale (défaut : true)
defaultValueunknownValeur par défaut pour les nouvelles entrées
validationobjectRègles de validation spécifiques au type
widgetstringRemplacement de widget personnalisé
optionsobjectConfiguration du widget
sortOrdernumberOrdre 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 :

  • id
  • slug
  • status
  • author_id
  • primary_byline_id
  • created_at
  • updated_at
  • published_at
  • scheduled_at
  • deleted_at
  • version
  • live_revision_id
  • draft_revision_id
  • terms
  • bylines
  • byline

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",
];