尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
基于 EmDash 构建 SaaS 营销落地页:marketing-cloudflare 模板的架构、内容模型与定制实战
CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载本文以 EmDash 开源仓库中的templates/marketing-cloudflare模板为对象完整拆解一个基于 Astro EmDash CMS 的 SaaS 风格营销站点从本地开发命令、seed 内容模型、五类 Marketing 块的插件注册机制到设计令牌体系、品牌换肤与 Cloudflare Workers 部署。读完你既能按模板快速起一个产品落地页也能理解 EmDash 的 Portable Text 块渲染链路与插件约束将其迁移复用到自己的站点。模板定位面向转化流程的 SaaS 落地页templates/marketing-cloudflare是一套在 Cloudflare Workers 上运行的 EmDash 模板站点。与博客、作品集模板不同它没有 posts 集合全部内容都以「营销块」marketing blocks的形式编排在pages集合内按 hero → features → testimonials → pricing → FAQ 的顺序自由组合适合产品营销站、App 落地页以及任何需要「Hero 特性 定价 CTA」转化链路的场景。模板的视觉基调在仓库内所有模板中最为鲜明高饱和的渐变强调色、Hero 区等距插画、加重的标题字重整体语气「产品自信但不落入 SaaS 俗套」原文product-confident without tipping into stock SaaS cliche。模板说明 中将其定位为「Bolder than the blog and portfolio templates」。快速上手本地开发命令模板在 package.json 中提供标准的 Astro 脚本配合 pnpm 工作区仓库根目录见 pnpm-workspace.yaml使用pnpm install # 安装依赖emdash 为 workspace 包 pnpm dev # 启动 Astro 开发服务器 npx emdash types # 从运行中的站点重新生成 TypeScript 类型管理后台地址固定为http://localhost:4321/_emdash/admin。npx emdash types会依据当前站点内容重新生成emdash-env.d.ts该文件在开发服务器启动时也会自动重新生成。其他常用脚本来自 package.json脚本命令用途devastro dev本地开发buildastro build生产构建previewastro preview预览构建产物deployastro build wrangler deploy构建并部署到 Cloudflare Workerstypecheckastro check类型检查关键文件一览从模板骨架理解 EmDash 站点模板目录结构见 templates/marketing-cloudflare核心文件与职责文件职责astro.config.mjsAstro 配置emdash()集成、D1 数据库、R2 存储、字体、图标src/live.config.tsEmDash loader 注册样板代码勿修改seed/seed.jsonSchema 定义 演示内容集合、字段、菜单、块内容emdash-env.d.ts集合生成类型dev 启动时自动重生成src/layouts/Base.astro基础布局菜单、搜索、页面元信息、主题切换src/pages/Astro 页面全部服务端渲染astro.config.mjs 的集成要点astro.config.mjs 完整展示了 EmDash 在 Cloudflare 适配器下的接线方式import cloudflare from astrojs/cloudflare; import { d1, r2 } from emdash-cms/cloudflare; import emdash from emdash/astro; export default defineConfig({ output: server, adapter: cloudflare(), integrations: [ react(), icon({ include: { ph: [/* 仅打包实际引用的 Phosphor 图标 */] } }), emdash({ database: d1({ binding: DB, session: auto }), storage: r2({ binding: MEDIA }), plugins: [ { id: marketing-blocks, version: 0.1.0, // 必须使用 file:// 绝对 URL虚拟模块 emdash/plugins // 在构建期才能解析相对路径会失败 entrypoint: new URL(./src/plugins/marketing-blocks/index.ts, import.meta.url).href, }, ], }), ], fonts: [ { provider: fontProviders.google(), name: Inter, cssVariable: --font-body, weights: [400, 500, 600, 700, 800], fallbacks: [sans-serif], }, ], devToolbar: { enabled: false }, });几个值得注意的实现细节output: server所有内容页必须服务端渲染模板规则里明确禁止对 CMS 内容使用getStaticPaths()。插件入口必须用file://绝对 URL代码注释解释了原因——emdash/plugins是虚拟模块没有磁盘位置来锚定相对路径因此模板用new URL(./src/plugins/marketing-blocks/index.ts, import.meta.url).href构造绝对地址。图标按需打包icon()集成只打包模板实际引用的 Phosphor 图标如chart-bar、shield-check、users-three等 16 个避免把整个iconify-json/ph集数 MB打进 worker 包。对应 wrangler.jsonc 中的nodejs_compat与 cron 触发器。D1/R2 绑定数据库绑定DB、存储桶绑定MEDIA与 wrangler.jsonc 中的d1_databases、r2_buckets一一对应。Cloudflare 绑定wrangler.jsoncwrangler.jsonc 声明了运行所需的 Cloudflare 资源{ name: my-marketing-site, main: ./src/worker.ts, compatibility_date: 2026-02-24, compatibility_flags: [nodejs_compat], d1_databases: [{ binding: DB, database_name: my-marketing-site }], r2_buckets: [{ binding: MEDIA, bucket_name: my-marketing-media }], triggers: { crons: [* * * * *] } }沙箱化插件需要 Worker LoaderWorkers 付费套餐可用模板中以注释形式预留了worker_loaders配置项。页面结构首页 / 定价 / 联系模板共三个内容页见 src/pages/均在服务端用getEmDashEntry拉取内容页面路径内容Home/营销块任意排序hero、features、testimonials、pricing、FAQ以 Home 页面上的 Portable Text 文档形式编排Pricing/pricing同样的块驱动编辑用pricing块呈现「Simple, transparent pricing」Contact/contact左列联系方式Email / Support / Sales各带渐变图标右列表单页面数据获取范式以 src/pages/index.astro 与 src/pages/contact.astro 为例标准写法是--- import { getEmDashEntry } from emdash; import Base from ../layouts/Base.astro; import MarketingBlocks from ../components/MarketingBlocks.astro; const { entry: page, cacheHint } await getEmDashEntry(pages, home); try { Astro.cache.set(cacheHint); } catch {} --- Base title{page?.data.title} {page?.data.content MarketingBlocks value{page.data.content} /} /Base注意两点模板规则查询过内容的页面必须调用Astro.cache.set(cacheHint)设置缓存提示contact.astro 里用try/catch包裹因为该路由同时处理 POST 表单提交缓存 API 在非 GET 响应下可能拒绝调用。entry.id是 slug用于 URLentry.data.id是数据库 ULID用于getEntryTerms等 API 调用二者不要混淆。Contact 页的表单处理src/pages/contact.astro 展示了在 worker 内直接处理 POST 表单的模式校验必填字段name/email/message与邮箱格式成功后输出成功态 UI。文件注释明确说明这是演示代码——生产环境需要自行补充 CSRF token 校验、限流如通过 Cloudflare 或 middleware以及真实的邮件/Webhook 发送。内容模型pages 集合与 seed.jsonseed/seed.json 既是 schema 定义也是演示内容顶部meta描述为「A conversion-focused marketing site with landing pages」。核心模型{ settings: { title: Acme, tagline: Build products people actually want }, collections: [ { slug: pages, label: Pages, labelSingular: Page, supports: [drafts, revisions, seo], fields: [ { slug: title, label: Title, type: string, required: true }, { slug: content, label: Content, type: portableText } ] } ], menus: [/* 4 个菜单 */], content: { pages: [/* home / pricing / contact */] } }要点只有一个pages集合字段只有titlestring和contentportableText支持drafts、revisions、seo三种能力。没有分类法taxonomies。四个菜单primary顶部导航Features / Pricing / Contact、footer_product、footer_company、footer_support。菜单项类型为custom含label与url。站点设置只有title和tagline标题渲染在页头tagline 用于页脚与元信息。Base.astro 中用getSiteSettings()与getMenu(primary)等 API 消费这些数据Promise.all并行拉取 4 个菜单siteTitle/tagline 作为标题与描述的兜底值页脚按三个栏目渲染菜单。演示内容content.pages包含三页Home 编排了 hero features testimonials faq 四个块注意默认 seed 里 Home 没有 pricing 块Pricing 页编排 herocentered: true pricing三档套餐Pro 档highlighted: true faqContact 页只有居中的 hero。seed 里的示例文案如 Build products people actually want正是 AGENTS.md「What not to do」一节点名批评的占位话术用于演示而非上线文案。Marketing blocks 插件五类块与字段模板自带一个本地插件位于 src/plugins/marketing-blocks/index.ts。它通过definePlugin注册admin.portableTextBlocks让编辑者在管理后台的 Portable Text 编辑器里插入和编辑五类块const definition: PluginDefinition { id: marketing-blocks, version: 0.1.0, admin: { portableTextBlocks: [/* 五个块定义 */], }, }; export function createPlugin() { return definePlugin(definition); }五类块的类型名、用途与字段完整列表块类型用途字段marketing.hero大标题区块 可选 CTAheadline、subheadline多行、primaryCtaLabel、primaryCtaUrl、secondaryCtaLabel、secondaryCtaUrl、centeredtogglemarketing.features带图标的特性卡片网格headline、subheadline多行、repeaterfeatures{ icon(select), title, description(多行) }min 1 / max 12 项marketing.testimonials客户证言卡片headline、repeatertestimonials{ quote(多行), author, role, company, avatar(URL) }marketing.pricing定价套餐对比卡片headline、repeaterplans{ name, price, period, description(多行), features(多行), ctaLabel, ctaUrl, highlighted(toggle) }min 1 / max 6 项marketing.faq常见问题headline、repeateritems{ question, answer(多行) }插件文件头部注释与 AGENTS.md 共同强调了Block Kit 的四个关键约束理解它们才能正确扩展块没有嵌套对象元素CTA 的{ label, url }必须拍平为兄弟字段如primaryCtaLabelprimaryCtaUrl。渲染端读取扁平键——Hero.astro 里就是用node.primaryCtaLabel node.primaryCtaUrl重新组装出{ label, url }对象。Repeater 子字段只能是标量text_input、number_input、select、toggle。不允许嵌套 repeater列表型字符串如 pricing 的features用单个多行文本字段存储渲染时按换行拆分——Pricing.astro 中的实现为(plan.features ?? ).split(\n).map(s s.trim()).filter(Boolean)。插件块弹窗里还没有媒体选择器所有图片字段如 testimonial 的avatar都是手填 URL 字符串必须用真实 URL 而非占位符。marketing.hero的编辑器 schema 中没有图片字段Hero 渲染器在没有图片时回退到内置的/hero-visual.svg插画。要自定义 hero 主视觉可以替换 public/hero-visual.svg仓库还附带了备选 public/hero-visual-alt.svg或者扩展插件 schema 增加图片字段并同步更新 Hero.astro。Features 块的图标来自固定集合zap, shield, users, chart, code, globe, heart, star, check, lock, clock, cloud。插件里以ICON_OPTIONS数组定义见 index.ts渲染端 Features.astro 用iconMap把块值映射为 Phosphor 图标名如zap→ph:lightning未知图标回退到ph:sparkle。渲染链路从 Portable Text 到页面内容在 seed 中以 Portable Text 文档存储每个块是带_type与_key的对象渲染链路为页面调用getEmDashEntry(pages, slug)拿到entry.data.content传给 MarketingBlocks.astro该组件把五类marketing.*类型映射到 src/components/blocks/ 下的独立组件交给emdash/ui的PortableText渲染--- import { PortableText } from emdash/ui; import Hero from ./blocks/Hero.astro; // ... Features / Testimonials / Pricing / FAQ const marketingTypes { marketing.hero: Hero, marketing.features: Features, marketing.testimonials: Testimonials, marketing.pricing: Pricing, marketing.faq: FAQ, }; --- PortableText value{value} components{{ type: marketingTypes }} /每个块组件接收nodeprop块字段自行输出语义化 HTML 与作用域样式。块组件的样式全部依赖设计令牌var(--spacing-*)、var(--radius-*)、var(--gradient-*)等因此五个块天然跟随主题变量换肤。Base.astro 承担页面骨架EmDashHead注入 SEO 元信息通过createPublicPageContext构造页面上下文、Font cssVariable--font-body preload /预加载字体、粘性页头渲染 primary 菜单与 Admin 入口/_emdash/admin、页脚渲染三个菜单栏目底部还带一个 Light / Dark / System 三态主题切换器通过themecookie 记忆选择并用内联脚本在首帧前应用主题避免闪烁。视觉系统与设计令牌模板的视觉性格见 AGENTS.md「Visual character」一节字体Inter 作为--font-body字重到 800 用于标题强调--font-weight-display: 800用于 hero 与章节标题--font-weight-heading: 700用于其他标题。无等宽、无衬线。标题字距收紧--tracking-tight。主色板--color-brand: #6366f1indigo——品牌主色用于按钮和链接附带-strong/-soft深浅变体--color-accent: #f472b6pink——与品牌色组成渐变--color-success/--color-warning/--color-danger——语义色定价对勾、表单错误。渐变即令牌--gradient-brandlogo、图标磁贴、定价徽章、CTA hover、--gradient-brand-strongCTA 静止态、--gradient-brand-softhero 图片光晕、--gradient-headlinehero 标题文字填充。渐变跟随 brand/accent 自动生成重新品牌通常只需改--color-brand-*/--color-accent-*。共享工具类.section-header/.section-headline/.section-subheadline居中块引言、.icon-tile48px 渐变图标方块新块应复用而非各自重写。圆角与阴影--radius10px、--radius-lg16px、--radius-full胶囊--shadow-sm到--shadow-xl分层阴影。完整令牌清单见 src/styles/tokens.cssAGENTS.md 列出了常用变量品牌/强调色系、四组渐变、背景/表面/文字/弱化文字/边框色、字体与字重、--font-size-{xs…6xl}字阶最大 4.5rem 给 hero、圆角与阴影。主题定制与品牌换肤定制原则见 AGENTS.md「Customisation」一节设计令牌定义在src/styles/tokens.css覆盖写进src/styles/theme.css。theme.css 的声明是未分层unlayered的因此总是压过layer base的默认值。不要为视觉改动编辑 tokens.css 或 Base.astro——Base.astro 里通过layer base声明确立了「base 层优先级低于未分层样式」的层叠顺序。颜色用light-dark(light, dark)定义每个令牌同时携带明暗两种模式。用纯色覆盖会同时改变明暗想保持明暗区分覆盖时也要用light-dark()。无需维护独立的暗色板。字体配置在astro.config.mjs的fonts:数组换字体只需改绑定到cssVariable: --font-body那条的name:。Inter 加载了 5 个字重400–800支撑 hero 冲击力替换字体需保证相近的字重范围文档建议 Geist、Plus Jakarta Sans、Manrope、DM Sans。想要系统字体或独立的标题字体则覆盖theme.css里的--font-body/--font-heading走编辑/奢侈品风格的柔和调性通常还要把--font-weight-display降到 700 或更低。品牌换肤最高杠杆的四步原文顺序改--color-brand及其-strong/-soft变体与--color-accent——渐变会自动跟随更新站点标题logo 字标与 tagline在 admin 的站点设置中修改替换 hero 插画 URL换public/hero-visual.svg把 hero 的headline/subheadline块改成具体、明确的产品文案。另外注意src/styles/theme.css 是覆盖层渐变可以整体压成纯色模板「去掉渐变会显得平庸」但平涂品牌可把--gradient-*设为纯色但不要把渐变铺满每个交互元素——CTA 渐变是「信号」处处渐变就不再是信号。编辑与内容运维规则AGENTS.md 给出四条硬性开发规则写页面/查内容时必须遵守内容页必须服务端渲染output: serverCMS 内容禁止getStaticPaths()图片字段是对象{ src, alt }而非字符串用emdash/ui的Image image{...} /渲染entry.id是 slugURL 用entry.data.id是数据库 ULIDAPI 用查询过内容的页面必须调用Astro.cache.set(cacheHint)查询里的分类法名称必须与 seed 的name字段完全一致如category而非categories。「What not to do」清单则是一份写给 Agent 与人类的编辑守则不写流水线 SaaS 套话文案定价档位不超过三档三档是默认是有原因的——更多档位让选择更难而非更易不要混用插画与摄影两种风格不要在每处都开渐变不要连续两个 hero 块一个 hero 后接 features / testimonials / pricing / FAQ 的某种顺序不要用硬编码表格替换marketing.pricing块——块是下游渲染器期望的数据形态。参考资料模板入口说明templates/marketing-cloudflare/AGENTS.md构建配置templates/marketing-cloudflare/astro.config.mjs 与 templates/marketing-cloudflare/wrangler.jsonc内容模型与演示内容templates/marketing-cloudflare/seed/seed.json营销块插件templates/marketing-cloudflare/src/plugins/marketing-blocks/index.ts块渲染器templates/marketing-cloudflare/src/components/MarketingBlocks.astro 与 src/components/blocks/布局与令牌src/layouts/Base.astro、src/styles/tokens.css、src/styles/theme.css页面示例src/pages/index.astro、src/pages/pricing.astro、src/pages/contact.astro如需更系统的 EmDash 建站知识仓库还提供了building-emdash-site、creating-plugins、emdash-cli等 Agent 技能文档以及docs/下的技术文档与skills/目录中对应的 building-emdash-site、creating-plugins 技能说明可继续深入。赞分享CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载相关推荐Backstage backend-dev-utils 深度解析DevDataStore 的公共 API 表面、IPC 实现原理与真实用例Backstage backend dev utils 深度解析DevDataStore 的公共 API 表面、IPC 实现原理与真实用例 packages/CMS后端前端插件系统SEO Machine marketing-ideas 技能实战139 个 SaaS 营销策略的完整索引与落地指南SEO Machine marketing ideas 技能实战139 个 SaaS 营销策略的完整索引与落地指南 本篇技术指南围绕 SEO Machine人工智能AI 应用AI 写作AI 技能AI AgentTinaCMS 落地页内容建模实战解读 kitchen-sink 首页 home.md 的 blocks 结构TinaCMS 落地页内容建模实战解读 kitchen sink 首页 home.md 的 blocks 结构 home.md 是 TinaCMS 仓库中 kCMS前端后端GraphQL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

9款AI写论文哪个好?我测完发现,能“把数据画出来”的只有这一款

9款AI写论文哪个好?我测完发现,能“把数据画出来”的只有这一款

aigcbiye官网 微信公众号搜一搜 aigcbiye 你写过论文你就知道,最折磨人的环节从来不是“写”。 是写到一半发现,你得有个图。 是导师看完初稿说“这里放个折线图会更清楚”,然后你打开Excel开始手动录数据。是审稿人批注“Figure 2 lacks …

📅 2026/9/23 23:23:44
基于Java的就业信息管理系统:技术选型、表结构设计与核心业务实现

基于Java的就业信息管理系统:技术选型、表结构设计与核心业务实现

简介:这是一套基于Java技术栈的就业信息管理系统完整源码,面向计算机相关专业学生、Java后端初学者及需要课程设计或毕业设计参考的开发者,帮助解决数据管理、可视化分析与权限控制等实际业务问题。资源包共825个文件,约24.36MB&a…

📅 2026/9/23 23:23:44
写论文软件哪个好?别问“哪个好”,先问你的论文“死”在哪一步——聊聊aigcbiye的毕业论文功能

写论文软件哪个好?别问“哪个好”,先问你的论文“死”在哪一步——聊聊aigcbiye的毕业论文功能

