シードファイル

このページ

シードファイルは、EmDash サイトの初期スキーマと任意のサンプルデータを記述します。現在のテンプレートはこれを seed/seed.json に置き、package.json#emdash.seed で指します。

EmDash はビルド時にシードを埋め込みます。初回セットアップと明示的なシードコマンド向けであり、デプロイのたびに実行されるマイグレーションではありません。

ファイルの検出

Astro 統合は次の順でシードを探します。

  1. .emdash/seed.json
  2. package.json#emdash.seed のパス
  3. seed/seed.json
  4. ユーザーシードがない場合の組み込みデフォルトシード

次のパッケージフィールドがテンプレートの慣例パスを選びます。

{
  "emdash": {
    "seed": "seed/seed.json"
  }
}

ルート形状

次の例はすべてのルートプロパティを含みます。

{
  "$schema": "https://emdashcms.com/seed.schema.json",
  "version": "1",
  "defaultLocale": "en",
  "meta": {
    "name": "Publication",
    "description": "A publication seed",
    "author": "Example Studio"
  },
  "settings": {},
  "blockTypes": [],
  "collections": [],
  "relations": [],
  "taxonomies": [],
  "bylines": [],
  "content": {},
  "menus": [],
  "redirects": [],
  "widgetAreas": [],
  "sections": []
}
PropertyRequiredPurpose
$schemaNoエディタのスキーマ URL
versionYesシード形式。受け付ける値は "1" のみ
defaultLocaleNolocale を省略したロケール付き行のロケール。デフォルトはランタイム設定、次に en
metaNoセットアップ中に表示される説明名、説明、著者
settingsNo部分的なサイト設定
blockTypesNoblocks フィールドで使うバージョン付き定義
collectionsNoコレクションとフィールド定義
taxonomiesNoタクソノミー定義と任意の用語
bylinesNo任意の表示クレジットプロフィール
contentNoコレクションスラッグごとにグループ化したサンプルエントリ
menusNoメニューとネストした項目
redirectsNoローカルリダイレクトルール
widgetAreasNoウィジェットエリアとウィジェット
sectionsNo再利用可能な Portable Text セクション

defaultLocale は先頭・末尾の空白がない空でない文字列である必要があります。

Settings

settings は部分的なサイト設定オブジェクトです。よく使うプロパティは title、tagline、logo、favicon、url、postsPerPage、dateFormat、timezone、social、seo です。

セットアップウィザードは、管理者がシード済みのタイトルとタグラインを上書きできるようにします。デフォルトの onConflict: "skip" は、シードを再適用するときにそれらの値を保ち、まだ欠けている提供済み設定を埋めます。

{
  "version": "1",
  "settings": {
    "title": "Field Notes",
    "tagline": "Reports from the team",
    "postsPerPage": 12,
    "dateFormat": "MMMM d, yyyy",
    "timezone": "Europe/London"
  }
}

ブロックタイプ

blockTypes は、コレクションの blocks フィールドが使うバージョン付き形状を定義します。EmDash はコレクションより先にこれらの定義を適用するため、フィールドは validation.allowedTypes でそれらを指名できます。

次のシードは、保存済みコンテンツとリビジョンのためにバージョン 1 を残しつつ、新しいブロックではバージョン 2 をアクティブにします。

{
  "version": "1",
  "blockTypes": [
    {
      "slug": "hero",
      "label": "Hero",
      "category": "Layout",
      "currentVersion": 2,
      "versions": [
        {
          "version": 1,
          "fields": [
            { "slug": "heading", "label": "Heading", "type": "string", "required": true }
          ]
        },
        {
          "version": 2,
          "fields": [
            { "slug": "title", "label": "Title", "type": "string", "required": true },
            { "slug": "image", "label": "Image", "type": "image" }
          ]
        }
      ]
    }
  ],
  "collections": [
    {
      "slug": "pages",
      "label": "Pages",
      "fields": [
        {
          "slug": "layout",
          "label": "Layout",
          "type": "blocks",
          "validation": { "allowedTypes": ["hero"], "maxItems": 20 }
        }
      ]
    }
  ]
}

バージョン番号は 1 から始まる連続した正の整数です。currentVersion は宣言済みバージョンを指名する必要があります。シードのエクスポートと再適用は正確なバージョン番号とアクティブポインタを保ちます。EmDash はそれらを付け替えません。

