Formato File Seed

In questa pagina

I file seed sono documenti JSON che inizializzano i siti EmDash. Definiscono collezioni, campi, tassonomie, menu, redirect, aree widget, impostazioni del sito e contenuto di esempio opzionale.

Struttura Root

Un file seed ha la seguente struttura di livello superiore:

{
	"$schema": "https://emdashcms.com/seed.schema.json",
	"version": "1",
	"meta": {},
	"settings": {},
	"collections": [],
	"taxonomies": [],
	"bylines": [],
	"menus": [],
	"redirects": [],
	"widgetAreas": [],
	"sections": [],
	"content": {}
}
CampoTipoRichiestoDescrizione
$schemastringNoURL dello schema JSON per la validazione dell’editor
version"1"Versione del formato seed
metaobjectNoMetadati sul seed
settingsobjectNoImpostazioni del sito
collectionsarrayNoDefinizioni di collezioni
taxonomiesarrayNoDefinizioni di tassonomie
bylinesarrayNoDefinizioni di profili byline
menusarrayNoMenu di navigazione
redirectsarrayNoRegole di redirect
widgetAreasarrayNoDefinizioni di aree widget
sectionsarrayNoBlocchi di contenuto riutilizzabili
contentobjectNoVoci di contenuto di esempio

Meta

L’oggetto meta contiene metadati descrittivi opzionali sul seed:

{
	"meta": {
		"name": "Blog Starter",
		"description": "A simple blog with posts, pages, and categories",
		"author": "EmDash"
	}
}

Settings

L’oggetto settings contiene valori di configurazione a livello di sito:

{
	"settings": {
		"title": "My Site",
		"tagline": "A modern CMS",
		"postsPerPage": 10,
		"dateFormat": "MMMM d, yyyy"
	}
}

Le impostazioni vengono applicate alla tabella options con il prefisso site:. L’Assistente di Configurazione precompilerà title e tagline dal file seed (se fornito), consentendo agli utenti di sovrascriverli durante la configurazione iniziale.

Collections

Ogni definizione di collezione crea un tipo di contenuto nel database:

{
	"collections": [
		{
			"slug": "posts",
			"label": "Posts",
			"labelSingular": "Post",
			"description": "Blog posts",
			"icon": "file-text",
			"supports": ["drafts", "revisions"],
			"fields": [
				{
					"slug": "title",
					"label": "Title",
					"type": "string",
					"required": true
				},
				{
					"slug": "content",
					"label": "Content",
					"type": "portableText"
				},
				{
					"slug": "featured_image",
					"label": "Featured Image",
					"type": "image"
				}
			]
		}
	]
}

Proprietà di Collection

ProprietàTipoRichiestoDescrizione
slugstringIdentificatore sicuro per URL (minuscole, underscore)
labelstringNome visualizzato al plurale
labelSingularstringNoNome visualizzato al singolare
descriptionstringNoDescrizione dell’interfaccia amministrativa
iconstringNoNome dell’icona Lucide
supportsarrayNoFunzionalità: "drafts", "revisions"
fieldsarrayDefinizioni dei campi

Proprietà di Field

ProprietàTipoRichiestoDescrizione
slugstringNome della colonna (minuscole, underscore)
labelstringNome visualizzato
typestringTipo di campo
requiredbooleanNoValidazione: il campo deve avere un valore
uniquebooleanNoValidazione: il valore deve essere univoco
defaultValueanyNoValore predefinito per nuove voci
validationobjectNoRegole di validazione aggiuntive
widgetstringNoOverride del widget dell’interfaccia amministrativa
optionsobjectNoConfigurazione specifica del widget

Tipi di Field

TipoDescrizioneMemorizzato come
stringTesto breveTEXT
textTesto lungo (textarea)TEXT
numberValore numericoREAL
integerNumero interoINTEGER
booleanVero/falsoINTEGER
dateValore di dataTEXT (ISO 8601)
datetimeData e oraTEXT (ISO 8601)
emailIndirizzo emailTEXT
urlURLTEXT
slugStringa sicura per URLTEXT
portableTextContenuto rich textJSON
imageRiferimento immagineJSON
fileRiferimento fileJSON
jsonJSON arbitrarioJSON
referenceRiferimento ad un’altra voceTEXT

