TinaCMS 落地页内容建模实战:解读 kitchen-sink 首页 home.md 的 blocks 结构
【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo 🦙 ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacms
home.md是 TinaCMS 仓库中 kitchen-sink 示例(Next.js / Astro / Hugo / React 多框架版本)共享的首页内容文件,它以 Markdown frontmatter 中的blocks数组描述整张落地页的区块结构,是理解 TinaCMS「Git-backed 内容 + 可视化编辑」工作流的最佳入门样本。读完本文,你将掌握 TinaCMS 的页面级 collection 建模方式、hero / features / cta / testimonial 四个内置模板的数据契约、blocks 从前台数据到 React 组件的完整渲染链路,并能在自己的站点中按相同模式新增或调整页面区块。
home.md 在示例工程中的定位:共享内容、多框架渲染
文件位于 examples/shared/content/pages/home.md,是examples/shared共享内容目录的一部分。从仓库目录结构可以观察到,examples/next/kitchen-sink、examples/astro/kitchen-sink、examples/hugo/kitchen-sink、examples/react/kitchen-sink等示例工程均未自带content/pages目录,而是统一复用examples/shared/content下的内容,再分别用 Next.js、Astro、Hugo、React 等不同技术栈渲染同一份数据,这本身就是 TinaCMS「内容与展示解耦」理念的直观体现。
home.md全文是一个标准的 Markdown frontmatter 文件,---之间只有blocks一个顶层键,其值为一个有序数组,依次声明了 4 个区块:
hero(首屏横幅)features(特性列表)cta(行动号召)testimonial(用户引语)
每个区块对象都带有一个_template字段,用于指定它属于哪种模板类型——这正是 TinaCMS 的「blocks 模板系统」在数据层的落点:内容文件中只存结构化数据,区块的类型与字段结构由_template声明,而字段如何渲染则由前端组件决定。
认识 page collection:blocks 字段如何被建模
要让上述 Markdown 数据在 TinaCMS 后台可编辑,必须先有对应的 collection 定义。kitchen-sink 示例的 page collection 位于 examples/next/kitchen-sink/tina/collections/page.tsx:
const Page: Collection = { label: 'Pages', name: 'page', path: 'content/pages', format: 'md', ui: { router: ({ document }) => { const filepath = document._sys.breadcrumbs.join('/'); if (filepath === 'home') { return '/'; // 首页路由映射到站点根路径 } return `/${filepath}`; }, }, fields: [ { type: 'object', list: true, name: 'blocks', label: 'Sections', ui: { visualSelector: true }, templates: [ heroBlockSchema, featureBlockSchema, ctaBlockSchema, testimonialBlockSchema, contentBlockSchema, ], }, { name: 'image', label: 'Image', type: 'image', accept: 'image' }, ], };关键点解读:
path: 'content/pages'将该 collection 绑定到内容目录下的pages文件夹,home.md正是该目录下的文档;format: 'md'说明内容以 Markdown 存储,blocks数据序列化在 frontmatter 中;blocks字段是type: 'object'+list: true的组合,即「对象数组」,每个数组元素从templates列表中按_template选择具体模板;ui.visualSelector: true开启后台的可视化区块选择器,编辑器可以直接增删、排序、更换区块;ui.router自定义前台预览路由:文件名home映射到/,其余页面映射到/<文件名>。
值得一提的是,templates中声明的 5 种模板(hero、features、cta、testimonial、content)中,前 4 种恰好覆盖了home.md的 4 个区块,content模板则为其他页面(如 examples/shared/content/pages/projects-built-with-tina.md)提供富文本内容块能力。
逐块拆解 home.md:四个内置模板的数据契约
hero:首屏横幅
home.md中的 hero 区块数据:
- tagline: Open-source CMS headline: The best editor experience for your developer-first sites text: | Tina is an open-source, Git-backed CMS with the ability to add visual editing to your NextJS site actions: - label: Get Started type: button link: 'https://tina.io' color: default _template: hero对应的模板 schema 定义在 examples/next/kitchen-sink/components/blocks/hero.tsx 的heroBlockSchema中,字段契约如下:
| 字段 | 类型 | 说明 |
|---|---|---|
tagline | string | 标题上方的小字标签,带胶囊背景 |
headline | string | 大号主标题 |
text | rich-text | 副文案,渲染为富文本(Markdown) |
image | object | 可选图片对象(src+alt),未设置则不渲染 |
backgroundImage | image | 可选背景图,accept: 'png' |
actions | object list | 按钮/链接列表(详见下文共享字段) |
color | string | 区块主题色:default/tint/primary |
hero.tsx中还给出了模板的defaultItem(编辑器新增区块时的预填内容),且ui.previewSrc: '/blocks/hero.png'指定了后台的区块预览缩略图——这正是 examples/shared/public/blocks/hero.png 的用途。
从渲染组件看,text字段通过TinaMarkdown渲染并支持自定义 Markdown 组件(customComponents),actions则交由Actions布局组件输出按钮组;组件上到处可见data-tina-field={tinaField(data, 'xxx')}标记,这些标记是可视化编辑(inline editing)时定位 DOM 与字段映射的关键。
features:特性列表
home.md中的 features 区块声明了标题、描述和 3 个特性条目,每个条目包含图标、标题和说明文字:
- title: Features description: Everything you need to build a great content editing experience. items: - icon: { name: BiSearchAlt2, color: primary, style: circle } title: Query Your Content text: Use GraphQL to query your content in any way you need. - icon: { name: BiLayer, color: teal, style: circle } title: Build on Top of Your Components text: Tina works alongside your existing component library. - icon: { name: BiTerminal, color: green, style: circle } title: Command Line Quickstart text: Get started in minutes with a single CLI command. color: default _template: features其模板 schema 位于 examples/next/kitchen-sink/components/blocks/features.tsx 的featureBlockSchema:
title/description:区块标题与描述(描述使用textarea组件);items:list: true的对象数组,每个条目包含icon(复用iconSchema,配置name图标名、color主题色、style样式如circle)、title、text、actions;ui.itemProps将条目列表的显示标签设为条目的title,便于后台识别;- 渲染组件对条目做了向后兼容处理:条目既可以是对象,也可以是纯字符串(简单卡片布局),说明 blocks 数据结构的演进需要兼顾旧数据。
cta:行动号召
- title: New to Tina? description: Learn the basics of the development workflow actions: - label: Check out the docs type: button link: 'https://tina.io/docs/' color: tint _template: ctacta 模板(examples/next/kitchen-sink/components/blocks/cta.tsx)的数据结构最为精简:title+description+actions+color。渲染时标题居中、描述跟随、动作按钮以Actions组件渲染。这个区块常被用作落地页的转化收尾区域,color: tint让它在页面中呈现与 hero(default)不同的底色层次。
testimonial:用户引语
- quote: 'There are only two hard things in Computer Science: cache invalidation and naming things.' author: Phil Karlton color: primary _template: testimonialtestimonial 模板(examples/next/kitchen-sink/components/blocks/testimonial.tsx)由quote(textarea)、author、color三个字段构成,渲染为带装饰性引号的大号块引用(blockquote),color: primary时使用高对比的主题色背景。有趣的是,该模板 schema 中的defaultItem恰好就是 home.md 里这条著名的 Phil Karlton 语录,说明这段示例内容正是从模板默认项沿用而来的。
共享字段:actions 与 color 的复用设计
四个区块反复出现actions与color两个字段,它们不是各自复制粘贴,而是抽取自 examples/next/kitchen-sink/tina/schemas/shared-fields.ts,这是 TinaCMS schema 工程化的常见手法。
actionsFieldSchema定义了按钮/链接列表:
export const actionsFieldSchema = { label: 'Actions', name: 'actions', type: 'object', list: true, ui: { defaultItem: { label: 'Action Label', type: 'button', icon: true, link: '/' }, itemProps: (item: any) => ({ label: item.label }), }, fields: [ { label: 'Label', name: 'label', type: 'string' }, { label: 'Type', name: 'type', type: 'string', options: [ { label: 'Button', value: 'button' }, { label: 'Link', value: 'link' }, ], }, { label: 'Link', name: 'link', type: 'string' }, { label: 'Icon', name: 'icon', type: 'boolean' }, ], };colorFieldSchema则把区块底色限定为default/tint/primary三个选项,保证视觉风格可控。shared-fields.ts还提供了makeSlugify、tagsFieldSchema、dateFieldSchemas等其他可复用片段,可整体作为团队级 schema 约定的参考范式。
从 Markdown 到页面:blocks 的渲染链路
理解了数据与 schema,再看前端如何把home.md变成真实页面。以 Next.js 版本为例,渲染链路分为两层:
第一层:数据获取与可视化订阅。examples/next/kitchen-sink/app/[...urlSegments]/client-page.tsx 是页面客户端组件,它接收服务端通过 Tina GraphQL 查询得到的query/variables/data,调用useTina完成内容订阅——编辑模式下数据变更会实时回流,构建模式下则直接使用静态数据:
const { data } = useTina({ ...props }); const page = data?.page; // ... <Blocks blocks={page.blocks} />第二层:区块分发渲染。examples/next/kitchen-sink/components/blocks/index.tsx 中的Blocks组件遍历blocks数组,依据_template(或由__typename反查的模板名)通过switch分发到对应的动态导入组件:
const template = blockWithMeta._template || typeNameMap[typename] || typename; switch (template) { case 'hero': content = <Hero data={...} />; break; case 'features': content = <Features data={...} />; break; case 'cta': content = <CTA data={...} />; break; case 'testimonial': content = <Testimonial data={...} />; break; case 'content': content = <Content data={...} />; break; default: // 未知模板给出黄色告警占位 }这里使用next/dynamic做按需加载,且保留了新旧两套__typename命名(PageBlocksHero与旧的PageBlockPageBlocksHero)的兼容映射,避免 schema 重新生成后破坏既有内容。遇到未知模板时渲染黄色告警占位,保证页面不会因数据异常而崩溃。
实操:如何扩展首页区块
基于以上机制,扩展现有首页有几种典型操作:
- 给 hero 增加按钮:在
home.md的 heroactions列表追加一个条目,type可选button或link,icon控制是否显示箭头图标;也可以在 TinaCMS 后台表单中直接点击添加。 - 新增特性条目:在 features 的
items下追加{ icon: {...}, title, text },icon.name填入图标库名称(如BiSearchAlt2、BiLayer、BiTerminal),icon.color与icon.style控制图标外观。 - 切换区块主题色:将任意区块的
color在default/tint/primary之间调整,即可改变该区块的视觉层次。 - 调整区块顺序:由于
blocks是有序数组,调整数组元素顺序即改变页面区块的上下排列;后台编辑器中通过拖拽或上下移动也能完成同样操作。 - 新增模板类型:若需要全新区块,在
templates中注册新的xxxBlockSchema,在 components/blocks/index.tsx 的typeNameMap与switch中补充分发逻辑,即可让该模板出现在后台的区块选择器与前端渲染中。
小结
home.md虽然只是一份十几行的 Markdown 文件,却是理解 TinaCMS 内容建模范式的浓缩样本:frontmatter 中的blocks数组与_template标记构成「数据即结构」的内容层,page.tsxcollection 完成 schema 契约的声明,各 block schema 与共享字段决定后台表单形态,而client-page.tsx+blocks/index.tsx完成从数据到组件的渲染闭环。这种「Git 仓库存内容、GraphQL 查内容、可视化编辑器改内容」的架构,正是 TinaCMS 面向 developer-first 站点的核心设计,也是你在自己的 Next.js / Astro / Hugo / React 项目中落地同类 CMS 方案的直接参考。
【免费下载链接】tinacmsTinaCMS is the leading open-source headless CMS that supports Markdown and Visual Editing. Your content is stored in your own GitHub repo 🦙 ❤️项目地址: https://gitcode.com/GitHub_Trending/ti/tinacms
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考