Tanplate Docs

Blog

Git 管理的 Blog、构建期发布索引、shadcn Typeset 与 Shiki 代码高亮。

Blog 是 Manifest 控制的 Git Content 模块。文章源位于 apps/web/content/blog,构建时校验并生成索引;Web 不在运行时读取 Git 文件,也不把 Blog 变成 D1 CMS。

新建文章

文件名必须与 slug 一致:

---
kind: blog
slug: building-clear-boundaries
title: Building clear boundaries
description: A concise description that satisfies the validated content boundary.
status: published
publishedAt: 2026-07-23
author: Tanplate
tags:
  - architecture
---

Article body.

draft 文章、未来 publishedAt 文章和 Manifest 关闭的内容类型不会进入生产输出。frontmatter、内部链接、允许的 MDX 节点和正文结构在构建前统一校验,失败会阻断构建。

路由与组件

pages/_app/blog/
  index.tsx
  $slug.tsx
  -components/
    blog-list.tsx
    blog-detail.tsx
    blog-content.tsx
    blog-code-block.tsx

两个路由保持薄适配:列表读取已发布索引,详情按 slug 读取并对未知文章返回 404。页面结构、正文排版和代码高亮全部留在 Blog 私有 -components

Typeset 正文

blog-content.tsx 使用 React Markdown + GFM,并把正文放入 shadcn Typeset 的 typeset 容器。链接、表格和 fenced code 通过显式组件映射处理:

  • 原始 HTML 被跳过。
  • 外部链接增加 noreferrer
  • 宽表格进入 typeset-scroll 横向滚动容器。
  • allowlisted MDX 先经过构建期转换,不执行任意组件或脚本。

这套排版来自 shadcn Typeset 的全局样式,Blog 组件不复制一套平行的 prose 主题。

Shiki 代码高亮

SSR 首屏输出可读的纯文本 <pre><code>,浏览器随后懒加载 shiki/core、JavaScript regex engine、当前语言和 GitHub light/dark 主题。高亮失败或遇到不支持的语言时保留纯文本,不阻断文章。

当前按需支持 CSS、HTML、JavaScript/JSX、JSON、Markdown、Shell、TypeScript/TSX 和 YAML;jstsbash 等常用别名会先规范化。主题输出使用 Shiki 双主题 CSS 变量,跟随站点明暗模式。

验证

pnpm --filter web test
pnpm --filter web test:e2e:content
pnpm build:web

新增或修改文章后同步 apps/web/content/blog/.folder.md。修改渲染组件时还要同步 pages/_app/blog/-components/.folder.md 与对应文件 Header。

On this page