onConflict: "update" では、新しい定義が互換な場合に限り、シードは保存済みバージョンを変更できます。非互換な定義に既存番号を再利用すると BLOCK_TYPE_VERSION_CONFLICT で失敗します。非互換な定義には新しいバージョン番号を追加してください。

保存済みブロック値は _type、_version、_key を含みます。シードコンテンツが保持バージョンを指すときはそれらのプロパティを提供してください。ランタイムは、新しく書かれたブロックがそれらを省略したときにアクティブバージョンとキーを割り当てます。

Collections

コレクションには slug、label、fields が必要です。

{
  "version": "1",
  "collections": [
    {
      "slug": "posts",
      "label": "Posts",
      "labelSingular": "Post",
      "description": "Published articles",
      "supports": ["drafts", "revisions", "scheduling", "search", "seo"],
      "urlPattern": "/posts/{slug}",
      "routable": true,
      "commentsEnabled": true,
      "editLocking": true,
      "titleField": "title",
      "dateField": "event_date",
      "admin": {
        "listColumns": ["event_date"]
      },
      "fields": [
        { "slug": "title", "label": "Title", "type": "string", "required": true },
        { "slug": "event_date", "label": "Event date", "type": "datetime", "indexed": true },
        { "slug": "content", "label": "Content", "type": "portableText" }
      ]
    }
  ]
}

コレクションプロパティ

PropertyTypeBehavior
slugstring必須のデータベース/API 名。小文字で始まり、小文字・数字・アンダースコアを含む
labelstring必須の複数形 UI ラベル
labelSingularstring任意の単数形 UI ラベル
descriptionstring任意の管理画面の説明
iconstring任意のアイコン名
admin.listColumnsstring[]コンテンツリストに表示する、宣言済みフィールドスラッグ最大 4 つ
supportsstring[]drafts、revisions、preview、scheduling、search、seo のいずれか
urlPatternstring/posts/{slug} のような公開パターン
routableboolean公開エントリにスラッグが必要か。デフォルト true
hiddenboolean生成されたサイドバーリンクとダッシュボードのクイックアクションを隠す。コレクションは URL と API では到達可能のまま
sortOrdernumber管理サイドバーでの明示的な位置。並べ替えられたコレクションが先に、昇順で来る
groupstring管理サイドバーのフォルダ。同じグループのコレクションは折りたたみ可能なエントリを共有する
commentsEnabledbooleanコレクションのコメントを有効にする
editLockingboolean編集ロックを有効にする。デフォルト true
titleFieldstringコンテンツリストのタイトルに使うフィールド
dateFieldstringコンテンツリストの日付に使う datetime フィールド
fieldsSeedField[]必須のフィールド定義

sortOrder はコレクションに属し、サイドバー順を制御します。SeedField に sortOrder プロパティはありません。フィールドはその配列順で作成されます。

フィールドプロパティ

PropertyTypePurpose
slugstringコレクションスラッグと同じパターンの必須フィールド名
labelstring必須の UI ラベル
typeFieldType必須の保存フィールドタイプ
requiredboolean必須の空の値を拒否する
uniqueboolean一意性制約を追加する
searchablebooleanコレクション検索にフィールドを含める
indexedbooleanサポートされるスカラー型のクエリインデックスを追加する
translatablebooleanロケールごとに値を保存。デフォルト true。false は翻訳間で 1 つの値を共有
defaultValueanyフィールド省略時の初期値
validationobject生成されたコンテンツスキーマが使う検証ルール
widgetstring管理フィールドウィジェットの上書き
optionsobjectウィジェット固有のオプション

サポートされるフィールドタイプは次のとおりです。

  • string、text、url、slug
  • number、integer、boolean
  • datetime
  • select、multiSelect
  • portableText、json、repeater
  • blocks
  • image、file、reference

reference フィールドはコレクションテーブルには何も保存しません。そのリンクは結び付いたリレーションにあります。 Relations を参照してください。

indexed: true を設定できるのは string、url、number、integer、boolean、datetime、select、reference、slug のみです。reference フィールドでは、フィールドがリレーションを持たない間だけフラグが適用されます。結び付いたフィールドにはインデックスする列がないためです。

フィールド検証

生成されたコレクションスキーマは、フィールドタイプがサポートするところで次のルールを認識します。