aigcbiye官网 微信公众号搜一搜 aigcbiye 各位同学好,我是那个教你们写论文的博主。 每次直播,弹幕里飘得最多的一个问题就是:“博主,写论文软件哪个好?” 这个问题我一开始还认真回答,后来发现根本答不…

📅 2026/9/23 23:23:44
MORE NEWS

更多资讯

📰

JavaScript数组遍历方法选型指南:for、for of、for in与函数式API的正确使用场景

1. 这不是语法考试,是日常开发中每天要做的“选择题”你写过多少次遍历数组的代码?我数不清了。但每次敲下for、forEach、map的时候,有没有真正想过:为什么这里非得用for of而不是for in?为什么filter返回新数组却不能…

📰

USDT多链收款平台:一套SDK打通TRC20/ERC20/BEP20/Polygon

简介:这是一套面向开发者与支付系统集成方的 USDT 收款接口服务资源,聚焦 Tron(波场)生态,提供 USDT-TRC20 与 TRX 的完整收款方案,适合需要为平台快速接入加密货币支付、又希望降低对接成本的技术人员。资…

📰

结构化数据实战指南:JSON-LD与微数据选型与避坑

1. 这不是“加个标签”那么简单:微数据和结构化数据到底在解决什么问题? 你有没有遇到过这样的场景:自己辛辛苦苦写了一篇关于“北京故宫门票预约指南”的HTML页面,图文并茂、逻辑清晰、SEO关键词也埋得恰到好处,结果…

📰

零成本自建企业H5场景秀平台:响应式框架与源码二次开发实战

做一个企业自己的H5场景秀平台,这个需求这几年越来越多。市场部的同事拿着第三方H5工具的报价单来找我时,那种感觉大概就是——你说它贵吧,一年大几千确实不便宜,你说自己开发吧,又怕搞不定。其实这事没有那么玄乎&…

📰

StrokeGen实战:GPU实时高质量卡通描边与笔画生成管线

1. 为什么卡渲描边是个“看起来简单、做起来头大”的活先聊个现象。我接触过不少刚入行做卡通渲染的同学,第一反应都是“描边嘛,边缘检测或者反向膨胀,随便搞搞就能出效果”。可真把项目跑起来,发现根本不是这么回事:线…

📰

Cesium地形开挖实战:裁剪平面原理、代码实现与避坑指南

简介:面向Cesium初学者与前端开发者的地形开挖示例包,通过单个HTML文件完整演示了基于Cesium的三维地形开挖核心实现。压缩包内仅含1个HTML文件,大小仅1KB,代码集中,可直接在浏览器中运行,适合作为入门模板…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