Taxonomies

Le tassonomie sono sistemi di classificazione per il contenuto:

{
	"taxonomies": [
		{
			"name": "category",
			"label": "Categories",
			"labelSingular": "Category",
			"hierarchical": true,
			"collections": ["posts"],
			"terms": [
				{ "slug": "news", "label": "News" },
				{ "slug": "tutorials", "label": "Tutorials" },
				{
					"slug": "advanced",
					"label": "Advanced Tutorials",
					"parent": "tutorials"
				}
			]
		},
		{
			"name": "tag",
			"label": "Tags",
			"labelSingular": "Tag",
			"hierarchical": false,
			"collections": ["posts"]
		}
	]
}

Proprietà di Taxonomy

ProprietàTipoRichiestoDescrizione
namestringIdentificatore univoco
labelstringNome visualizzato al plurale
labelSingularstringNoNome visualizzato al singolare
hierarchicalbooleanConsenti termini nidificati (categorie) o piatti (tag)
collectionsarrayCollezioni a cui si applica questa tassonomia
termsarrayNoTermini predefiniti

Proprietà di Term

ProprietàTipoRichiestoDescrizione
slugstringIdentificatore sicuro per URL
labelstringNome visualizzato
descriptionstringNoDescrizione del termine
parentstringNoSlug del termine padre (solo gerarchico)

L’array menus definisce i menu di navigazione modificabili dall’amministratore:

{
	"menus": [
		{
			"name": "primary",
			"label": "Primary Navigation",
			"items": [
				{ "type": "custom", "label": "Home", "url": "/" },
				{ "type": "page", "ref": "about" },
				{ "type": "custom", "label": "Blog", "url": "/posts" },
				{
					"type": "custom",
					"label": "External",
					"url": "https://example.com",
					"target": "_blank"
				}
			]
		}
	]
}

Tipi di Menu Item

TipoDescrizioneCampi richiesti
customURL personalizzatourl
pageLink a una voce di paginaref
postLink a una voce di postref
taxonomyLink a un archivio di tassonomiaref, collection
collectionLink a un archivio di collezionecollection

Proprietà di Menu Item

ProprietàTipoDescrizione
typestringTipo di elemento (vedi sopra)
labelstringTesto visualizzato (auto-generato per ref pagina/post)
urlstringURL personalizzato (per tipo custom)
refstringID contenuto nel seed (per tipi page/post)
collectionstringSlug di collezione
targetstring"_blank" per nuova finestra
titleAttrstringAttributo title HTML
cssClassesstringClassi CSS personalizzate
childrenarrayElementi di menu nidificati

Bylines

I profili byline sono separati dalla proprietà (author_id). Definisci identità byline riutilizzabili una volta, quindi fai riferimento ad esse dalle voci di contenuto.

{
	"bylines": [
		{
			"id": "editorial",
			"slug": "emdash-editorial",
			"displayName": "EmDash Editorial"
		},
		{
			"id": "guest",
			"slug": "guest-contributor",
			"displayName": "Guest Contributor",
			"isGuest": true
		}
	]
}
ProprietàTipoRichiestoDescrizione
idstringID locale del seed usato da content[].bylines
slugstringSlug byline sicuro per URL
displayNamestringNome mostrato in template e API
biostringNoBiografia del profilo opzionale
websiteUrlstringNoURL del sito web opzionale
isGuestbooleanNoContrassegna byline come profilo ospite

Redirects

L’array redirects definisce le regole di redirect che preservano gli URL legacy dopo la migrazione:

{
	"redirects": [
		{ "source": "/old-about", "destination": "/about" },
		{ "source": "/legacy-feed", "destination": "/rss.xml", "type": 308 },
		{
			"source": "/category/news",
			"destination": "/categories/news",
			"groupName": "migration"
		}
	]
}

Proprietà di Redirect

ProprietàTipoRichiestoDescrizione
sourcestringPercorso sorgente (deve iniziare con /)
destinationstringPercorso di destinazione (deve iniziare con /)
typenumberNoStato HTTP: 301, 302, 307 o 308
enabledbooleanNoSe il redirect è attivo (predefinito: true)
groupNamestringNoEtichetta di raggruppamento opzionale per filtro/ricerca admin

Widget Areas

L’array widgetAreas definisce regioni di contenuto configurabili:

{
	"widgetAreas": [
		{
			"name": "sidebar",
			"label": "Main Sidebar",
			"description": "Appears on blog posts and pages",
			"widgets": [
				{
					"type": "component",
					"title": "Recent Posts",
					"componentId": "core:recent-posts",
					"props": { "count": 5 }
				},
				{
					"type": "menu",
					"title": "Quick Links",
					"menuName": "footer"
				},
				{
					"type": "content",
					"title": "About",
					"content": [
						{
							"_type": "block",
							"style": "normal",
							"children": [{ "_type": "span", "text": "Welcome to our site!" }]
						}
					]
				}
			]
		}
	]
}

Tipi di Widget

TipoDescrizioneCampi richiesti
contentContenuto rich textcontent (Portable Text)
menuRenderizza un menumenuName
componentComponente registratocomponentId

Componenti Integrati

ID componenteDescrizione
core:recent-postsElenco di post recenti
core:categoriesElenco di categorie
core:tagsTag cloud
core:searchForm di ricerca
core:archivesArchivi mensili

Sections

Le sezioni sono blocchi di contenuto riutilizzabili che gli editor inseriscono nei campi Portable Text tramite il comando slash /section:

{
	"sections": [
		{
			"slug": "hero-centered",
			"title": "Centered Hero",
			"description": "Full-width hero with centered heading and CTA button",
			"keywords": ["hero", "banner", "header", "landing"],
			"content": [
				{
					"_type": "block",
					"style": "h1",
					"children": [{ "_type": "span", "text": "Welcome to Our Site" }]
				},
				{
					"_type": "block",
					"children": [
						{ "_type": "span", "text": "Your compelling tagline goes here." }
					]
				}
			]
		}
	]
}

Proprietà di Section

ProprietàTipoRichiestoDescrizione
slugstringIdentificatore sicuro per URL
titlestringNome visualizzato mostrato nel selettore di sezioni
descriptionstringNoSpiega quando usare questa sezione
keywordsarrayNoTermini di ricerca per trovare la sezione
contentarrayBlocchi Portable Text
sourcestringNo"theme" (predefinito per i seed) o "import"

Le sezioni dai file seed sono contrassegnate con source: "theme" e non possono essere eliminate dall’interfaccia amministrativa. Gli editor possono creare le proprie sezioni (source: "user") e inserire qualsiasi tipo di sezione durante la modifica del contenuto.

Content

L’oggetto content contiene voci di contenuto di esempio organizzate per collezione:

{
	"content": {
		"posts": [
			{
				"id": "hello-world",
				"slug": "hello-world",
				"status": "published",
				"bylines": [
					{ "byline": "editorial" },
					{ "byline": "guest", "roleLabel": "Guest essay" }
				],
				"data": {
					"title": "Hello World",
					"content": [
						{
							"_type": "block",
							"style": "normal",
							"children": [{ "_type": "span", "text": "Welcome!" }]
						}
					],
					"excerpt": "Your first post."
				},
				"taxonomies": {
					"category": ["news"],
					"tag": ["welcome", "first-post"]
				}
			}
		],
		"pages": [
			{
				"id": "about",
				"slug": "about",
				"status": "published",
				"data": {
					"title": "About Us",
					"content": [
						{
							"_type": "block",
							"style": "normal",
							"children": [{ "_type": "span", "text": "About page content." }]
						}
					]
				}
			}
		]
	}
}

Proprietà di Content Entry

ProprietàTipoRichiestoDescrizione
idstringID locale del seed per riferimenti
slugstringSlug URL
statusstringNo"published" o "draft" (predefinito: "published")
dataobjectValori dei campi
bylinesarrayNoCrediti byline ordinati (byline, opzionale roleLabel)
taxonomiesobjectNoAssegnazioni di termini per nome di tassonomia

Content References

Fai riferimento ad altre voci di contenuto usando il prefisso $ref::

{
	"data": {
		"related_posts": ["$ref:another-post", "$ref:third-post"]
	}
}

Il prefisso $ref: risolve gli ID del seed in ID del database durante il seeding.

Media References

Includere immagini da URL:

