콘텐츠 모델

이 페이지

콘텐츠 모델은 사이트가 저장하는 컬렉션과 필드의 집합입니다. 관리 패널이나 CLI에서 정의하고, 필요할 때 변경하며, 선택적으로 TypeScript 타입을 생성할 수 있습니다. 이 페이지에서는 사용 방법을 다룹니다.

컬렉션과 필드

컬렉션은 콘텐츠 유형입니다(게시물, 제품, 저자). 각 컬렉션에는 정의한 필드가 있습니다(제목, 본문, 가격). 모든 항목에는 EmDash가 관리하는 시스템 필드도 있습니다.

Content Types의 관리 패널에서 시각적으로 컬렉션과 필드를 생성하고 편집하거나 CLI를 사용할 수 있습니다. 변경 사항은 즉시 적용되며 개발자가 아닌 사람도 수행할 수 있습니다.

시스템 필드

정의한 필드 외에도 모든 항목에는 다음 필드가 항상 존재합니다:

필드목적
id안정적인 고유 식별자
slugURL 안전 식별자, 로케일별로 고유
statusdraft, published 또는 scheduled
author_id항목을 생성한 사용자
created_at / updated_at / published_at타임스탬프
deleted_at소프트 삭제 시 설정됨, 행은 유지됨
version저장할 때마다 증가

항목 삭제는 소프트 삭제입니다: 복원할 수 있습니다.

언제든지 모델 변경

관리 패널이나 CLI를 통해 라이브 컬렉션의 필드를 언제든지 추가, 이름 변경, 제거 또는 유형 변경할 수 있습니다. 기존 콘텐츠는 보존됩니다.

TypeScript 타입

타입 생성은 선택 사항이지만 권장됩니다. 현재 모델에서 타입을 생성합니다:

npx emdash types

이렇게 하면 컬렉션당 인터페이스와 타입이 지정된 쿼리 오버로드가 포함된 .emdash/types.ts가 작성되므로 getEmDashCollection("posts")는 완전히 타입이 지정된 항목을 반환합니다:

export interface Post {
	title: string;
	content: PortableTextBlock[];
	excerpt?: string;
}

declare module "emdash" {
	export function getEmDashCollection(
		type: "posts",
	): Promise<{ entries: ContentEntry<Post>[]; error?: Error }>;
}

모델 변경 후 명령을 다시 실행하여 타입을 동기화하세요.

워크플로

두 워크플로 모두 동일한 모델을 변경합니다.

개발자가 아닌 사용자는 관리 패널을 사용합니다:

  1. 관리 패널에서 Content Types를 엽니다.
  2. Add Collection을 클릭합니다.
  3. 시각적 빌더로 필드를 정의합니다.
  4. 콘텐츠 생성을 시작합니다.

개발자는 CLI를 사용하여 타입을 생성하고 환경 간에 모델을 이동할 수 있습니다:

npx emdash types                     # TypeScript 타입 생성
npx emdash export-seed > seed.json   # 모델을 시드 파일로 내보내기

시드 파일

시드 파일은 컬렉션, 분류체계, 메뉴에 대한 JSON 설명입니다. 템플릿에는 하나가 포함되어 있으며, 버전 관리나 다른 환경 설정을 위해 자체적으로 내보낼 수 있습니다.

{
	"version": "1",
	"collections": [
		{
			"slug": "posts",
			"label": "Blog Posts",
			"labelSingular": "Post",
			"supports": ["drafts", "revisions", "preview"],
			"fields": [
				{ "slug": "title", "type": "string", "required": true },
				{ "slug": "content", "type": "portableText" }
			]
		}
	],
	"taxonomies": [{ "name": "category", "label": "Categories", "hierarchical": true }],
	"menus": [{ "name": "primary", "label": "Primary Navigation" }]
}

시드 적용은 멱등성이므로 다시 실행해도 안전합니다:

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

const { valid, errors } = validateSeed(seedData);
await applySeed(db, seedData, { includeContent: true, onConflict: "skip" });

전체 스키마는 시드 파일 형식을 참조하세요.

다음 단계