From 03cc0fd2834c48e91b86bd2e4fe643fffb0cc170 Mon Sep 17 00:00:00 2001 From: richarjiang Date: Sun, 8 Feb 2026 09:17:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=A8=E9=9D=A2=E4=BC=98=E5=8C=96=20?= =?UTF-8?q?SEO=20=E5=85=83=E6=95=B0=E6=8D=AE=E3=80=81=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E5=8C=96=E6=95=B0=E6=8D=AE=E5=92=8C=E7=AB=99=E7=82=B9=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为所有工具页面添加 canonical URL、keywords、SoftwareApplication 和 BreadcrumbList 结构化数据,优化标题和描述以包含搜索意图关键词, 更新站点地图日期和优先级,移除无效的 SearchAction,新增 PWA manifest。 Co-Authored-By: Claude Opus 4.6 --- public/manifest.json | 16 +++++ .../tools/audio-compress/layout.tsx | 65 +++++++++++++++++-- .../tools/image-compress/layout.tsx | 65 +++++++++++++++++-- .../tools/texture-atlas/layout.tsx | 57 +++++++++++----- .../(dashboard)/tools/video-frames/layout.tsx | 63 ++++++++++++++++-- src/app/layout.tsx | 1 + src/app/sitemap.ts | 55 ++++++++-------- src/components/seo/StructuredData.tsx | 39 ++++++++--- 8 files changed, 295 insertions(+), 66 deletions(-) create mode 100644 public/manifest.json diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..b46624e --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,16 @@ +{ + "name": "KYMR.TOP - Game Asset Tools", + "short_name": "KYMR.TOP", + "description": "Free online tools for game developers. Compress images, extract video frames, optimize audio, generate texture atlases. Browser-based, privacy-first.", + "start_url": "/", + "display": "standalone", + "background_color": "#09090b", + "theme_color": "#09090b", + "icons": [ + { + "src": "/icon.svg", + "sizes": "any", + "type": "image/svg+xml" + } + ] +} diff --git a/src/app/(dashboard)/tools/audio-compress/layout.tsx b/src/app/(dashboard)/tools/audio-compress/layout.tsx index 2aea891..7b403ca 100644 --- a/src/app/(dashboard)/tools/audio-compress/layout.tsx +++ b/src/app/(dashboard)/tools/audio-compress/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { headers } from "next/headers"; +import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData"; export async function generateMetadata(): Promise { const headersList = await headers(); @@ -7,25 +8,61 @@ export async function generateMetadata(): Promise { const lang = acceptLanguage.includes("zh") ? "zh" : "en"; const titles = { - en: "Audio Compression - Compress & Convert Audio Files", - zh: "音频压缩 - 压缩并转换音频文件", + en: "Audio Compression - Compress & Convert Audio Files Online Free", + zh: "音频压缩 - 免费在线压缩并转换音频文件", }; const descriptions = { - en: "Compress and convert audio files to various formats including MP3, AAC, OGG, FLAC. Adjust bitrate and sample rate for optimal quality.", - zh: "压缩并转换音频文件为多种格式,包括 MP3、AAC、OGG、FLAC。调整比特率和采样率以获得最佳质量。", + en: "Free online audio compressor and converter. Compress MP3, WAV, OGG, AAC, FLAC files. Adjust bitrate, sample rate, channels. Browser-based with no uploads required.", + zh: "免费在线音频压缩转换工具。压缩 MP3、WAV、OGG、AAC、FLAC 文件。调整比特率、采样率、声道。浏览器本地处理无需上传。", }; + const keywords = { + en: [ + "audio compression", + "audio compressor online", + "compress MP3", + "audio converter", + "WAV to MP3", + "reduce audio size", + "audio bitrate converter", + "OGG converter", + "FLAC converter", + "browser-based", + ], + zh: [ + "音频压缩", + "在线音频压缩", + "MP3压缩", + "音频转换", + "WAV转MP3", + "缩小音频", + "音频比特率转换", + "OGG转换", + "FLAC转换", + "浏览器端", + ], + }; + + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://kymr.top"; + return { title: titles[lang], description: descriptions[lang], + keywords: keywords[lang], + alternates: { + canonical: `${baseUrl}/tools/audio-compress`, + }, openGraph: { title: titles[lang], description: descriptions[lang], + url: `${baseUrl}/tools/audio-compress`, + type: "website", }, twitter: { title: titles[lang], description: descriptions[lang], + card: "summary_large_image", }, }; } @@ -35,5 +72,23 @@ export default function AudioCompressLayout({ }: { children: React.ReactNode; }) { - return children; + return ( + <> + + + {children} + + ); } diff --git a/src/app/(dashboard)/tools/image-compress/layout.tsx b/src/app/(dashboard)/tools/image-compress/layout.tsx index 0c88530..771ff0f 100644 --- a/src/app/(dashboard)/tools/image-compress/layout.tsx +++ b/src/app/(dashboard)/tools/image-compress/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { headers } from "next/headers"; +import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData"; export async function generateMetadata(): Promise { const headersList = await headers(); @@ -7,25 +8,61 @@ export async function generateMetadata(): Promise { const lang = acceptLanguage.includes("zh") ? "zh" : "en"; const titles = { - en: "Image Compression - Optimize Images for Web & Mobile", - zh: "图片压缩 - 为网页和移动端优化图片", + en: "Image Compression - Optimize PNG, JPEG, WebP Online Free", + zh: "图片压缩 - 免费在线优化 PNG、JPEG、WebP 图片", }; const descriptions = { - en: "Optimize images for web and mobile without quality loss. Support for batch processing and format conversion including PNG, JPEG, WebP.", - zh: "为网页和移动端优化图片,不影响质量。支持批量处理和格式转换,包括 PNG、JPEG、WebP。", + en: "Free online image compressor. Optimize PNG, JPEG, WebP, AVIF images without quality loss. Batch processing, format conversion, browser-based with no uploads required.", + zh: "免费在线图片压缩工具。无损优化 PNG、JPEG、WebP、AVIF 图片。支持批量处理、格式转换,浏览器本地处理无需上传。", }; + const keywords = { + en: [ + "image compression", + "image compressor online", + "compress PNG", + "compress JPEG", + "WebP converter", + "image optimizer", + "batch image compression", + "reduce image size", + "AVIF converter", + "browser-based", + ], + zh: [ + "图片压缩", + "在线图片压缩", + "PNG压缩", + "JPEG压缩", + "WebP转换", + "图片优化", + "批量压缩", + "缩小图片", + "AVIF转换", + "浏览器端", + ], + }; + + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://kymr.top"; + return { title: titles[lang], description: descriptions[lang], + keywords: keywords[lang], + alternates: { + canonical: `${baseUrl}/tools/image-compress`, + }, openGraph: { title: titles[lang], description: descriptions[lang], + url: `${baseUrl}/tools/image-compress`, + type: "website", }, twitter: { title: titles[lang], description: descriptions[lang], + card: "summary_large_image", }, }; } @@ -35,5 +72,23 @@ export default function ImageCompressLayout({ }: { children: React.ReactNode; }) { - return children; + return ( + <> + + + {children} + + ); } diff --git a/src/app/(dashboard)/tools/texture-atlas/layout.tsx b/src/app/(dashboard)/tools/texture-atlas/layout.tsx index 8da6b97..2baaa06 100644 --- a/src/app/(dashboard)/tools/texture-atlas/layout.tsx +++ b/src/app/(dashboard)/tools/texture-atlas/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { headers } from "next/headers"; +import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData"; export async function generateMetadata(): Promise { const headersList = await headers(); @@ -7,47 +8,55 @@ export async function generateMetadata(): Promise { const lang = acceptLanguage.includes("zh") ? "zh" : "en"; const titles = { - en: "Texture Atlas Generator - Create Sprite Sheets Online", - zh: "纹理图集生成器 - 在线创建精灵图", + en: "Texture Atlas Generator - Create Sprite Sheets Online Free", + zh: "纹理图集生成器 - 免费在线创建精灵图", }; const descriptions = { - en: "Generate texture atlases and sprite sheets for game development. Pack multiple sprites into a single texture atlas with JSON data export. All processing happens locally in your browser.", - zh: "为游戏开发生成纹理图集和精灵图。将多个精灵打包到单个纹理图集中,支持导出 JSON 数据。所有处理都在您的浏览器本地进行。", + en: "Free online texture atlas and sprite sheet generator for game development. Pack multiple sprites into optimized atlases with JSON data export. Browser-based, no uploads needed.", + zh: "免费在线纹理图集和精灵图生成器,专为游戏开发设计。将多个精灵打包到优化的图集中,支持导出 JSON 数据。浏览器本地处理,无需上传。", }; const keywords = { en: [ "texture atlas", - "sprite sheet", - "game development", + "sprite sheet generator", + "texture packer online", + "sprite sheet creator", + "game development tools", "sprite packer", - "texture packing", - "game assets", - "sprite generator", "JSON export", + "game assets", + "texture atlas generator", "browser-based", ], zh: [ "纹理图集", - "精灵图", - "游戏开发", + "精灵图生成器", + "在线纹理打包", + "精灵图制作", + "游戏开发工具", "精灵打包", - "纹理打包", - "游戏资产", - "精灵生成器", "JSON导出", + "游戏资产", + "纹理图集生成器", "浏览器端", ], }; + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://kymr.top"; + return { title: titles[lang], description: descriptions[lang], keywords: keywords[lang], + alternates: { + canonical: `${baseUrl}/tools/texture-atlas`, + }, openGraph: { title: titles[lang], description: descriptions[lang], + url: `${baseUrl}/tools/texture-atlas`, type: "website", }, twitter: { @@ -63,5 +72,23 @@ export default function TextureAtlasLayout({ }: { children: React.ReactNode; }) { - return children; + return ( + <> + + + {children} + + ); } diff --git a/src/app/(dashboard)/tools/video-frames/layout.tsx b/src/app/(dashboard)/tools/video-frames/layout.tsx index 2d69ced..f9dbe60 100644 --- a/src/app/(dashboard)/tools/video-frames/layout.tsx +++ b/src/app/(dashboard)/tools/video-frames/layout.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next"; import { headers } from "next/headers"; +import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData"; export async function generateMetadata(): Promise { const headersList = await headers(); @@ -7,25 +8,59 @@ export async function generateMetadata(): Promise { const lang = acceptLanguage.includes("zh") ? "zh" : "en"; const titles = { - en: "Video to Frame Sequence - Extract Frame Sequences from Videos", - zh: "视频转序列帧 - 从视频中提取序列帧", + en: "Video to Frame Sequence - Extract Frames from Video Online Free", + zh: "视频转序列帧 - 免费在线从视频提取帧图片", }; const descriptions = { - en: "Extract frame sequences from videos with customizable frame rates. Perfect for sprite animations and game asset preparation. Supports MP4, MOV, AVI, WebM.", - zh: "从视频中提取序列帧,可自定义帧率。非常适合精灵动画制作和游戏素材准备。支持 MP4、MOV、AVI、WebM。", + en: "Free online video to frame sequence extractor. Extract PNG, WebP, JPEG frames from MP4, WebM, MOV videos with custom frame rates. Perfect for sprite animations and game assets.", + zh: "免费在线视频转序列帧工具。从 MP4、WebM、MOV 视频中提取 PNG、WebP、JPEG 帧图片,可自定义帧率。非常适合精灵动画和游戏素材制作。", }; + const keywords = { + en: [ + "video to frames", + "video frame extractor", + "extract frames from video", + "video to PNG sequence", + "video to sprite sheet", + "frame sequence generator", + "MP4 to frames", + "game animation frames", + "browser-based", + ], + zh: [ + "视频转序列帧", + "视频抽帧", + "视频帧提取", + "视频转PNG", + "视频转精灵图", + "序列帧生成", + "MP4转帧", + "游戏动画帧", + "浏览器端", + ], + }; + + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://kymr.top"; + return { title: titles[lang], description: descriptions[lang], + keywords: keywords[lang], + alternates: { + canonical: `${baseUrl}/tools/video-frames`, + }, openGraph: { title: titles[lang], description: descriptions[lang], + url: `${baseUrl}/tools/video-frames`, + type: "website", }, twitter: { title: titles[lang], description: descriptions[lang], + card: "summary_large_image", }, }; } @@ -35,5 +70,23 @@ export default function VideoFramesLayout({ }: { children: React.ReactNode; }) { - return children; + return ( + <> + + + {children} + + ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5f2186f..1af1202 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -73,6 +73,7 @@ export const metadata: Metadata = { icons: { icon: "/icon.svg", }, + manifest: "/manifest.json", openGraph: { type: "website", siteName: "KYMR.TOP", diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 963320c..86db057 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -5,56 +5,61 @@ interface ToolPage { en: { title: string; description: string }; zh: { title: string; description: string }; lastModified: Date; + priority: number; } const tools: ToolPage[] = [ { path: "/tools/image-compress", en: { - title: "Image Compression - Optimize Images for Web & Mobile", - description: "Optimize images for web and mobile without quality loss. Support for batch processing and format conversion including PNG, JPEG, WebP.", + title: "Image Compression - Optimize PNG, JPEG, WebP Online Free", + description: "Free online image compressor. Optimize PNG, JPEG, WebP, AVIF images without quality loss. Batch processing, format conversion, browser-based.", }, zh: { - title: "图片压缩 - 为网页和移动端优化图片", - description: "为网页和移动端优化图片,不影响质量。支持批量处理和格式转换,包括 PNG、JPEG、WebP。", + title: "图片压缩 - 免费在线优化 PNG、JPEG、WebP 图片", + description: "免费在线图片压缩工具。无损优化 PNG、JPEG、WebP、AVIF 图片。支持批量处理、格式转换,浏览器本地处理。", }, - lastModified: new Date("2025-01-01"), + lastModified: new Date("2026-02-08"), + priority: 0.9, }, { path: "/tools/video-frames", en: { - title: "Video to Frame Sequence - Extract Frame Sequences from Videos", - description: "Extract frame sequences from videos with precision control. Support for MP4, WebM and other video formats. Export as PNG, WebP or ZIP.", + title: "Video to Frame Sequence - Extract Frames from Video Online Free", + description: "Free online video to frame sequence extractor. Extract PNG, WebP, JPEG frames from MP4, WebM, MOV videos with custom frame rates.", }, zh: { - title: "视频转序列帧 - 从视频中提取序列帧", - description: "精确控制从视频中提取序列帧。支持 MP4、WebM 等视频格式。导出为 PNG、WebP 或 ZIP。", + title: "视频转序列帧 - 免费在线从视频提取帧图片", + description: "免费在线视频转序列帧工具。从 MP4、WebM、MOV 视频中提取 PNG、WebP、JPEG 帧图片,可自定义帧率。", }, - lastModified: new Date("2025-01-01"), + lastModified: new Date("2026-02-08"), + priority: 0.9, }, { path: "/tools/audio-compress", en: { - title: "Audio Compression - Compress & Convert Audio Files", - description: "Compress and convert audio files with ease. Support for MP3, WAV, OGG and more. Adjustable quality settings.", + title: "Audio Compression - Compress & Convert Audio Files Online Free", + description: "Free online audio compressor and converter. Compress MP3, WAV, OGG, AAC, FLAC files. Browser-based with no uploads required.", }, zh: { - title: "音频压缩 - 压缩并转换音频文件", - description: "轻松压缩和转换音频文件。支持 MP3、WAV、OGG 等格式。可调节质量设置。", + title: "音频压缩 - 免费在线压缩并转换音频文件", + description: "免费在线音频压缩转换工具。压缩 MP3、WAV、OGG、AAC、FLAC 文件。浏览器本地处理无需上传。", }, - lastModified: new Date("2025-01-01"), + lastModified: new Date("2026-02-08"), + priority: 0.8, }, { path: "/tools/texture-atlas", en: { - title: "Texture Atlas Generator - Create Sprite Sheets Online", - description: "Generate texture atlases and sprite sheets for game development. Pack multiple sprites into a single texture atlas with JSON data export.", + title: "Texture Atlas Generator - Create Sprite Sheets Online Free", + description: "Free online texture atlas and sprite sheet generator for game development. Pack multiple sprites into optimized atlases with JSON data export.", }, zh: { - title: "纹理图集生成器 - 在线创建精灵图", - description: "为游戏开发生成纹理图集和精灵图。将多个精灵打包到单个纹理图集中,支持导出 JSON 数据。", + title: "纹理图集生成器 - 免费在线创建精灵图", + description: "免费在线纹理图集和精灵图生成器。将多个精灵打包到优化的图集中,支持导出 JSON 数据。", }, - lastModified: new Date("2025-01-01"), + lastModified: new Date("2026-02-08"), + priority: 0.8, }, ]; @@ -65,14 +70,8 @@ export default async function sitemap(): Promise { { url: baseUrl, lastModified: new Date(), - changeFrequency: "daily", - priority: 1, - }, - { - url: `${baseUrl}/tools`, - lastModified: new Date(), changeFrequency: "weekly", - priority: 0.9, + priority: 1, }, ]; @@ -80,7 +79,7 @@ export default async function sitemap(): Promise { url: `${baseUrl}${tool.path}`, lastModified: tool.lastModified, changeFrequency: "weekly" as const, - priority: 0.8, + priority: tool.priority, })); return [...staticPages, ...toolPages]; diff --git a/src/components/seo/StructuredData.tsx b/src/components/seo/StructuredData.tsx index cfb3aaa..68e7455 100644 --- a/src/components/seo/StructuredData.tsx +++ b/src/components/seo/StructuredData.tsx @@ -37,14 +37,6 @@ export function WebSiteStructuredData({ lang = "en" }: WebSiteProps) { keywords: "image compression, image converter, WebP converter, PNG optimizer, video converter, video to frame sequence, audio compression, texture atlas, sprite sheet generator, game development tools, browser-based tools", 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: "KYMR.TOP", @@ -155,3 +147,34 @@ export function SoftwareApplicationStructuredData({ /> ); } + +interface BreadcrumbItem { + name: string; + url: string; +} + +interface BreadcrumbProps { + items: BreadcrumbItem[]; +} + +export function BreadcrumbStructuredData({ items }: BreadcrumbProps) { + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://kymr.top"; + + const data = { + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: items.map((item, index) => ({ + "@type": "ListItem", + position: index + 1, + name: item.name, + item: `${baseUrl}${item.url}`, + })), + }; + + return ( +