ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

EmDash Schema and Seed 文件完全指南:用 seed.json 一键定义站点结构与示例内容

EmDash Schema and Seed 文件完全指南:用 seed.json 一键定义站点结构与示例内容 CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载EmDash 的 seed 文件seed/seed.json是一个数据库无关的 JSON 文档它一次性声明了站点的全部 schema——集合collections、字段fields、分类法taxonomies、菜单menus、组件区widget areas、设置settings以及可选的示例内容content。这份文件在构建时被内联进产物当数据库为空且设置向导尚未完成时会在首次请求时自动应用。阅读本文后你将掌握 seed 文件的完整结构、每种配置项的写法与取值规则以及如何通过emdash export-seed命令从现有数据库反向导出 seed从而具备从零建站与站点迁移的完整能力。Seed 文件整体结构一个 seed 文件以$schema与version开头随后按功能分区组织站点定义。下面的骨架对应 types.ts 中SeedFile接口的全部顶层字段{ $schema: https://emdashcms.com/seed.schema.json, version: 1, meta: { name: My Site, description: A description of this site, author: Author Name }, settings: { ... }, collections: [ ... ], taxonomies: [ ... ], menus: [ ... ], widgetAreas: [ ... ], sections: [ ... ], bylines: [ ... ], content: { ... } }各字段的语义如下$schemaJSON Schema 引用用于编辑器校验提示versionseed 格式版本当前必须为1validate.ts 会拒绝其他版本meta种子元信息仅作描述不参与建库settings站点级设置标题、标语等collections内容类型定义是 seed 的核心taxonomies分类/标签体系menus导航菜单widgetAreas可配置组件区域sections可在编辑器中通过/section命令插入的可复用内容块bylines署名作者档案独立于用户账号content按集合 slug 组织的示例内容此外SeedFile还支持redirects重定向规则与defaultLocale多语言场景下省略locale的行所回退的默认语言见 types.ts。Collections定义内容类型集合定义了站点的内容类型。每个集合在数据库中对应一张名为ec_{slug}的表这一点可以从 apply.ts 中通过SchemaRegistry批量建表、以及 export-seed.ts 中直接查询ec_${collection.slug}表得到印证。{ slug: posts, label: Posts, labelSingular: Post, supports: [drafts, revisions, search, seo], commentsEnabled: true, fields: [ ... ] }Collection Supportssupports数组声明集合开启哪些平台能力SupportDescriptiondraftsDraft/published workflowrevisionsRevision historysearchFull-text search indexingseoSEO meta fields in admin根据 types.ts 的类型定义supports还支持preview预览与scheduling定时发布。在 apply.ts 中可以看到search支持的实际效果应用 seed 后引擎会对含可搜索字段的集合自动调用ftsManager.enableSearch()开启全文搜索。Slug 规则集合与字段 slug 必须满足小写字母数字加下划线/^[a-z][a-z0-9_]*$/最大 63 个字符不能与保留 slug 冲突该正则定义在 validate.ts 中同时会检查重复的集合 slug。另外集合字段的 slug 校验也使用同一模式。更多集合级选项除原文档示例外types.ts 还定义了大量可选项全部可由 apply.ts 中的建集合逻辑处理urlPattern集合条目的 URL 模式routable默认true是否要求条目在发布前具备 slughidden是否从管理后台侧边栏与快捷操作中隐藏仍可通过 API、MCP、插件钩子访问sortOrder管理后台侧边栏的显式排序升序未设置的集合保持字母序并排在有序集合之后group与其他集合共享的管理后台侧边栏文件夹commentsEnabled是否启用评论editLocking默认true打开条目时是否获取编辑锁titleField/dateField指定驱动管理后台列表标题列与日期列的字段 slug见 apply.ts二者会在字段创建成功后单独回写校验。Field Types字段类型与数据库列映射每种字段类型对应一种数据库列类型与一种运行时形态TypeColumn typeRuntime shapeNotesstringTEXTstringSingle line texttextTEXTstringMulti-line text (textarea)numberREALnumberFloating pointintegerINTEGERnumberWhole numbersbooleanINTEGERbooleanStored as 0/1datetimeTEXTDateISO 8601 string in DBimageTEXT{ id, src?, alt?, width?, height? }Object, not a stringreferenceTEXTstring(ID)Reference to another entryportableTextJSONPortableTextBlock[]Rich text as structured JSONjsonJSONanyArbitrary JSON data注意image字段在运行时是对象而非字符串包含id等元数据boolean在数据库中存为 0/1datetime以 ISO 8601 字符串存储。Field Definition{ slug: title, label: Title, type: string, required: true, searchable: true }字段可用的属性SeedField见 types.tsslug必填——字段标识符label必填——管理后台显示名type必填——上述类型之一required——校验必填searchable——纳入全文搜索索引unique——字段值唯一indexed——为字段建索引defaultValue——默认值validation——自定义校验规则widget——指定管理后台使用的输入组件options——传给 widget/字段的附加选项如reference字段可指定目标集合。常见字段组合模式博客文章Blog postfields: [ { slug: title, label: Title, type: string, required: true, searchable: true }, { slug: featured_image, label: Featured Image, type: image }, { slug: content, label: Content, type: portableText, searchable: true }, { slug: excerpt, label: Excerpt, type: text } ]作品集项目Portfolio projectfields: [ { slug: title, label: Title, type: string, required: true, searchable: true }, { slug: featured_image, label: Featured Image, type: image, required: true }, { slug: client, label: Client, type: string }, { slug: year, label: Year, type: string }, { slug: summary, label: Summary, type: text, searchable: true }, { slug: content, label: Content, type: portableText, searchable: true }, { slug: gallery, label: Gallery, type: json }, { slug: url, label: Project URL, type: string } ]页面Page极简fields: [ { slug: title, label: Title, type: string, required: true, searchable: true }, { slug: content, label: Content, type: portableText, searchable: true } ]Taxonomies分类与标签体系Taxonomies 是挂在集合上的标签/分类系统。hierarchical: true表示树形结构类似 WordPress 的分类hierarchical: false则是扁平列表类似 WordPress 的标签。collections声明该分类法应用于哪些集合terms定义预置的分类项。{ name: category, label: Categories, labelSingular: Category, hierarchical: true, collections: [posts], terms: [ { slug: development, label: Development }, { slug: design, label: Design } ] }hierarchical: true—— 树形结构类似 WordPress categorieshierarchical: false—— 扁平列表类似 WordPress tagscollections—— 该分类法适用的集合terms—— 预创建的分类项在 apply.ts 中层级分类项通过applyHierarchicalTerms多轮次应用每轮只处理父项已就绪的 term最多重试 10 轮以支持深层嵌套每个分类项还可携带parent父项 slug与可选的translationOf引用。注意 terms 属于示例数据范畴仅在includeContent为 true 时才会创建SeedApplyOptions.includeContent见 types.ts。Menus导航菜单菜单由管理后台维护seed 中提供初始结构。type: custom的菜单项使用任意 URL内容引用类菜单项页面/文章在渲染时解析。{ name: primary, label: Primary Navigation, items: [ { type: custom, label: Home, url: / }, { type: custom, label: About, url: /pages/about }, { type: custom, label: Posts, url: /posts } ] }菜单项类型custom—— 任意 URL从 types.ts 可见菜单项还支持更多字段非custom项使用ref内容 id 或分类项 slug配合collection目标集合名引用条目可选target_blank/_self、titleAttr、cssClasses以及嵌套children构建多级菜单。apply.ts 会按sort_order递归构建菜单树export-seed.ts 中的buildMenuItemTree展示了相同的父子关系处理逻辑。菜单在内容之后应用这样菜单中的内容引用$ref可以解析到已创建的条目。Widget Areas可配置组件区域组件区是编辑者可以放置可配置组件的命名区域。{ name: sidebar, label: Sidebar, description: Widget area displayed on single post pages, widgets: [ { type: component, componentId: core:search, title: Search }, { type: component, componentId: core:categories, title: Categories }, { type: component, componentId: core:tags, title: Tags }, { type: component, componentId: core:recent-posts, title: Recent Posts, settings: { count: 5, showDate: true } }, { type: component, componentId: core:archives, title: Archives, settings: { type: monthly, limit: 6 } }, { type: content, title: About, content: [ { _type: block, style: normal, children: [{ _type: span, text: Some rich text content. }] } ] } ] }Widget 类型TypeDescriptionKey fieldscontentRich text (Portable Text)contentmenuNavigation menumenuNamecomponentCore or custom componentcomponentId,settings根据 types.tscomponent组件的配置在类型定义中为props导出代码 export-seed.ts 中也是读写props字段isWidgetType严格限定三种合法类型。应用时组件区会整体重建——已存在的区域先清空旧 widgets 再写入新 widgetsapply.ts。核心组件core:search—— 搜索表单core:categories—— 带计数的分类列表core:tags—— 标签云core:recent-posts—— 最新文章列表core:archives—— 按月归档链接Sections可复用内容块Sections 是可复用内容块编辑者在编辑器中通过/section斜杠命令插入。{ slug: newsletter-signup, title: Newsletter Signup, description: A call-to-action block for newsletter subscriptions, keywords: [newsletter, subscribe, email, cta], source: theme, content: [ { _type: block, style: h3, children: [{ _type: span, text: Stay in the loop }] }, { _type: block, style: normal, children: [{ _type: span, text: Get notified when new posts are published. }] } ] }types.ts 中source取值为themeseed 提供或importWordPress 导入theme_id在应用时随source写入。应用逻辑见 apply.ts。Bylines署名作者档案Bylines 是独立的署名作者档案与用户账号无关。seed 中声明的 byline 通过id被内容条目的bylines数组引用。{ id: byline-editorial, slug: emdash-editorial, displayName: EmDash Editorial }客座作者{ id: byline-guest, slug: guest-contributor, displayName: Guest Contributor, isGuest: true }types.ts 中SeedByline还支持bio、websiteUrl以及avatar通过已存储文件的storageKey关联头像不会触发下载适合配合媒体迁移一起 seed。byline 属于示例数据同样只在includeContent为 true 时应用apply.ts。Settings站点设置settings: { title: My Blog, tagline: Thoughts on building for the web }可用键title、tagline、logo、favicon、social、timezone、dateFormat。设置以site:前缀存入选项表见 apply.ts 与 export-seed.ts 中SETTINGS_PREFIX的读写对称逻辑。onConflict对设置按 key 逐个处理skip只创建缺失 keyupdate覆盖传入 keyerror遇到首个已存在 key 即报错。Content示例内容内容按集合 slug 组织。每个条目包含idseed 内唯一标识用于$ref解析、slug、statuspublished/draft、data字段 slug → 值以及可选的bylines与taxonomies关联content: { posts: [ { id: post-1, slug: hello-world, status: published, data: { title: Hello World, excerpt: My first post., featured_image: { $media: { url: https://images.unsplash.com/photo-xxx?w1200h800fitcrop, alt: Description of image, filename: hello-world.jpg } }, content: [ { _type: block, style: normal, children: [{ _type: span, text: This is the body text. }] } ] }, bylines: [ { byline: byline-editorial } ], taxonomies: { category: [development], tag: [webdev, opinion] } } ], pages: [ { id: about, slug: about, status: published, data: { title: About, content: [ { _type: block, style: normal, children: [{ _type: span, text: About this site. }] } ] } } ] }Content 中的媒体引用$media图片字段使用$media语法EmDash 会下载并存储该图片下载 → 上传到配置的存储 → 创建媒体记录 → 替换为正式字段值这一流程注释在 types.ts 中featured_image: { $media: { url: https://images.unsplash.com/photo-xxx?w1200h800fitcrop, alt: Description, filename: my-image.jpg } }如需使用外部图片而不下载直接给字符串 URLfeatured_image: https://images.unsplash.com/photo-xxx?w1200SeedApplyOptions还提供skipMediaDownload将$media解析为使用原始外部 URL 的externalprovider 媒体值无需存储适配器适合 playground/演示环境与mediaBasePath本地媒体文件的基础路径见 types.ts。Content 中的引用字段$ref使用$ref:id格式引用其他条目author: $ref:byline-editorialapplySeed在应用过程中维护 seed id → 真实条目 id 的映射表seedIdMap先创建被引用目标、后创建引用方从而解析$ref。导出侧export-seed.ts则通过orderByReferenceTargets对集合做依赖排序保证引用目标先被写入。Content 中的 Portable TextportableText类型的内容字段是 block 数组[ { _type: block, style: normal, children: [{ _type: span, text: A paragraph. }] }, { _type: block, style: h2, children: [{ _type: span, text: A heading }] }, { _type: block, style: blockquote, children: [{ _type: span, text: A quote. }] } ]行内标记加粗、斜体、链接{ _type: block, style: normal, children: [ { _type: span, text: This is }, { _type: span, text: bold, marks: [strong] }, { _type: span, text: and }, { _type: span, text: italic, marks: [em] } ] }块级样式支持normal、h1-h6、blockquote。草稿内容设置status: draft创建未发布内容{ id: post-draft, slug: work-in-progress, status: draft, data: { ... } }从 apply.ts 的实现细节看status: published的条目在创建后会被立即提升为 live revision填充live_revision_id管理后台显示Unpublish而非Save Publishstatus: draft则保持草稿。真实示例marketing-cloudflare 模板的 seed仓库中 templates/marketing-cloudflare/seed/seed.json 是一个完整可运行的 seed它定义了一个pages集合含title与content字段、四个导航菜单primary以及三个页脚菜单footer_product/footer_company/footer_support并在content.pages中预置了home、pricing、contact三个页面。其正文大量使用marketing.hero、marketing.features、marketing.testimonials、marketing.pricing、marketing.faq等自定义 block 类型与 src/components/blocks 下的组件一一对应——这展示了 seed 内容与主题组件如何通过_type完成绑定是编写带插件内容 seed 的绝佳参照。应用 Seeds时机、位置与幂等性seed 的加载入口在 load.ts它通过 Vite 的虚拟模块virtual:emdash/seed在构建时将用户 seed或默认 seed内联进产物从而避免运行时文件系统访问在 workerd/miniflare 中process.cwd()返回/。seed 文件可以放在以下任一位置按优先级.emdash/seed.jsonpackage.json#emdash.seedseed/seed.json它被内联进构建在数据库为空且设置向导未完成时于首次请求自动应用。已有数据永远不会被覆盖——applySeed是幂等的可安全重复执行。应用顺序applySeedapply.ts严格按照依赖顺序写入先决条件是外键与引用都能解析Site settingsCollections FieldsTaxonomy definitions TermsBylinesContent先于菜单使菜单引用可解析Menus Menu items此时可解析内容引用RedirectsWidget areas WidgetsSections对supports含search的集合启用全文搜索冲突处理SeedApplyOptions.onConflict决定冲突时的行为默认skipskip跳过已存在项、update覆盖、error在首个冲突处抛错。另需注意includeContent默认false——即默认只应用 schema 与结构集合、字段、分类法定义、菜单、设置、重定向、组件区、sections内容条目、byline 与分类项属于示例数据需显式开启。验证何时失败校验在应用时运行validateSeedvalidate.ts。常见错误包括图片字段使用原始 URL应使用$media引用字段使用原始 ID应使用$ref:idPortableText 不是数组或缺少_type类型不匹配string 与 number 混用等validateSeed还会检查version必须为1集合 slug 必须匹配/^[a-z][a-z0-9_]*$/且不重复defaultLocale必须是非空且无首尾空格的字符串重定向路径必须以/开头、不能含//开头、CRLF 或..路径穿越validate.ts。如果 seed 无效首次请求会失败并记录错误。修复后需重启开发服务器。导出 Seeds从数据库反向生成通过 CLI 可以从现有数据库导出 seed 文件用于站点备份、克隆或模板化npx emdash export-seed # Schema only npx emdash export-seed --with-content # Schema all content npx emdash export-seed --with-contentposts,pages # Specific collections命令定义在 export-seed.ts支持的完整参数--database, -d数据库路径默认./data.db--cwd工作目录默认当前进程目录--with-content包含内容all与裸标志、true等价或逗号分隔的集合名列表--prettyJSON 是否美化输出默认true。导出过程有以下实现要点导出前会检查迁移状态存在待执行迁移或由更新版本 EmDash 迁移过的数据库会直接报错export-seed.ts命令以只读方式连接数据库seed 文档写入stdout便于emdash export-seed seed.json重定向诊断信息写入 stderr避免污染输出导出内容时图片字段被转换回$media语法、引用字段被转换回$ref:seedId形式processDataForExportexport-seed.ts内容条目的 seed id 形如collectionSlug:itemSlug多语言下追加:locale保证$ref在往返export → seed后依然稳定导出会检测数据中的语言分布多个 locale 时输出带locale与translationOf的多语言结构单个非enlocale 时通过顶层defaultLocale自描述避免往返时被回填成en见 export-seed.ts 中的detectLocaleInfo。小结seed 文件是 EmDash 建站与迁移的枢纽它把内容类型的数据库表结构、后台配置、导航、组件区、示例内容压缩成一份声明式 JSON构建期内联、首请求自动应用、重复执行幂等配合emdash export-seed又能在任意时刻把线上数据库的 schema 与内容完整导出。对开发者和模板作者来说掌握collections/fields的字段类型映射、$media/$ref/Portable Text 的书写规范以及onConflict/includeContent等应用选项就能像写配置文件一样搭建出结构完整、可直接运营的 EmDash 站点。上述所有行为均可在 packages/core/src/seed 目录下找到对应实现与测试佐证。赞分享CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载相关推荐EmDash Schema 与 Seed 文件完全指南用 seed.json 定义内容模型与示例数据EmDash Schema 与 Seed 文件完全指南用 seed.json 定义内容模型与示例数据 导读 本文基于 EmDash 官方技能文档 schemCMS后端前端插件系统Thunderbolt 5 RDMAJACCL低延迟分布式通信实战Thunderbolt 5 RDMAJACCL低延迟分布式通信实战 四台 M3 Ultra 张量并行推理TCP 延迟为何成了瓶颈 四台 M3 Ultra 用CMS后端前端插件系统CopilotKit 工具驱动式生成 UI 实战LangGraph TypeScript Agent 中用 useComponent 把工具结果渲染为 React 图表CopilotKit 工具驱动式生成 UI 实战LangGraph TypeScript Agent 中用 useComponent 把工具结果渲染为 ReaCMS后端前端插件系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表