feat: 添加 PWA 支持和 SEO 优化

添加 PWA manifest 文件、favicon、结构化数据、sitemap 和 robots.txt。
优化根布局和组件的国际化支持,包括服务端语言检测和防止水合闪烁。
This commit is contained in:
2026-01-31 20:26:55 +08:00
parent b29de1dd80
commit a44a3f6a0d
13 changed files with 748 additions and 94 deletions

View File

@@ -0,0 +1,157 @@
interface StructuredDataProps {
type: "WebSite" | "Organization" | "SoftwareApplication" | "WebPage";
data: Record<string, unknown>;
}
export function StructuredData({ type, data }: StructuredDataProps) {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://minigameai.com";
const baseData = {
"@context": "https://schema.org",
"@type": type,
url: baseUrl,
...data,
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(baseData) }}
/>
);
}
interface WebSiteProps {
lang?: "en" | "zh";
}
export function WebSiteStructuredData({ lang = "en" }: WebSiteProps) {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://minigameai.com";
const content = {
en: {
name: "Mini Game AI",
alternateName: "MiniGameAI",
description:
"Transform your game development workflow with AI-powered tools. Video to frames, image compression, audio processing, texture atlas generation, and more.",
keywords:
"game development, AI tools, video processing, image compression, audio processing, texture atlas",
inLanguage: "en-US",
potentialAction: {
"@type": "SearchAction",
target: {
"@type": "EntryPoint",
urlTemplate: `${baseUrl}/search?q={search_term_string}`,
},
"query-input": "required name=search_term_string",
},
},
zh: {
name: "Mini Game AI",
alternateName: "迷你游戏AI",
description:
"用 AI 驱动的工具改变游戏开发流程。视频抽帧、图片压缩、音频处理、纹理图集生成等。",
keywords:
"游戏开发, AI工具, 视频处理, 图片压缩, 音频处理, 纹理图集",
inLanguage: "zh-CN",
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "WebSite",
url: baseUrl,
...content[lang],
}),
}}
/>
);
}
export function OrganizationStructuredData() {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://minigameai.com";
const data = {
"@context": "https://schema.org",
"@type": "Organization",
name: "Mini Game AI",
url: baseUrl,
logo: `${baseUrl}/icon-512.png`,
description:
"AI-powered tools for game developers. Transform your workflow with browser-based tools for video, image, and audio processing.",
sameAs: [] as string[],
contactPoint: {
"@type": "ContactPoint",
contactType: "customer service",
url: `${baseUrl}/contact`,
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
/>
);
}
interface SoftwareApplicationProps {
name: string;
description: string;
url: string;
category: string;
operatingSystem: string;
offersPrice?: string;
offersCurrency?: string;
}
export function SoftwareApplicationStructuredData({
name,
description,
url,
category,
operatingSystem = "Any (Browser-based)",
offersPrice = "0",
offersCurrency = "USD",
}: SoftwareApplicationProps) {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://minigameai.com";
const data = {
"@context": "https://schema.org",
"@type": "SoftwareApplication",
name,
description,
url: `${baseUrl}${url}`,
applicationCategory: category,
operatingSystem,
offers: {
"@type": "Offer",
price: offersPrice,
priceCurrency: offersCurrency,
},
featureList: [
"Browser-based processing",
"No file uploads required",
"Privacy-first design",
"Batch processing support",
],
browserRequirements: "Requires JavaScript. Requires HTML5.",
softwareVersion: "1.0",
author: {
"@type": "Organization",
name: "Mini Game AI",
url: baseUrl,
},
};
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
/>
);
}