Add dynamic OG image generation for social media sharing

## Features
- Create /api/og route for dynamic Open Graph image generation
- Beautiful gradient design with site branding
- Display post title, description, and tags
- Support for both light and dark themes
- Proper sizing for social media (1200x630)

## Implementation
- Use @vercel/og package for image generation
- Add OpenGraph and Twitter Card metadata to blog posts
- Fallback to localhost for development
- Uses NEXT_PUBLIC_SITE_URL environment variable for production

## Social Media Support
- OpenGraph (Facebook, LinkedIn, etc.)
- Twitter Cards with large image preview
- Article metadata including publish time and tags

Example usage:
/api/og?title=Post+Title&description=Post+Desc&tags=tag1,tag2,tag3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-20 14:55:36 +08:00
parent 7d1f29dd9d
commit d7dc279d32
4 changed files with 406 additions and 2 deletions

View File

@@ -28,9 +28,40 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
const post = getPostBySlug(slug);
if (!post) return {};
const ogImageUrl = new URL('/api/og', process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000');
ogImageUrl.searchParams.set('title', post.title);
if (post.description) {
ogImageUrl.searchParams.set('description', post.description);
}
if (post.tags && post.tags.length > 0) {
ogImageUrl.searchParams.set('tags', post.tags.slice(0, 3).join(','));
}
return {
title: post.title,
description: post.description || post.title
description: post.description || post.title,
openGraph: {
title: post.title,
description: post.description || post.title,
type: 'article',
publishedTime: post.published_at,
authors: post.authors,
tags: post.tags,
images: [
{
url: ogImageUrl.toString(),
width: 1200,
height: 630,
alt: post.title,
},
],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.description || post.title,
images: [ogImageUrl.toString()],
},
};
}