feat(seo): 结构化数据/每页元数据/列表页metadata/hreflang修正/OG分享图

- 详情页注入 Article+BreadcrumbList JSON-LD,工具页 SoftwareApplication
- 课程/技能/文章/练习 动态 generateMetadata(canonical/OG)
- 新增 skills/contents/practices/prompts/models 列表页 metadata
- 修正 hreflang(删除不存在的/en),用 next/og 生成 OG 分享图
This commit is contained in:
TradeMate Dev
2026-07-11 17:23:56 +08:00
parent 8f13604e0e
commit 09bf329544
14 changed files with 389 additions and 28 deletions
+59
View File
@@ -0,0 +1,59 @@
import { SITE_URL } from './config';
export function absoluteUrl(path: string): string {
if (/^https?:\/\//.test(path)) return path;
return `${SITE_URL}${path.startsWith('/') ? '' : '/'}${path}`;
}
export function articleJsonLd(data: {
headline: string;
description?: string;
url: string;
datePublished?: string;
image?: string;
authorName?: string;
}) {
return {
'@context': 'https://schema.org',
'@type': 'Article',
headline: data.headline,
description: data.description || '',
url: data.url,
...(data.datePublished ? { datePublished: data.datePublished } : {}),
author: { '@type': 'Organization', name: data.authorName || '宇之然 AI', url: SITE_URL },
publisher: {
'@type': 'Organization',
name: '宇之然 AI',
url: SITE_URL,
logo: { '@type': 'ImageObject', url: `${SITE_URL}/favicon.png` },
},
...(data.image ? { image: data.image } : {}),
};
}
export function softwareAppJsonLd(data: { name: string; description?: string; url: string }) {
return {
'@context': 'https://schema.org',
'@type': 'SoftwareApplication',
name: data.name,
description: data.description || '',
url: data.url,
applicationCategory: 'UtilitiesApplication',
operatingSystem: 'Web',
offers: { '@type': 'Offer', price: '0', priceCurrency: 'CNY' },
publisher: { '@type': 'Organization', name: '宇之然 AI', url: SITE_URL },
};
}
export function breadcrumbJsonLd(items: { name: string; url: string }[]) {
return {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: items.map((it, i) => ({
'@type': 'ListItem',
position: i + 1,
name: it.name,
item: it.url,
})),
};
}