diff --git a/openspec/changes/archive/2026-01-19-add-cover-image-display/design.md b/openspec/changes/archive/2026-01-19-add-cover-image-display/design.md
new file mode 100644
index 00000000..f52ecdc5
--- /dev/null
+++ b/openspec/changes/archive/2026-01-19-add-cover-image-display/design.md
@@ -0,0 +1,132 @@
+# Design: Add Cover Image Display
+
+## Architecture Overview
+
+本变更涉及两个独立的 UI 组件修改,不引入新的架构模式。
+
+```
+┌─────────────────────────────────────────────────────┐
+│ PostDetails.astro │
+│ ┌───────────────────────────────────────────────┐ │
+│ │ Cover Image (NEW) │ │
+│ │ - 条件渲染 (ogImageUrl 存在时) │ │
+│ │ - 响应式图片容器 │ │
+│ └───────────────────────────────────────────────┘ │
+│ ┌───────────────────────────────────────────────┐ │
+│ │ 导读区块 (existing) │ │
+│ └───────────────────────────────────────────────┘ │
+│ ┌───────────────────────────────────────────────┐ │
+│ │ 文章内容 (existing) │ │
+│ └───────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────┘
+
+┌─────────────────────────────────────────────────────┐
+│ Card.astro │
+│ ┌─────────┬────────────────────────────────────┐ │
+│ │ Thumb │ Title + Badge │ │
+│ │ (NEW) │ Datetime │ │
+│ │ │ Description │ │
+│ └─────────┴────────────────────────────────────┘ │
+│ ↑ 有 ogImage 时的布局 │
+│ │
+│ ┌───────────────────────────────────────────────┐ │
+│ │ Title + Badge │ │
+│ │ Datetime │ │
+│ │ Description │ │
+│ └───────────────────────────────────────────────┘ │
+│ ↑ 无 ogImage 时的布局(保持不变) │
+└─────────────────────────────────────────────────────┘
+```
+
+## Data Flow
+
+### ogImage 数据类型
+
+根据 `content.config.ts` 定义:
+```typescript
+ogImage: image().or(z.string()).optional()
+```
+
+可能的值:
+1. `undefined` - 未配置
+2. `string` - 远程 URL(如 CDN 地址)
+3. `ImageMetadata` - 本地图片 asset(有 `.src` 属性)
+
+### PostDetails.astro 中已有的解析逻辑
+
+```typescript
+let ogImageUrl: string | undefined;
+
+if (typeof initOgImage === "string") {
+ ogImageUrl = initOgImage; // 远程图片
+} else if (initOgImage?.src) {
+ ogImageUrl = initOgImage.src; // 本地 asset
+}
+```
+
+直接复用此变量即可。
+
+### Card.astro 需要新增解析
+
+Card 组件当前未使用 ogImage,需要:
+1. 从 `data` 中解构 `ogImage`
+2. 添加类似的类型判断逻辑
+
+## Styling Decisions
+
+### 文章详情页头图
+
+```
+容器:
+- 宽度:100%
+- 最大高度:400px(桌面)/ 250px(移动)
+- 圆角:rounded-lg (8px)
+- 下边距:mb-6
+
+图片:
+- object-fit: cover
+- width: 100%
+- height: auto
+- loading: lazy
+```
+
+### 文章列表缩略图
+
+```
+容器:
+- 尺寸:80px × 80px(移动)/ 120px × 80px(桌面)
+- 圆角:rounded-md (6px)
+- flex-shrink: 0
+
+图片:
+- object-fit: cover
+- 100% 填充容器
+- loading: lazy
+```
+
+## Responsive Breakpoints
+
+| Breakpoint | 详情页头图高度 | 列表缩略图 |
+|------------|---------------|-----------|
+| < 640px (sm) | max-h-[250px] | 80×80px,图片在标题上方 |
+| ≥ 640px | max-h-[400px] | 120×80px,图片在左侧 |
+
+## Trade-offs
+
+### 选项 A:列表页图片在左侧
+- ✅ 视觉层次清晰
+- ✅ 符合常见博客布局
+- ❌ 需要调整现有 flex 结构
+
+### 选项 B:列表页图片在上方
+- ✅ 实现简单
+- ❌ 占用更多垂直空间
+- ❌ 有图/无图的卡片高度差异大
+
+**决策**:采用选项 A,桌面端图片在左侧,移动端图片在上方。
+
+## Backward Compatibility
+
+- 无 ogImage 的文章保持原有布局,无任何变化
+- 不修改 ogImage 的 schema 定义
+- 不影响 Open Graph 元数据生成
diff --git a/openspec/changes/archive/2026-01-19-add-cover-image-display/proposal.md b/openspec/changes/archive/2026-01-19-add-cover-image-display/proposal.md
new file mode 100644
index 00000000..6cbd1ebc
--- /dev/null
+++ b/openspec/changes/archive/2026-01-19-add-cover-image-display/proposal.md
@@ -0,0 +1,44 @@
+# Proposal: Add Cover Image Display
+
+## Change ID
+`add-cover-image-display`
+
+## Summary
+在文章页面和文章列表中显示配置的头图(ogImage)。当前 ogImage 仅用于社交媒体分享时的 Open Graph 元数据,本提案将其扩展为可选的视觉展示元素。
+
+## Motivation
+- 用户配置了 ogImage 后,期望在文章页面中能直接看到这张图片
+- 头图可以增强文章的视觉吸引力,提升阅读体验
+- 在文章列表中显示缩略图可以帮助读者快速识别感兴趣的内容
+
+## Scope
+
+### In Scope
+1. **文章详情页**:在"导读"区块上方显示头图
+2. **文章列表卡片**:在 description 左侧显示头图缩略图
+
+### Out of Scope
+- 修改 ogImage 的 schema 定义
+- 修改 Open Graph 元数据生成逻辑
+- 添加新的配置选项(如全局开关)
+
+## Affected Files
+- `src/layouts/PostDetails.astro` - 文章详情页布局
+- `src/components/Card.astro` - 文章列表卡片组件
+
+## Dependencies
+- 无外部依赖
+- 复用现有的 ogImage 解析逻辑
+
+## Risks & Mitigations
+| Risk | Impact | Mitigation |
+|------|--------|------------|
+| 图片加载失败 | 页面布局错乱 | 使用 CSS object-fit 和固定容器尺寸 |
+| 外部图片 URL 可能较慢 | 页面加载体验下降 | 使用 loading="lazy" 延迟加载 |
+| 响应式布局适配 | 移动端显示异常 | 使用 Tailwind 响应式类,移动端调整布局 |
+
+## Success Criteria
+- [ ] 配置了 ogImage 的文章在详情页"导读"上方显示头图
+- [ ] 配置了 ogImage 的文章在列表卡片中 description 左侧显示缩略图
+- [ ] 未配置 ogImage 的文章保持原有布局不变
+- [ ] 响应式布局在移动端和桌面端均正常显示
diff --git a/openspec/changes/archive/2026-01-19-add-cover-image-display/specs/cover-image/spec.md b/openspec/changes/archive/2026-01-19-add-cover-image-display/specs/cover-image/spec.md
new file mode 100644
index 00000000..b57a9531
--- /dev/null
+++ b/openspec/changes/archive/2026-01-19-add-cover-image-display/specs/cover-image/spec.md
@@ -0,0 +1,78 @@
+# Spec: Cover Image Display
+
+## Overview
+为配置了 ogImage 的文章提供页面内头图展示能力。
+
+---
+
+## ADDED Requirements
+
+### Requirement: Post Detail Cover Image
+当文章配置了 ogImage 时,系统 SHALL 在文章详情页的"导读"区块上方显示头图。
+
+- 图片 SHALL 显示在标题、日期之后,"导读"区块之前
+- 图片宽度 SHALL 为 100%,高度自适应,最大高度受限
+- 系统 SHALL 使用 lazy loading 优化加载性能
+- 图片加载期间 SHALL NOT 影响页面布局
+
+#### Scenario: Article with ogImage displays cover
+- **GIVEN** 一篇文章配置了 `ogImage: "https://example.com/cover.png"`
+- **WHEN** 用户访问该文章详情页
+- **THEN** 应在"导读"区块上方看到该头图
+- **AND** 图片应为圆角样式,宽度撑满内容区域
+
+#### Scenario: Article without ogImage shows no cover
+- **GIVEN** 一篇文章未配置 ogImage
+- **WHEN** 用户访问该文章详情页
+- **THEN** 页面布局与当前保持一致,无头图区域
+
+---
+
+### Requirement: Card Thumbnail Image
+当文章配置了 ogImage 时,系统 SHALL 在文章列表卡片中显示缩略图。
+
+- 缩略图 SHALL 显示在卡片左侧(桌面端)或上方(移动端)
+- 系统 SHALL 使用固定尺寸容器,图片使用 object-cover 裁切
+- 系统 SHALL 使用 lazy loading 优化加载性能
+- 无 ogImage 的文章 SHALL 保持原有纯文字布局
+
+#### Scenario: Article with ogImage shows thumbnail in list
+- **GIVEN** 首页或文章列表页
+- **AND** 某篇文章配置了 ogImage
+- **WHEN** 该文章卡片被渲染
+- **THEN** 应在卡片左侧(桌面端)显示缩略图
+- **AND** 缩略图为固定尺寸、圆角样式
+
+#### Scenario: Article without ogImage shows text-only card
+- **GIVEN** 首页或文章列表页
+- **AND** 某篇文章未配置 ogImage
+- **WHEN** 该文章卡片被渲染
+- **THEN** 卡片布局保持原有样式,无缩略图区域
+
+---
+
+### Requirement: Responsive Layout
+头图展示 SHALL 在不同屏幕尺寸下正常显示。
+
+- 移动端(<640px):详情页头图最大高度 SHALL 为 250px
+- 移动端(<640px):列表缩略图 SHALL 显示在标题上方
+- 桌面端(≥640px):详情页头图最大高度 SHALL 为 400px
+- 桌面端(≥640px):列表缩略图 SHALL 显示在内容左侧
+
+#### Scenario: Mobile view of article with cover
+- **GIVEN** 用户使用移动设备(屏幕宽度 < 640px)
+- **WHEN** 访问配置了 ogImage 的文章
+- **THEN** 详情页头图高度不超过 250px
+- **AND** 列表页缩略图显示在标题上方
+
+#### Scenario: Desktop view of article with cover
+- **GIVEN** 用户使用桌面设备(屏幕宽度 ≥ 640px)
+- **WHEN** 访问配置了 ogImage 的文章
+- **THEN** 详情页头图高度不超过 400px
+- **AND** 列表页缩略图显示在内容左侧
+
+---
+
+## Related Capabilities
+- Open Graph 元数据生成(不受影响)
+- 动态 OG 图片生成(不受影响)
diff --git a/openspec/changes/archive/2026-01-19-add-cover-image-display/tasks.md b/openspec/changes/archive/2026-01-19-add-cover-image-display/tasks.md
new file mode 100644
index 00000000..97d45aed
--- /dev/null
+++ b/openspec/changes/archive/2026-01-19-add-cover-image-display/tasks.md
@@ -0,0 +1,57 @@
+# Tasks: Add Cover Image Display
+
+## Task List
+
+### Phase 1: 文章详情页头图展示
+
+- [x] **T1.1** 修改 `PostDetails.astro`,在标题上方添加头图展示区域
+ - 条件渲染:仅当 `ogImageUrl` 存在时显示
+ - 容器样式:圆角、阴影、浅色边框
+ - 图片样式:object-cover、lazy loading
+ - hover 效果:阴影增强 + 轻微放大
+ - 验证:本地预览确认有/无头图的文章显示正确
+
+### Phase 2: 文章列表卡片头图展示
+
+- [x] **T2.1** 修改 `Card.astro`,获取 ogImage 数据
+ - 从 props 中解构 ogImage 字段
+ - 处理 string 和 image asset 两种类型
+
+- [x] **T2.2** 调整 Card 布局结构
+ - 布局:标题行 → 日期行 → 头图+description 行
+ - 有头图时:左侧图片 + 右侧内容(flex 布局)
+ - 无头图时:保持原有纯文字布局
+ - 响应式:移动端图片在上,桌面端图片在左
+
+- [x] **T2.3** 添加缩略图样式
+ - 尺寸:96px × 160px
+ - object-cover 裁切
+ - 圆角边框 + 浅色边框 + 阴影
+ - hover 效果:放大 5%
+ - lazy loading
+
+### Phase 3: RSS 头图支持
+
+- [x] **T3.1** 修改 `rss.xml.ts`,添加头图到 RSS feed
+ - 使用 `enclosure` 标签(RSS 2.0 标准)
+ - 自动识别图片 MIME type
+
+### Phase 4: 验证与测试
+
+- [x] **T4.1** 本地预览测试
+ - 有 ogImage 的文章详情页
+ - 无 ogImage 的文章详情页
+ - 首页文章列表
+ - 文章归档页面
+
+- [x] **T4.2** 响应式测试
+ - 桌面端(>1024px)
+ - 移动端(<768px)
+
+## Dependencies
+- T2.2 依赖 T2.1
+- T2.3 依赖 T2.2
+- T4.1 依赖 T1.1, T2.3, T3.1
+
+## Parallelizable Work
+- T1.1 和 T2.1 可并行开发
diff --git a/src/components/Card.astro b/src/components/Card.astro
index 7924174f..35f0af99 100644
--- a/src/components/Card.astro
+++ b/src/components/Card.astro
@@ -24,7 +24,15 @@ const {
section = "",
} = Astro.props;
-const { title, description, featured, ...props } = data;
+const { title, description, featured, ogImage, ...props } = data;
+
+// 解析 ogImage URL
+let ogImageUrl: string | undefined;
+if (typeof ogImage === "string") {
+ ogImageUrl = ogImage;
+} else if (ogImage?.src) {
+ ogImageUrl = ogImage.src;
+}
// 自动生成摘要:如果 description 为空,从文章内容提取
function getExcerpt(content: string, maxLength: number = 350): string {
@@ -76,5 +84,34 @@ const excerpt = description || (body ? getExcerpt(body) : "");
}
{excerpt}
} + { + excerpt && ( ++ {excerpt} +
+