RuleUsed by
min、max数値フィールド
minLength、maxLength、pattern文字列形フィールド
optionsselect と multiSelect
subFields、minItems、maxItemsrepeater
allowedTypes、minItems、maxItemsblocks
allowedMimeTypesメディアフィールド

blocks フィールドの retiredTypes はサーバー側で扱われます。allowedTypes からスラッグを外すと引退し、既存の保存ブロックは有効のまま、新しいブロックでは使えなくなります。

validateSeed() は validation や options 内のすべてのルールを深く検査しません。そのため無効なルールがシード検証を通過し、後でコレクションスキーマ作成時やコンテンツ書き込み時に失敗することがあります。

Relations

リレーションは 2 つのコレクションを結び、そのエントリ間のリンクを所有します。reference フィールドは一方に結び付き、その端からリンクを見ます。次のシードは、投稿あたり 1 人の著者を許す posts と authors のリレーションを宣言します。

{
	"relations": [
		{
			"slug": "post_authors",
			"parentCollection": "posts",
			"childCollection": "authors",
			"parentLabel": "Posts",
			"parentLabelSingular": "Post",
			"childLabel": "Authors",
			"childLabelSingular": "Author",
			"maxChildrenPerParent": 1
		}
	]
}
PropertyTypeRequiredDescription
slugstringYesreference フィールドがアドレスする一意の名前
parentCollectionstringYes親端のコレクション
childCollectionstringYes子端のコレクション
parentLabelstringYes子から見た親の役割名
parentLabelSingularstringNoparentLabel の単数形
childLabelstringYes親から見た子の役割名
childLabelSingularstringNochildLabel の単数形
maxChildrenPerParentnumber | nullNo親がリンクできる子の数(null: 制限なし)
maxParentsPerChildnumber | nullNo子がリンクできる親の数(null: 制限なし)

collections 内の reference フィールドは、結び付くリレーションを指名します。

{
	"slug": "author",
	"label": "Author",
	"type": "reference",
	"validation": { "relation": "post_authors" }
}

フィールドは代わりに targetCollection を指名し、そのためのリレーションを作成させることもできます。これは一方のコレクションだけが見るリンクへの最短経路です。両方のコレクションが見る必要があるとき、またはラベルと上限を設定するときは relations でリレーションを宣言してください。 reference は両方の形と、それぞれが受け付ける検証キーを文書化しています。

リレーションの 2 つのコレクションは存在後は固定です。異なるものを指名するシードは、保持するリンクがもはや端ではないコレクションを指すことを許さず失敗します。ラベルと上限は、シードが onConflict: "update" で適用されるときに更新されます。

タクソノミー

タクソノミー定義は対象コレクションを識別します。用語はサンプルデータで、includeContent が true のときだけ適用されます。

{
  "version": "1",
  "taxonomies": [
    {
      "name": "category",
      "label": "Categories",
      "labelSingular": "Category",
      "hierarchical": true,
      "collections": ["posts"],
      "terms": [
        { "slug": "engineering", "label": "Engineering" },
        { "slug": "platform", "label": "Platform", "parent": "engineering" }
      ]
    }
  ]
}

タクソノミーはシードローカルの id、locale、translationOf を持てます。用語もそれらのプロパティを持てます。translationOf は別のシードローカル ID を指します。用語は、翻訳元の用語の後に並べる必要があります。同じ name のタクソノミーエントリは任意の順で現れ得ます。タクソノミーの形状を宣言するエントリが翻訳より先に適用されるためです。

hierarchical と collections はタクソノミーのすべてのロケールで共有されるため、同じ name のエントリを translationOf が指すタクソノミーエントリはそれらを省略できます。適用エンジンは同じ name のエントリを通じて translationOf をたどり、最後のものから取ります。バリデーションは、翻訳が取る値と異なる値を宣言したとき、またはタクソノミーについてそれらを宣言する 2 つのエントリが一致しないときに警告します。既存のタクソノミーは、translationOf のないエントリが置き換えるまで値を保ちます。これは onConflict: "update" で起き、Conflict behavior で述べる未変更の組み込み category または tag 定義をエントリのロケールが持つ場合、またはその組み込み定義がタクソノミーの唯一のものである場合はどのモードでも起きます。エクスポートは、翻訳が指すエントリにのみそれらを書き込みます。

用語の parent は同じロケール内の親用語のスラッグです。非階層タクソノミーの親は警告を出し、無視されます。translationOf があり parent がない用語は、翻訳元の用語の親を取ります。

Bylines

ルートの bylines は表示クレジットを定義します。サンプルデータであり、includeContent: true が必要です。

{
  "version": "1",
  "bylines": [
    {
      "id": "byline-editor",
      "slug": "alex-editor",
      "displayName": "Alex Editor",
      "isGuest": true
    }
  ]
}

id はシードローカルで、コンテンツクレジットが使います。任意のプロパティは bio、websiteUrl、isGuest、avatar です。

バイラインのアバターは、設定済みストレージに既にあるファイルを指します。

{
  "id": "byline-editor",
  "slug": "alex-editor",
  "displayName": "Alex Editor",
  "avatar": {
    "storageKey": "avatars/alex.jpg",
    "filename": "alex.jpg",
    "mimeType": "image/jpeg",
    "alt": "Alex Editor",
    "width": 400,
    "height": 400
  }
}

バイラインアバターのシードは、ストレージキーのメディア行を作成または再利用します。ファイルのアップロードやダウンロードはしません。

Content

content はコレクションスラッグごとにエントリをグループ化します。各エントリにはシードローカルの id と data オブジェクトが必要です。ルーティング可能なコレクションには空でない slug も必要です。

{
  "version": "1",
  "content": {
    "posts": [
      {
        "id": "post-welcome",
        "slug": "welcome",
        "status": "published",
        "data": {
          "title": "Welcome",
          "content": []
        },
        "taxonomies": {
          "category": ["engineering"]
        },
        "bylines": [
          { "byline": "byline-editor", "roleLabel": "Editor" }
        ]
      }
    ]
  }
}
PropertyRequiredBehavior
idYesシードローカルの参照 ID
slugルーティング可能なコレクション向け公開スラッグと競合キー
statusNopublished または draft。デフォルト published
dataYesコレクションフィールドスラッグでキー付けされた値
taxonomiesNoタクソノミー名から用語スラッグの配列へ
bylinesNoルートバイライン ID を参照する順序付きクレジット
localeNoBCP 47 ロケール。defaultLocale 経由でデフォルト
translationOfNo同じコレクション内のシードローカルコンテンツ ID

ルーティング可能なエントリでは、シードローカルの id はデータベースの同一性ではありません。EmDash はデータベース ID を作成し、後続の参照のためにマッピングを記録します。routable: false のコレクションでスラッグのないエントリでは、EmDash はシードの id を保存 ID として使い、再適用を冪等に保ちます。

読み取り時、entry.id は Astro のルート識別子で、通常はスラッグです。保存されたデータベース ID は entry.data.id です。

コンテンツ参照

data 内で $ref: 文字列を使い、シードローカルのコンテンツ ID を作成されたデータベース ID に置き換えます。

{
  "id": "event-opening",
  "slug": "opening-night",
  "data": {
    "title": "Opening night",
    "venue": "$ref:venue-main-hall"
  }
}

参照先は、適用エンジンの ID マップに載るだけ十分早く現れる必要があります。未解決の $ref: 値は元のリテラル文字列のまま残ります。validateSeed() はそれを拒否しません。

reference フィールドでは、そのリレーションの親端からリンクを宣言してください。両端が同じリンク集合を見るため、子コレクション上のフィールドは親が既に持つリンクを再主張することになります。

メディア参照

コンテンツデータ内の $media を使い、URL をダウンロードし、提供されたストレージアダプタでアップロードし、メディア行を作成し、オブジェクトをメディアフィールド値に置き換えます。

{
  "featured_image": {
    "$media": {
      "url": "https://example.com/images/launch.jpg",
      "filename": "launch.jpg",
      "alt": "A product launch on stage",
      "caption": "Launch event"
    }
  }
}

Portable Text の image ブロックや gallery 画像では、asset 内の $media がメディア参照(_type: "reference"、_ref、url、provider)になり、メディアの代替テキストと寸法が欠けているとき画像の alt、width、height を埋めます。

1 回の適用呼び出し内では、同じ URL への繰り返し参照は解決済みメディア値を再利用します。シードのメディア参照はローカルの file プロパティを受け付けません。mediaBasePath は公開型 SeedApplyOptions に残りますが、現在の適用エンジンは読みません。

