博客
学习如何创建、管理和自定义支持多语言的博客文章
MkSaaS 包含一个基于 Fumadocs MDX 构建的强大博客系统。博客系统支持多语言内容、分类、作者和丰富的内容格式,非常适合 SaaS 营销、公告、教程和知识库文章。
博客系统架构
博客系统使用 Fumadocs MDX 构建,并与国际化集成。
blog-card.tsx
blog-grid.tsx
blog-category-filter.tsx
blog-toc.tsx
source.ts
source.config.ts
源配置
博客系统在 source.config.ts
文件中使用 Fumadocs MDX 配置:
import { defineCollections, frontmatterSchema } from 'fumadocs-mdx/config';
import { z } from 'zod';
// 博客文章集合
export const blog = defineCollections({
type: 'doc',
dir: 'content/blog',
schema: frontmatterSchema.extend({
image: z.string(),
date: z.string().date(),
published: z.boolean().default(true),
categories: z.array(z.string()),
author: z.string(),
}),
});
// 博客作者集合
export const author = defineCollections({
type: 'doc',
dir: 'content/author',
schema: z.object({
name: z.string(),
avatar: z.string(),
description: z.string().optional(),
}),
});
// 博客分类集合
export const category = defineCollections({
type: 'doc',
dir: 'content/category',
schema: z.object({
name: z.string(),
description: z.string().optional(),
}),
});
然后在 src/lib/source.ts
中使用 Fumadocs 加载器加载博客文章、作者和分类:
import { type InferPageType, loader } from 'fumadocs-core/source';
import { createMDXSource } from 'fumadocs-mdx';
import { author, blog, category } from '../../../.source';
import { docsI18nConfig } from './i18n';
/**
* 博客文章源
*/
export const blogSource = loader({
baseUrl: '/blog',
i18n: docsI18nConfig,
source: createMDXSource(blog),
});
/**
* 博客作者源
*/
export const authorSource = loader({
baseUrl: '/author',
i18n: docsI18nConfig,
source: createMDXSource(author),
});
/**
* 博客分类源
*/
export const categorySource = loader({
baseUrl: '/category',
i18n: docsI18nConfig,
source: createMDXSource(category),
});
// 类型定义
export type BlogType = InferPageType<typeof blogSource>;
export type AuthorType = InferPageType<typeof authorSource>;
export type CategoryType = InferPageType<typeof categorySource>;
创建博客内容
添加新作者
在 content/author
目录中创建新的 MDX 文件:
---
name: John Doe
avatar: /images/authors/john-doe.jpg
---
添加新分类
在 content/category
目录中创建新的 MDX 文件:
---
name: Tutorial
description: Step-by-step guides to learn new features
---
添加新博客文章
在 content/blog
目录中创建新的 MDX 文件:
---
title: My First Blog Post
description: This is a brief description of my first blog post.
image: /images/blog/my-first-post.jpg
date: "2023-12-01"
published: true
categories: ["tutorial", "announcement"]
author: "mksaas"
---
# 介绍
这是我的第一篇博客文章。在这里我将谈论一些有趣的事情。
## 第一部分
这里是一些内容...
## 第二部分
这里是更多内容...
多语言支持
MkSaaS 博客系统完全支持国际化。您可以使用以下文件命名约定创建多语言内容:
- 默认语言(例如英语):
filename.mdx
- 其他语言(例如中文):
filename.zh.mdx
多语言作者和分类
对作者和分类遵循相同的模式:
---
name: MkSaaS 团队
avatar: /images/authors/mksaas.jpg
---
---
name: 公告
description: 官方平台公告和更新
---
多语言博客文章示例
英语博客文章:
---
title: Welcome to our Blog
description: Our first official blog post
image: /images/blog/welcome.jpg
date: "2023-12-01"
published: true
categories: ["announcement"]
author: "mksaas"
---
英语内容...
同一篇文章的中文版本:
---
title: 欢迎来到我们的博客
description: 我们的第一篇官方博客文章
image: /images/blog/welcome.jpg
date: "2023-12-01"
published: true
categories: ["announcement"]
author: "mksaas"
---
中文内容...
系统将根据用户的语言设置自动匹配相应语言的文章。
自定义博客架构
要向博客文章、作者或分类添加新字段:
- 在
source.config.ts
中修改架构 - 运行命令
pnpm run content
重新生成.source
文件夹 - 更新组件以显示新字段
示例:添加"精选"字段
export const blog = defineCollections({
type: 'doc',
dir: 'content/blog',
schema: frontmatterSchema.extend({
image: z.string(),
date: z.string().date(),
published: z.boolean().default(true),
categories: z.array(z.string()),
author: z.string(),
// 添加新字段
featured: z.boolean().default(false),
}),
});
然后,您可以在博客文章中使用此字段:
---
title: 重要公告
description: 阅读这个重要公告
image: /images/blog/announcement.jpg
date: "2023-12-01"
published: true
categories: ["announcement"]
author: "mksaas"
featured: true
---
内容在这里...
然后,运行命令 pnpm run content
重新生成 .source
文件夹。
高级用法
程序化查询文章
您可以使用 Fumadocs 源程序化查询文章:
import { blogSource, authorSource, categorySource } from '@/lib/docs/source';
// 获取所有博客文章
const allPosts = blogSource.getPages();
// 获取已发布的文章
const publishedPosts = allPosts.filter(post => post.data.published);
// 按分类获取文章
const getPostsByCategory = (categorySlug: string) => {
return allPosts.filter(post =>
post.data.categories.includes(categorySlug)
);
};
// 按作者获取文章
const getPostsByAuthor = (authorSlug: string) => {
return allPosts.filter(post => post.data.author === authorSlug);
};
// 获取所有作者
const allAuthors = authorSource.getPages();
// 获取所有分类
const allCategories = categorySource.getPages();
更改博客文章卡片布局
在 src/components/blog/blog-card.tsx
中自定义博客卡片组件:
import type { BlogType } from '@/lib/docs/source';
interface BlogCardProps {
post: BlogType;
}
export function BlogCard({ post }: BlogCardProps) {
return (
<div className="group flex flex-col border rounded-lg overflow-hidden h-full bg-card shadow-sm hover:shadow-md transition-shadow">
{/* 通过 post.data 访问文章数据 */}
<h3>{post.data.title}</h3>
<p>{post.data.description}</p>
<time>{post.data.date}</time>
{/* ... 组件的其余部分 */}
</div>
);
}
构建过程
博客系统使用 Fumadocs MDX 的构建过程:
- 开发:在开发过程中按需处理内容
- 构建:运行
pnpm run content
生成优化的内容源 - 生成的文件:
.source
目录包含生成的 TypeScript 文件和您的内容
最佳实践
- 使用高质量图片:为博客文章使用适当大小和优化的图片
- 一致的分类:在文章中保持一致的分类集合
- 强大的元数据:编写引人注目的标题和描述提高 SEO 效果
- 结构化内容:在博客文章内容中使用适当的标题和段落
- 包含目录:对于较长的文章,确保标题组织良好以便生成目录
- 国际化内容:在所有本地化内容中保持翻译一致性
- 优化图片:使用响应式图片和延迟加载以获得更好的性能
- 架构验证:利用 Zod 架构进行类型安全的内容验证
视频教程
下一步
现在您了解了如何在 MkSaaS 中使用博客系统,您可能想要探索这些相关功能: