文档
开发指南博客系统

博客系统

🚀 Cheatsheet (快速执行)

目标: 5分钟内发布你的第一篇博客文章,开始内容营销

最快上手方式:

# 1. 创建新文章 (已配置好 MDX + Content Collections)
# 在 content/posts/ 目录下创建 .mdx 文件

# 2. 复制现有文章作为模板
cp content/posts/first_post.mdx content/posts/my-new-post.mdx

# 3. 编辑文章内容
# 修改标题、内容、发布时间等

# 4. 自动发布
# 保存文件,刷新网站即可看到新文章

立即生效: 访问 /blog 查看文章列表,点击文章查看详情页

❓ 为什么要做博客系统

对 MVP 的核心价值:

  • SEO 流量: 博客是获取搜索引擎流量的最佳方式
  • 建立权威: 专业内容让用户相信你是专家
  • 用户教育: 教用户如何使用你的产品,提高留存
  • 销售转化: 软性植入产品介绍,自然转化付费用户

真实场景举例: 你做了个 AI 写作工具,写博客《如何用 AI 提高写作效率》,用户搜索看到文章,觉得很有用,顺便试用你的工具,最后付费订阅。

🤔 为什么选择 MDX + Content Collections

我们的实战经验:

  • 开发者友好: Markdown 写作简单,MDX 支持 React 组件
  • 版本控制: 文章和代码一起管理,不会丢失
  • 性能极佳: 静态生成,加载速度快,SEO 友好
  • 类型安全: 编译时检查文章格式,减少错误

对比其他方案:

WordPress:      需要服务器,维护复杂,性能一般
Notion + API:   依赖外部服务,加载慢,SEO 不好
Headless CMS:   需要额外费用,增加复杂度
MDX: 简单快速,完全控制,免费

🧠 简要原理 & 最简案例

博客系统架构: MDX 文件 → Content Collections 解析 → 静态生成页面 → 用户访问

最简文章示例:

---
title: "我的第一篇博客"
description: "这是一篇测试文章"
publishedAt: "2024-01-15"
author: "张三"
tags: ["创业", "技术"]
---

## 文章标题

这里是文章内容,支持 **粗体***斜体* 等 Markdown 语法。

### 代码示例

```javascript
console.log('Hello World')
```

### 插入 React 组件

<CallToAction>
  立即试用我们的产品 →
</CallToAction>

🛠️ 实际操作步骤

1. 创建你的第一篇文章 (5分钟)

复制模板文件:

# 进入文章目录
cd content/posts

# 复制现有文章作为模板
cp first_post.mdx how-to-start-blog.mdx

# 编辑文章
code how-to-start-blog.mdx

文章头部配置:

---
title: "如何快速搭建个人博客"
description: "零基础教你用 Next.js 搭建现代化博客系统"
publishedAt: "2024-01-20"
updatedAt: "2024-01-20"
author: "你的名字"
tags: ["技术", "教程", "博客"]
category: "tutorial"
featured: true
image: "/images/blog/blog-setup.jpg"
---

2. 编写高质量内容 (20分钟)

文章结构模板:

## 为什么要有个人博客?

个人博客是展示专业能力的最佳平台,无论你是:

- 📱 **产品经理**:分享产品思考,建立行业影响力
- 💻 **程序员**:记录技术心得,获得更好工作机会  
- 🚀 **创业者**:分享创业过程,吸引投资人关注
- ✍️ **内容创作者**:建立个人品牌,获得商业合作

## 搭建步骤

### 第一步:选择技术栈

我推荐 Next.js + MDX 的方案,原因是:

1. **写作体验好**:Markdown 语法简单易学
2. **性能优秀**:静态生成,加载速度快
3. **SEO 友好**:搜索引擎容易收录
4. **可扩展性强**:后期可以加各种功能

### 第二步:内容规划

制定内容计划,保持更新频率:

- **每周 2 篇**:技术教程
- **每月 1 篇**:行业观察  
- **每季度 1 篇**:年度总结

## 实用技巧

### 提升文章质量

1. **开头抓人**:第一句话决定用户是否继续读
2. **结构清晰**:用小标题分段,方便扫读
3. **配图丰富**:一图胜千言,提升阅读体验
4. **结尾有力**:给出明确的行动建议

## 总结

搭建个人博客是技术人必备技能,选择合适的工具,坚持输出优质内容,就能获得意想不到的回报。

**下一步行动**
1. 确定博客主题定位
2. 写下第一篇文章
3. 设置定期更新提醒

3. 配置博客功能 (15分钟)

文章列表页面:

// app/blog/page.tsx
import { getAllPosts } from '@/lib/content'
import { BlogCard } from '@/modules/blog/BlogCard'

export default function BlogPage() {
  const posts = getAllPosts()
  const featuredPosts = posts.filter(post => post.featured)
  const recentPosts = posts.slice(0, 6)
  
  return (
    <div className="container mx-auto px-4 py-8">
      <div className="text-center mb-12">
        <h1 className="text-4xl font-bold mb-4">我们的博客</h1>
        <p className="text-gray-600 max-w-2xl mx-auto">
          分享关于创业、技术和产品的思考与实践
        </p>
      </div>
      
      {/* 精选文章 */}
      {featuredPosts.length > 0 && (
        <section className="mb-12">
          <h2 className="text-2xl font-bold mb-6">精选文章</h2>
          <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
            {featuredPosts.map(post => (
              <BlogCard key={post.slug} post={post} featured />
            ))}
          </div>
        </section>
      )}
      
      {/* 最新文章 */}
      <section>
        <h2 className="text-2xl font-bold mb-6">最新文章</h2>
        <div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
          {recentPosts.map(post => (
            <BlogCard key={post.slug} post={post} />
          ))}
        </div>
      </section>
    </div>
  )
}

文章卡片组件:

// components/blog/BlogCard.tsx
import Link from 'next/link'
import Image from 'next/image'
import { formatDate } from '@/lib/utils'

export function BlogCard({ post, featured = false }) {
  return (
    <article className="bg-white rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow">
      {post.image && (
        <div className="relative h-48">
          <Image
            src={post.image}
            alt={post.title}
            fill
            className="object-cover"
          />
        </div>
      )}
      
      <div className="p-6">
        <div className="flex flex-wrap gap-2 mb-3">
          {post.tags.slice(0, 2).map(tag => (
            <span 
              key={tag}
              className="px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded"
            >
              {tag}
            </span>
          ))}
        </div>
        
        <h3 className="text-xl font-bold mb-2">
          <Link href={`/blog/${post.slug}`} className="hover:text-blue-600">
            {post.title}
          </Link>
        </h3>
        
        <p className="text-gray-600 mb-4">
          {post.description}
        </p>
        
        <div className="flex items-center justify-between text-sm text-gray-500">
          <span>作者:{post.author}</span>
          <time>{formatDate(post.publishedAt)}</time>
        </div>
      </div>
    </article>
  )
}

4. SEO 优化配置 (10分钟)

元数据优化:

// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }) {
  const post = getPostBySlug(params.slug)
  
  if (!post) return {}
  
  return {
    title: `${post.title} | 我的博客`,
    description: post.description,
    keywords: post.tags.join(', '),
    authors: [{ name: post.author }],
    openGraph: {
      title: post.title,
      description: post.description,
      images: [post.image || '/default-blog-image.jpg'],
      type: 'article',
      publishedTime: post.publishedAt,
    },
    twitter: {
      card: 'summary_large_image',
      title: post.title,
      description: post.description,
      images: [post.image || '/default-blog-image.jpg'],
    }
  }
}

站点地图生成:

// app/sitemap.ts
import { getAllPosts } from '@/lib/content'

export default function sitemap() {
  const posts = getAllPosts()
  
  const blogUrls = posts.map(post => ({
    url: `https://yourdomain.com/blog/${post.slug}`,
    lastModified: new Date(post.updatedAt || post.publishedAt),
    changeFrequency: 'monthly' as const,
    priority: 0.7,
  }))
  
  return [
    {
      url: 'https://yourdomain.com/blog',
      lastModified: new Date(),
      changeFrequency: 'weekly' as const,
      priority: 0.8,
    },
    ...blogUrls
  ]
}

💡 高级功能实现

文章搜索功能

// components/blog/SearchBar.tsx
'use client'
import { useState, useMemo } from 'react'
import { Input } from '@/components/ui/input'

export function SearchBar({ posts, onFilter }) {
  const [searchTerm, setSearchTerm] = useState('')
  
  const filteredPosts = useMemo(() => {
    return posts.filter(post => 
      post.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
      post.description.toLowerCase().includes(searchTerm.toLowerCase()) ||
      post.tags.some(tag => tag.toLowerCase().includes(searchTerm.toLowerCase()))
    )
  }, [posts, searchTerm])
  
  useMemo(() => {
    onFilter(filteredPosts)
  }, [filteredPosts, onFilter])
  
  return (
    <div className="mb-8">
      <Input
        type="text"
        placeholder="搜索文章..."
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
        className="max-w-md"
      />
      <p className="text-sm text-gray-600 mt-2">
        找到 {filteredPosts.length} 篇文章
      </p>
    </div>
  )
}

RSS 订阅

// app/rss.xml/route.ts
import { getAllPosts } from '@/lib/content'
import RSS from 'rss'

export async function GET() {
  const posts = getAllPosts()
  
  const feed = new RSS({
    title: '我的博客',
    description: '分享技术和创业思考',
    site_url: 'https://yourdomain.com',
    feed_url: 'https://yourdomain.com/rss.xml',
    language: 'zh',
  })
  
  posts.forEach(post => {
    feed.item({
      title: post.title,
      description: post.description,
      url: `https://yourdomain.com/blog/${post.slug}`,
      date: new Date(post.publishedAt),
      categories: post.tags,
    })
  })
  
  return new Response(feed.xml(), {
    headers: { 'Content-Type': 'application/xml' },
  })
}

🎯 内容创作指南

文章模板结构

## 问题背景 (抓住注意力)
- 用户遇到什么问题
- 问题的影响和后果
- 为什么现在需要解决

## 解决方案 (提供价值)
### 步骤一:准备工作
- 具体操作指南
- 工具和资源准备
- 注意事项

### 步骤二:核心实施
- 详细实施步骤
- 代码示例和截图
- 常见问题解答

### 步骤三:验证结果
- 成功标志
- 测试方法
- 优化建议

## 实战案例 (建立信任)
- 真实案例分析
- 数据和效果展示
- 经验教训总结

## 行动指南 (促进转化)
- 关键要点总结
- 下一步行动建议
- 相关资源链接

写作技巧清单

 标题包含关键词,具体且有吸引力
 开头 3 句话说明文章价值
 使用小标题,便于扫读
 每段不超过 3 行,提高可读性
 加入代码示例和截图
 结尾给出明确行动建议
 添加相关内链,提高用户粘性
 配置合适的标签和分类

🆘 常见问题解决

问题1: 文章不显示

# 检查文件路径
ls content/posts/
# 确保文件以 .mdx 结尾,位置正确

# 检查文章头部格式
head -10 content/posts/your-post.mdx
# 确保 YAML 语法正确,所有字段都有值

问题2: 图片不加载

// 正确的图片引用方式
// 1. 放在 public/images/blog/ 目录
// 2. 文章中使用相对路径
![描述](/images/blog/your-image.jpg)

// 或使用 Next.js Image 组件
import Image from 'next/image'

<Image 
  src="/images/blog/your-image.jpg"
  alt="描述文字"
  width={800}
  height={400}
/>

问题3: 构建失败

# 检查 MDX 语法
bun run build

# 常见错误:
# - YAML 头部格式错误
# - 未闭合的 HTML 标签
# - 特殊字符需要转义

📊 内容效果分析

文章表现统计

// 添加文章浏览统计
export function trackArticleView(slug: string) {
  fetch('/api/analytics/article-view', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ 
      slug, 
      timestamp: Date.now(),
      referrer: document.referrer 
    })
  })
}

// 热门文章排行
export async function getPopularArticles(limit = 10) {
  const articles = await db.articleView.groupBy({
    by: ['slug'],
    _count: { slug: true },
    orderBy: { _count: { slug: 'desc' } },
    take: limit
  })
  
  return articles.map(item => ({
    slug: item.slug,
    views: item._count.slug
  }))
}

📎 延伸阅读

技术文档:

写作指南:

工具推荐:


下一步: 博客系统配置完成后,查看 [SEO 优化]./seo) 了解如何提高搜索引擎排名。