Modelo de Conteúdo
Compreenda a abordagem database-first.
As coleções são a base do modelo de conteúdo do EmDash. Cada coleção representa um tipo de conteúdo (posts, páginas, produtos) e contém definições de campos que determinam a estrutura dos seus dados.
Crie coleções através do painel administrativo em Tipos de Conteúdo. Cada coleção possui:
| Propriedade | Descrição |
|---|---|
slug | Identificador seguro para URL (ex.: posts, products) |
label | Nome de exibição (ex.: “Blog Posts”) |
labelSingular | Forma singular (ex.: “Post”) |
description | Descrição opcional para editores |
icon | Nome do ícone Lucide para a barra lateral administrativa |
supports | Recursos como rascunhos, revisões, pré-visualização, agendamento, busca, seo |
Ao criar uma coleção, habilite os recursos que você precisa:
| Recurso | Descrição |
|---|---|
drafts | Habilita o fluxo de trabalho rascunho/publicado |
revisions | Rastreia o histórico de conteúdo com snapshots de versão |
preview | Gera URLs de pré-visualização assinadas para conteúdo em rascunho |
scheduling | Agenda conteúdo para publicação em uma data futura |
// Example collection with all features enabled{ slug: "posts", label: "Blog Posts", labelSingular: "Post", supports: ["drafts", "revisions", "preview", "scheduling"]}O EmDash suporta 15 tipos de campo que mapeiam para tipos de coluna SQLite:
Entrada de texto curto. Mapeia para coluna TEXT.
{ slug: "title", type: "string", label: "Title" }Área de texto multi-linha. Mapeia para coluna TEXT.
{ slug: "excerpt", type: "text", label: "Excerpt" }Campo de slug seguro para URL. Mapeia para coluna TEXT.
{ slug: "handle", type: "slug", label: "URL Handle" }Editor de texto rico (TipTap/ProseMirror). Armazenado como JSON.
{ slug: "content", type: "portableText", label: "Content" }Portable Text é um formato baseado em blocos que preserva a estrutura sem incorporar HTML.
Dados JSON arbitrários. Armazenado como JSON.
{ slug: "metadata", type: "json", label: "Custom Metadata" }Números decimais. Mapeia para coluna REAL.
{ slug: "price", type: "number", label: "Price" }Números inteiros. Mapeia para coluna INTEGER.
{ slug: "quantity", type: "integer", label: "Stock Quantity" }Alternador verdadeiro/falso. Mapeia para INTEGER (0/1).
{ slug: "featured", type: "boolean", label: "Featured Post" }Seletor de data e hora. Armazenado como string ISO 8601.
{ slug: "eventDate", type: "datetime", label: "Event Date" }Opção única de uma lista. Mapeia para coluna TEXT.
{ slug: "status", type: "select", label: "Product Status", validation: { options: ["active", "discontinued", "coming_soon"] }}Múltiplas opções de uma lista. Armazenado como array JSON.
{ slug: "features", type: "multiSelect", label: "Product Features", validation: { options: ["wireless", "waterproof", "eco-friendly"] }}Seletor de imagem da biblioteca de mídia. Armazena ID da mídia como TEXT.
{ slug: "featuredImage", type: "image", label: "Featured Image" }Seletor de arquivo da biblioteca de mídia. Armazena ID da mídia como TEXT.
{ slug: "attachment", type: "file", label: "PDF Attachment" }Referência a uma entrada de outra coleção. Armazena ID da entrada como TEXT.
{ slug: "author", type: "reference", label: "Author", options: { collection: "authors" }}Cada campo suporta estas propriedades:
| Propriedade | Tipo | Descrição |
|---|---|---|
slug | string | Nome da coluna no banco de dados |
label | string | Rótulo de exibição na interface administrativa |
type | FieldType | Um dos 15 tipos de campo |
required | boolean | Se o campo deve ter um valor |
unique | boolean | Se os valores devem ser únicos entre as entradas |
defaultValue | unknown | Valor padrão para novas entradas |
validation | object | Regras de validação específicas do tipo |
widget | string | Identificador de widget personalizado |
options | object | Configuração específica do widget |
sortOrder | number | Ordem de exibição no editor |
O objeto validation varia de acordo com o tipo de campo:
interface FieldValidation { required?: boolean; // All 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}Exemplo com validação:
{ 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,}$" }}O objeto options configura o comportamento específico da interface do campo:
interface FieldWidgetOptions { rows?: number; // text (textarea rows) showPreview?: boolean; // image, file collection?: string; // reference (target collection) allowMultiple?: boolean; // reference (multiple refs) [key: string]: unknown; // Custom widget options}Exemplo de campo de referência:
{ slug: "relatedProducts", type: "reference", label: "Related Products", options: { collection: "products", allowMultiple: true }}Use as funções de consulta fornecidas para buscar conteúdo. Elas seguem o padrão de coleções ao vivo do Astro, retornando resultados estruturados:
import { getEmDashCollection, getEmDashEntry } from "emdash";
// Obtém todas as entradas - retorna { entries, error }const { entries: posts } = await getEmDashCollection("posts");
// Filtra por statusconst { entries: drafts } = await getEmDashCollection("posts", { status: "draft",});
// Limitar resultadosconst { entries: recent } = await getEmDashCollection("posts", { limit: 5,});
// Filtrar por taxonomiaconst { entries: newsPosts } = await getEmDashCollection("posts", { where: { category: "news" },});
// Obter uma entrada única por slug - retorna { entry, error, isPreview }const { entry: post } = await getEmDashEntry("posts", "my-post-slug");
// Lidar com errosconst { entries, error } = await getEmDashCollection("posts");if (error) { console.error("Failed to load posts:", error);}Execute npx emdash types para gerar tipos TypeScript a partir do seu esquema:
// .emdash/types.ts (generated)export interface Post { title: string; content: PortableTextBlock[]; excerpt?: string; featuredImage?: string; author: string; // reference ID}
export interface Product { title: string; price: number; description: PortableTextBlock[];}Os tipos de campo mapeiam para tipos de coluna SQLite:
| Tipo de Campo | Tipo SQLite | Notas |
|---|---|---|
string | TEXT | |
text | TEXT | |
slug | TEXT | |
number | REAL | Ponto flutuante 64-bit |
integer | INTEGER | Inteiro com sinal 64-bit |
boolean | INTEGER | 0 ou 1 |
datetime | TEXT | Formato ISO 8601 |
select | TEXT | |
multiSelect | JSON | Array de strings |
portableText | JSON | Array de blocos |
image | TEXT | ID da mídia |
file | TEXT | ID da mídia |
reference | TEXT | ID da entrada |
json | JSON | JSON arbitrário |
Modelo de Conteúdo
Compreenda a abordagem database-first.
Taxonomias
Organize conteúdo com categorias e tags.
Biblioteca de Mídia
Gerencie imagens e arquivos.