ストレージアダプタが提供されないとき、$media 参照はスキップされ null に解決されます。skipMediaDownload: true では外部メディア値になり、ストレージアダプタは不要です。

メニュー

メニューは構造データで、includeContent が false でも適用されます。

{
  "version": "1",
  "menus": [
    {
      "name": "primary",
      "label": "Primary navigation",
      "items": [
        {
          "type": "page",
          "label": "About",
          "ref": "page-about",
          "collection": "pages"
        },
        {
          "type": "custom",
          "label": "Contact",
          "url": "/contact",
          "target": "_self"
        }
      ]
    }
  ]
}

許可される項目タイプは custom、page、post、taxonomy、collection です。custom には url が、page と post には ref が必要です。項目は id、translationOf、label、collection、titleAttr、cssClasses、locale、target、入れ子の children を含められます。

page と post では、ref はシードコンテンツ ID を指名します。欠落したターゲットは検証警告を出し、解決済みコンテンツ参照のないメニュー項目になります。既存のメニュー項目は、onConflict に関係なく、そのメニューが適用されるたびに削除して再作成されます。

リダイレクト

リダイレクトにはローカルのソースと宛先パスが必要です。

{
  "version": "1",
  "redirects": [
    {
      "source": "/old-path",
      "destination": "/new-path",
      "type": 308,
      "enabled": true,
      "groupName": "WordPress migration"
    }
  ]
}

両方のパスは / で始まる必要があります。プロトコル相対 URL、パストラバーサルセグメント、改行は拒否されます。許可されるステータスコードは 301、302、307、308 です。

ウィジェットエリア

ウィジェットエリアは content、menu、または component ウィジェットを保持します。

{
  "version": "1",
  "widgetAreas": [
    {
      "name": "sidebar",
      "label": "Sidebar",
      "widgets": [
        {
          "type": "menu",
          "title": "Explore",
          "menuName": "primary"
        },
        {
          "type": "component",
          "title": "Recent posts",
          "componentId": "core:recent-posts",
          "props": { "count": 5 }
        }
      ]
    }
  ]
}

コンテンツウィジェットは Portable Text を content に保存します。メニューウィジェットには menuName が必要です。コンポーネントウィジェットには componentId が必要で、props を渡せます。SeedWidget に settings プロパティはありません。

エリア内の既存ウィジェットは、onConflict に関係なく、エリアが適用されるたびに削除して再作成されます。

セクション

セクションは再利用可能な Portable Text コンテンツを保持します。

{
  "version": "1",
  "sections": [
    {
      "slug": "newsletter-signup",
      "title": "Newsletter signup",
      "description": "Signup call to action",
      "keywords": ["newsletter", "email"],
      "source": "theme",
      "content": []
    }
  ]
}

セクションスラッグは小文字、数字、ハイフンを含みます。source は theme、user、または import です。シードはデフォルトで theme に設定します。テーマセクションは管理画面で削除できません。セクションは構造的で、includeContent が false でも適用されます。

ローカライゼーション

defaultLocale は、タクソノミー、用語、メニュー、メニュー項目、コンテンツの欠けたロケールを埋めます。存在するときはアクティブなランタイム i18n 設定が優先されます。

ローカライズされたタクソノミー、用語、メニュー、メニュー項目、コンテンツは、シードローカルの id と translationOf フィールドを使います。適用エンジンが翻訳グループを解決できるよう、ソース項目を翻訳より前に置いてください。翻訳されたコンテンツエントリは locale を設定し、その translationOf は同じコレクション内の別エントリを指名する必要があります。

プログラムからのシード適用

applySeed() と validateSeed() は emdash/seed からエクスポートされます。次のヘルパーは適用前に検証します。

import {
  applySeed,
  validateSeed,
  type SeedApplyOptions,
  type SeedFile,
} from "emdash/seed";

type SeedDatabase = Parameters<typeof applySeed>[0];

export async function applyProjectSeed(
  db: SeedDatabase,
  seed: SeedFile,
  options: SeedApplyOptions,
) {
  const validation = validateSeed(seed);
  if (!validation.valid) {
    throw new Error(validation.errors.join("\n"));
  }

  return applySeed(db, seed, options);
}

SeedApplyOptions