{
	"data": {
		"featured_image": {
			"$media": {
				"url": "https://images.unsplash.com/photo-xxx",
				"alt": "Description of the image",
				"filename": "hero.jpg",
				"caption": "Photo by Someone"
			}
		}
	}
}

Includere immagini locali da .emdash/media/:

{
	"data": {
		"featured_image": {
			"$media": {
				"file": "hero.jpg",
				"alt": "Description of the image"
			}
		}
	}
}

Proprietà di Media

ProprietàTipoRichiestoDescrizione
urlstringSì*URL remoto da scaricare
filestringSì*Nome file locale in .emdash/media/
altstringNoTesto alternativo per l’accessibilità
filenamestringNoSovrascrivere il nome file
captionstringNoDidascalia del media

*È richiesto url o file, non entrambi.

Applying Seeds Programmatically

Usa l’API seed per strumenti CLI o script:

import { applySeed, validateSeed } from "emdash/seed";
import seedData from "./.emdash/seed.json";

// Prima valida
const validation = validateSeed(seedData);
if (!validation.valid) {
	console.error(validation.errors);
	process.exit(1);
}

// Applica il seed
const result = await applySeed(db, seedData, {
	includeContent: true,
	onConflict: "skip",
	storage: myStorage,
	baseUrl: "http://localhost:4321",
});

console.log(result);
// {
//   collections: { created: 2, skipped: 0 },
//   fields: { created: 8, skipped: 0 },
//   taxonomies: { created: 2, terms: 5 },
//   bylines: { created: 2, skipped: 0 },
//   menus: { created: 1, items: 4 },
//   redirects: { created: 3, skipped: 0 },
//   widgetAreas: { created: 1, widgets: 3 },
//   settings: { applied: 3 },
//   content: { created: 3, skipped: 0 },
//   media: { created: 2, skipped: 0 }
// }

Opzioni Apply

OpzioneTipoPredefinitoDescrizione
includeContentbooleanfalseCreare voci di contenuto di esempio
onConflictstring"skip""skip", "update" o "error"
mediaBasePathstringPercorso base per i file media locali
storageStorageAdapter di storage per caricamenti media
baseUrlstringURL base per URL media

Idempotency

Il seeding è sicuro da eseguire più volte. Comportamento di conflitto per tipo di entità:

EntitàComportamento
CollectionSalta se esiste lo slug
FieldSalta se esiste collection + slug
Definizione tassonomiaSalta se esiste il nome
Termine tassonomiaSalta se esiste nome + slug
Profilo bylineSalta se esiste lo slug
MenuSalta se esiste il nome
Elementi menuSostituisci tutti (il menu viene ricreato)
RedirectSalta se esiste la sorgente
Area widgetSalta se esiste il nome
WidgetsSostituisci tutti (l’area viene ricreata)
SezioneSalta se esiste lo slug
ImpostazioniAggiorna (le impostazioni sono destinate a cambiare)
ContenutoSalta se esiste lo slug nella collezione

Validation

I file seed sono validati prima dell’applicazione:

import { validateSeed } from "emdash/seed";

const { valid, errors, warnings } = validateSeed(seedData);

if (!valid) {
	errors.forEach((e) => console.error(e));
}

warnings.forEach((w) => console.warn(w));

La validazione verifica che:

  • I campi richiesti siano presenti
  • Gli slug siano validi per il loro tipo (gli slug di collection e field consentono lettere minuscole, cifre e underscore; altri slug consentono anche trattini)
  • I tipi di campo siano validi
  • I riferimenti puntino a contenuto esistente
  • I genitori di termini gerarchici esistano
  • I percorsi di redirect siano URL locali sicuri
  • Le sorgenti di redirect siano univoche
  • Non ci siano slug duplicati all’interno delle collezioni

CLI Commands

Il file seed a .emdash/seed.json, package.json#emdash.seed o seed/seed.json viene integrato nella build e applicato alla prima richiesta quando il database è vuoto. Per esportare lo schema di un sito esistente (e opzionalmente il suo contenuto) come file seed:

# `mkdir -p` perché .emdash/ potrebbe non esistere ancora su un progetto nuovo
mkdir -p .emdash

# Esporta lo schema corrente come file seed
npx emdash export-seed > .emdash/seed.json

# Esporta con il contenuto
npx emdash export-seed --with-content > .emdash/seed.json

Next Steps