ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

EmDash 博客模板实战指南:基于 Astro 的 CMS 站点结构、内容模型与主题定制

EmDash 博客模板实战指南:基于 Astro 的 CMS 站点结构、内容模型与主题定制 CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载EmDash 是一个基于 Astro 构建的全栈 TypeScript CMS被项目描述为 WordPress 的精神续作而templates/blog正是官方为以写作为核心产品的博客场景准备的完整模板。本文以 templates/blog/CLAUDE.md 为骨架结合模板内的源码、配置与种子数据系统讲解该模板的启动命令、关键文件职责、内容 Schema 设计、页面路由实现、视觉系统与定制方法帮助你快速上手并二次开发一个属于自己的 EmDash 博客站点。模板定位一个写作即产品的博客根据 CLAUDE.md 中的模板说明这是一个包含posts文章、pages页面、categories分类、tags标签、全文搜索与 RSS的博客模板定位是个人写作、技术写作、独立通讯indie newsletters以及任何以写作为核心产品的场景。它的视觉基调是编辑部技术美学editorial-tech aesthetic自信的无衬线字体、克制的强调色、带 bylines署名与阅读时间reading time的真实文章结构。整套模板由以下文件构成位于 templates/blog文件/目录用途astro.config.mjsAstro 配置包含emdash()集成、数据库与存储src/live.config.tsEmDash loader 注册样板代码勿修改seed/seed.jsonSchema 定义 演示内容collections、fields、taxonomies、menus、widgetsemdash-env.d.ts集合的生成类型dev server 启动时自动重新生成src/layouts/Base.astro基础布局承载 EmDash 接线菜单、搜索、页面贡献src/pages/Astro 页面——全部服务端渲染快速启动两条命令跑起来CLAUDE.md 给出了最核心的两条命令pnpm dev # 启动 Astro 开发服务器 npx emdash types # 根据运行中的站点重新生成 TypeScript 类型配套脚本在 package.json 中定义完整devastro dev、buildastro build、previewastro preview、startnode ./dist/server/entry.mjs、typecheckastro check。其中start表明该模板构建后以Node 独立模式standalone运行。管理后台Admin UI地址为http://localhost:4321/_emdash/admin。开发模式下启动后即可在后台登录、写文章、管理分类标签所有改动实时反映到前台页面。类型生成机制npx emdash types会基于运行中的站点即当前 seed 的集合与字段定义重新生成 emdash-env.d.ts。这个文件的类型会在 dev server 启动时自动重新生成因此当你修改了 seed 中的字段后重启开发服务器即可获得带完整类型提示的查询 API 体验。关键文件地图CLAUDE.md 用一张表概括了核心文件职责理解它们就等于理解了模板的运行骨架astro.config.mjs— Astro 配置含emdash()集成、数据库和存储配置src/live.config.ts— EmDash loader 注册属于样板代码不要修改seed/seed.json— Schema 定义与演示内容集合、字段、分类法、菜单、组件区emdash-env.d.ts— 集合的生成类型src/layouts/Base.astro— 基础布局含 EmDash 接线菜单、搜索、页面贡献src/pages/— 全部服务端渲染的 Astro 页面。架构核心emdash()集成、数据库与存储astro.config.mjs 是整个模板的装配中心import node from astrojs/node; import react from astrojs/react; import auditLog from emdash-cms/plugin-audit-log; import { defineConfig, fontProviders } from astro/config; import emdash, { local } from emdash/astro; import { sqlite } from emdash/db; export default defineConfig({ output: server, adapter: node({ mode: standalone, }), image: { layout: constrained, responsiveStyles: true, }, integrations: [ react(), emdash({ database: sqlite({ url: file:./data.db }), storage: local({ directory: ./uploads, baseUrl: /_emdash/api/media/file, }), plugins: [auditLog], }), ], fonts: [ /* 见下文字体管线 */ ], devToolbar: { enabled: false }, });要点解读output: server Node adapter这呼应了 CLAUDE.md 的硬性规则——所有内容页面必须服务端渲染禁止为 CMS 内容使用getStaticPaths()emdash()集成接收三类配置database这里用sqlite({ url: file:./data.db })本地开发默认 SQLite 单文件数据库storagelocal({ directory: ./uploads, baseUrl: /_emdash/api/media/file })媒体文件存储在./uploads通过/_emdash/api/media/file对外提供plugins默认挂载了emdash-cms/plugin-audit-log审计日志插件这是工作区内的官方插件react()集成用于后台管理 UI 与评论组件等 React 渲染部分devToolbar: { enabled: false }关闭了 Astro 默认的 dev toolbar。内容加载器live.config.tssrc/live.config.ts 定义了 EmDash 的 Live Content Collectionsimport { defineLiveCollection } from astro:content; import { emdashLoader } from emdash/runtime; export const collections { _emdash: defineLiveCollection({ loader: emdashLoader() }), };它建立了_emdash集合覆盖数据库中所有内容类型。页面中通过getEmDashCollection()与getEmDashEntry()按类型查询具体内容——这正是 CLAUDE.md 要求不要修改的原因它是模板与 EmDash 运行时之间的固定接线。内容 Schemaseed.json 决定一切CLAUDE.md 中的 Schema 一节可以用 seed/seed.json 完整印证。整个文件以$schema声明、version: 1开头meta提供元信息然后依次定义settings站点设置settings: { title: My Blog, tagline: Thoughts on building for the web }CLAUDE.md 指出站点设置的title和tagline都会渲染在 header / footer 中。模板的 site-identity.ts 会读取它们并解析出siteTitle、siteTagline、siteLogo。collections集合posts集合字段titlestring必填可搜索——文章标题featured_imageimage——头图contentportableText可搜索——正文Portable Text 富文本excerpttext——摘要。posts的supports声明为[drafts, revisions, search, seo]即支持草稿、修订历史、全文搜索与 SEO且commentsEnabled: true开启了评论。pages集合字段titlestring必填可搜索contentportableText可搜索。用于/about等静态页面。taxonomies分类法{ name: category, label: Categories, hierarchical: true, collections: [posts], terms: [...] } { name: tag, label: Tags, hierarchical: false, collections: [posts], terms: [...] }注意name是查询时使用的精确标识如category而非categories——这是 CLAUDE.md 规则列表中的明确要求。分类是层级化的hierarchical: true标签则扁平。种子数据中分类含 development / design / notes标签含 webdev / opinion / tools / creativity。bylines署名bylines: [ { id: byline-editorial, slug: emdash-editorial, displayName: EmDash Editorial }, { id: byline-guest, slug: guest-contributor, displayName: Guest Contributor, isGuest: true } ]文章通过bylines关联作者署名isGuest标记客座作者。menus菜单单一的primary菜单默认包含 Home、About、Posts 三个自定义链接项type: custom。此外 Base.astro 还会尝试读取可选的social菜单用于页脚Connect栏——如果 seed 未定义该栏只显示 RSS。widgetAreas组件区seed 定义了sidebar单篇文章页右侧栏与footer页脚两个组件区sidebar 挂载了core:search搜索、core:categories分类、core:tags标签、core:recent-posts最新文章count: 5、showDate: true、core:archives归档月度、limit: 6footer 挂载了一个content类型的小组件渲染一段 Portable Text 简介。sections区块与 content内容newsletter-signup与about-author两个 theme 区块带keywords便于检索复用以及 7 篇演示文章 1 篇草稿status: draft草稿不会出现在公开列表和 1 个 About 页面。演示文章使用$media语法引用外部图片作为featured_image每篇均声明了bylines与taxonomies归属。页面与路由每个 URL 都对应一个 Astro 文件CLAUDE.md 的 Pages 表列出了模板的完整路由在 src/pages 中一一对应页面路径内容首页/精选文章 Hero大图 摘要、最新文章网格全部文章/posts文章计数、带摘要与标签徽章的文章列表文章详情/posts/[slug]头图、标题、正文、左侧元信息列作者 日期、右侧 TOC 搜索 分类栏搜索/search全文搜索 UI页面/pages/[slug]静态页面内容Portable Text分类/category/[slug]按分类过滤的文章标签/tag/[slug]按标签过滤的文章RSS/rss.xml生成的 feed首页的数据查询模式src/pages/index.astro 是理解模板查询约定的最佳范例用getEmDashCollection(posts, { orderBy: { published_at: desc }, limit: POSTS_PER_PAGE 1 })让数据库做切片POSTS_PER_PAGE 7多取 1 条用于判断是否显示View all而不是拉全量再在 JS 里裁剪自动挑选第一篇有featured_image的文章作为 Hero其余进网格用getTermsForEntries(posts, ids, tag)一次性批量查询多篇文章的标签避免逐篇调用getEntryTerms()造成 N1 查询查完内容后立即Astro.cache.set(cacheHint)。文章详情页的三栏阅读布局src/pages/posts/[slug].astro 实现了 CLAUDE.md 强调的招牌三栏阅读视图左侧元信息列--meta-col-width180pxsticky 定位展示 bylines 头像与署名、发布时间、阅读时间、标签中间正文列--content-width680pxPortableText value{post.data.content} /渲染富文本并用Image组件渲染头图右侧栏--gutter-width200px客户端脚本从正文的 h2/h3 构建 TOC带 IntersectionObserver 滚动高亮下方是WidgetArea namesidebar /渲染的侧栏组件区底部还有Continue reading相关文章区块与Comments/CommentForm评论系统seed 中commentsEnabled: true。页面还展示了 SEO 的完整链路getSeoMeta(post, {...})生成标题、描述、OG 图、canonical、robots再通过getImageUrl()从图片对象src或meta.storageKey推导 OG 回退图最后以createPublicPageContext()注入 Base 布局。搜索页走 FTS 而不是 JS 过滤src/pages/search.astro 的注释点明了设计意图调用 EmDash 的search(query, { collections: [posts], limit: 30 })全文搜索 API由数据库完成分词、词干化与排序而不是把全部文章拉到 JS 里过滤——后者在文章数超过几百篇后会迅速不可用。返回结果中的snippet已包含mark高亮标签页面用set:html渲染。六条硬性规则来自 CLAUDE.md所有内容页面必须服务端渲染output: serverCMS 内容禁用getStaticPaths()图片字段是对象{ src, alt }而非字符串必须用emdash/ui的Image image{...} /渲染entry.id是 slug用于 URLentry.data.id是数据库 ULID用于getEntryTerms等 API 调用查询内容的页面必须调用Astro.cache.set(cacheHint)设置缓存提示查询中的分类法名称必须与 seed 的name字段完全一致例如category而不是categories。这些规则在源码中都能找到对应实现所有页面均带cacheHint调用getTermsForEntries使用entry.data.id页面跳转链接使用p.idslug。视觉系统单字体、单强调色、三栏文章版式CLAUDE.md 的 Visual character 一节精确描述了模板的视觉 DNA源码可在 src/styles/tokens.css 验证单一字体族全站使用Inter绑定--font-body标题默认复用正文字体靠字重与字号建立层级--font-weight-heading600、--font-weight-display700 用于 h1/页标题h1/h2 收紧字距--tracking-tight/--tracking-snugJetBrains Mono绑定--font-mono用于行内代码与代码块品牌色#0066cc--color-brand用于链接、文章卡片标题 hover 与搜索框 focus 光环另有--color-text-secondary与--color-muted用于次级文本与元信息。不要添加第二个强调色文章三栏版式是标志性功能左栏元信息、中间 680px 正文、右栏搜索 TOC 分类。桌面端不要把它压成一栏——这个布局在向读者传递这是值得阅读的内容。深色模式与主题切换tokens.css 中所有颜色都用light-dark(light, dark)定义同一个 token 同时携带明暗两套值无需维护单独的暗色面板。Base.astro 的内联脚本会在页面渲染前立即根据themecookie 应用主题防止闪烁页脚提供 light / dark / system 三个切换按钮通过写themecookie 与给html加 class 实现。此外还有针对不支持light-dark()的旧浏览器Safari 17.5、Chrome 123的纯亮色回退块。定制化token 覆盖、字体管线与 CSS 变量清单设计 token 的分层覆盖机制CLAUDE.md 明确指出设计 token 的默认值全部在src/styles/tokens.css而重新换肤应该改src/styles/theme.css——因为 theme.css 中的声明是**无分层unlayered**的永远压过layer base的默认值无需技巧性的选择器优先级对抗。不要为了视觉改动而去编辑tokens.css或Base.astro。theme.css 的注释给出了示例:root { --color-brand: light-dark(#0f766e, #2dd4bf); --font-heading: Iowan Old Style, Georgia, serif; --radius: 8px; }覆盖颜色的两条规则用纯色值覆盖会同时改变明暗两套模式想保持明暗区分就用light-dark(light, dark)覆盖。字体管线astro.config.mjs 的 fonts 配置Webfont 在 astro.config.mjs 的fonts:数组中配置fonts: [ { provider: fontProviders.google(), name: Inter, cssVariable: --font-body, weights: [400, 500, 600, 700], fallbacks: [sans-serif], }, { provider: fontProviders.google(), name: JetBrains Mono, cssVariable: --font-mono, weights: [400, 500], fallbacks: [monospace], }, ],换正文衬线字体的操作是修改绑定cssVariable: --font-body的条目的name。CLAUDE.md 推荐的无衬线替代Geist、IBM Plex Sans、Söhne需授权、Public Sans如果想要衬线正文博客可换 Source Serif、Crimson Pro 或 Lora——但换衬线后要把--font-size-base提到1.0625rem以保可读性。若只想让标题用别的字体或改用系统字体而不碰字体管线直接在 theme.css 覆盖--font-heading或--font-body即可。Base.astro 通过Font cssVariable--font-body preload /加载并预取字体。值得掌握的 CSS 变量完整列表见 tokens.css品牌与配色--color-brand、--color-brand-hover、--color-on-brand、--color-brand-ring页面配色--color-bg、--color-bg-subtle、--color-surface、--color-text、--color-text-secondary、--color-muted、--color-border、--color-border-subtle字体--font-body、--font-heading、--font-mono字重--font-weight-heading600/--font-weight-display700——换衬线时可调低字距--tracking-tight/--tracking-snug/--tracking-wide/--tracking-wider用于标题与元信息标签布局--content-width680px正文列、--wide-width1200px最大容器、--gutter-width200px文章页右侧 TOC 栏、--meta-col-width180px文章页左侧元信息列头像--avatar-size-{xs,sm,md,lg}对应卡片、列表、精选、单篇文章等不同尺度的 byline 头像。值得留意的是 tokens.css 中的全套字号阶梯--font-size-xs到--font-size-5xl、行高--leading-tight到--leading-relaxed、间距--spacing-1到--spacing-24与阴影 token--shadow-sm/--shadow-lg它们共同支撑了整套版式的统一性。反向清单不要做什么CLAUDE.md 的 What not to do 是一份极具实操价值的边界清单不要添加第二个强调色或彩色区块背景——页面应该是黑、白、一种蓝不要用展示型无衬线体Bebas、Anton 等替换 Inter——标题层级靠字重而非新奇字体不要在桌面端折叠文章侧栏——它是阅读体验的一部分不要用模板式博客文案Welcome to my blog、Stay tuned for more——写一句真正说明这个博客是干什么的 tagline不要用三篇一模一样的占位文章填充首页——只有一篇真实文章就展示一篇不要在没有审核计划时开启评论——模板默认不附带评论系统是有原因的。Agent 技能与文档接入面向 AI 编码工具CLAUDE.md 的 Skills 与 Documentation 两节面向 AI Agent 场景但同样值得人类开发者了解技能存放于.agents/skills/按任务加载building-emdash-site内容查询、Portable Text 渲染、Schema 设计、seed 文件、菜单/组件区/搜索/SEO/评论/byline 等站点特性建议从这里开始、creating-plugins用 hooks、storage、admin UI、API routes 与 Portable Text block 类型构建插件、emdash-cli内容管理、seed、类型生成与可视化编辑流程的 CLI 命令EmDash 文档以 MCP server 形式提供模板自带了.mcp.json、.cursor/mcp.json、.vscode/mcp.json使 Claude Code、Cursor、VS Code 能自动发现文档服务器其他工具OpenCode、Windsurf 等需要一次性手动配置。延伸阅读模板根说明templates/blog/README.md若存在Agent 模板约定templates/blog/AGENTS.md 与 templates/blog/AGENTS-template.md版本变更记录templates/blog/CHANGELOG.md同系列云托管模板templates/blog-cloudflareCloudflare Workers 版本以及 marketing、portfolio、starter 等姊妹模板见 templates全仓库技能库skills/building-emdash-site/SKILL.md、skills/creating-plugins/SKILL.md、skills/emdash-cli/SKILL.md赞分享CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载相关推荐EmDash 博客模板深度指南基于 Astro 的全栈 CMS 站点搭建与定制EmDash 博客模板深度指南基于 Astro 的全栈 CMS 站点搭建与定制 EmDash 是一个基于 Astro 构建的全栈 TypeScript CMSCMS后端前端插件系统EmDash 博客模板Cloudflare 版实战指南基于 Astro D1 R2 的编辑器优先 CMS 站点搭建EmDash 博客模板Cloudflare 版实战指南基于 Astro D1 R2 的编辑器优先 CMS 站点搭建 本指南围绕 EmDash 官方CMS后端前端插件系统EmDash Blank 模板实战基于 Astro 从零搭建无预设 CMS 站点的最小基底EmDash Blank 模板实战基于 Astro 从零搭建无预设 CMS 站点的最小基底 导读 templates/blank 是 EmDash一个构建在CMS后端前端插件系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表