OptionDefaultCurrent behavior
includeContentfalseコンテンツエントリ、バイライン、タクソノミー用語を含める
onConflict"skip"サポートされるエンティティ競合に対する "skip"、"update"、または "error"
storagenone$media URL のダウンロードに必要なストレージアダプタ
skipMediaDownloadfalse$media URL を外部メディア値のままにする
mediaBasePathnone公開型にはあるが、現在の適用エンジンでは使われない

プログラム適用のデフォルトは includeContent が false です。セットアップウィザードは管理者のサンプルコンテンツ選択を渡します。CLI の emdash seed は、--no-content が設定されない限りデフォルトでコンテンツを含めます。

競合動作

onConflict はシード全体のトランザクションポリシーではありません。

  • コレクション、フィールド、バイライン、コンテンツ、リダイレクト、セクションは skip、update、error の動作をサポートします。
  • タクソノミー定義と用語は、該当する競合モードに従います。例外は、新しいデータベースが始まる組み込みの category と tag 定義です。サイトがそれらを変更するまでは、それらを宣言するシードはどのモードでも置き換えます。
  • 設定はキーごとの競合処理を使います。skip は欠けた設定を作成し既存値を保ちます。update は提供された各設定を上書きします。error は最初の既存設定で止まります。シード順で先に作成された設定は適用されたままです。
  • 既存メニューはメニュー行を保ちつつ全項目を置き換えます。
  • 既存ウィジェットエリアはエリア行を保ちつつ全ウィジェットを置き換えます。
  • コンテンツ競合はコレクション、スラッグ、ロケールで照合されます。ルーティング不可コレクションのスラッグなしエントリはシード ID で照合されます。

onConflict: "update" では、コンテンツデータが置き換えられ、バイラインとタクソノミーの割り当てがシードに合わせて調整されます。既存サイトに対して使う前に、コピー上で update モードをテストしてください。

applySeed() は、コレクション、フィールド、タクソノミー、バイライン、メニュー、リダイレクト、ウィジェットエリア、セクション、設定、コンテンツ、メディアのカウンタを返します。

検証動作

validateSeed() は { valid, errors, warnings } を返します。applySeed() はそれを呼び出し、エラーがあるとき Invalid seed file を投げます。

バリデータは、適用エンジンが必要とする構造ルールを検査します。例:

  • バージョンと空でない defaultLocale
  • コレクション、フィールド、タクソノミー、用語、メニュー、ウィジェットエリア、セクション、バイライン、コンテンツのコンテナ形状
  • 必須の名前、ラベル、ID、スラッグ、サポートされるフィールド/ウィジェットタイプ
  • 関連スコープ内の重複識別子
  • インデックス付きフィールドタイプと admin.listColumns 参照
  • タクソノミーの親、コンテンツ翻訳、コンテンツバイライン参照、メニュー項目の要件
  • 安全なローカルリダイレクトパスとステータスコード

一部の条件はエラーではなく警告です。例: コレクションのないタクソノミー、フラットタクソノミーの親、シードにないメニューコンテンツ参照。

バリデータは、すべての data 値がコレクションフィールドに適合することを証明しません。サイト設定、フィールドの validation、フィールドの options、任意の Portable Text ブロック、コンポーネントウィジェットの props、コンテンツデータ内の $ref: ターゲット、$media のリモート可用性も深く検証しません。有効なシードでも、スキーマ作成、コンテンツ検証、ネットワークダウンロード、ストレージアップロードで失敗することがあります。

エディタ支援には $schema URL を使い、適用前に実行可能なバリデータを実行してください。

npx emdash seed seed/seed.json --validate

CLI コマンド

明示的な競合動作でローカル SQLite データベースにシードを適用します。

npx emdash seed seed/seed.json --database ./data.db --on-conflict skip

現在のローカルスキーマと全コンテンツをテンプレートパスへエクスポートします。

npx emdash export-seed --database ./data.db --with-content=all > seed/seed.json

export-seed はローカル SQLite ファイルに対して直接動作します。デプロイ済みの D1 データベースでは、先にローカルファイルへエクスポートしてください。結果をコミットする前に、エクスポートされた設定、コンテンツ、メディア参照を確認してください。エクスポートしたメディアを別サイトでインポート可能にするには --media-base-url を渡してください。Media URLs を参照してください。

次のステップ

  • Create a theme — 再利用可能な Astro テンプレートでシードを使う
  • Schema evolution — 既存のデプロイ済みサイトのスキーマを更新する
  • CLI reference — データベースとエクスポートのオプション