feat: 全面优化 SEO 元数据、结构化数据和站点地图
为所有工具页面添加 canonical URL、keywords、SoftwareApplication 和 BreadcrumbList 结构化数据,优化标题和描述以包含搜索意图关键词, 更新站点地图日期和优先级,移除无效的 SearchAction,新增 PWA manifest。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
16
public/manifest.json
Normal file
16
public/manifest.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData";
|
||||||
|
|
||||||
export async function generateMetadata(): Promise<Metadata> {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
@@ -7,25 +8,61 @@ export async function generateMetadata(): Promise<Metadata> {
|
|||||||
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
||||||
|
|
||||||
const titles = {
|
const titles = {
|
||||||
en: "Audio Compression - Compress & Convert Audio Files",
|
en: "Audio Compression - Compress & Convert Audio Files Online Free",
|
||||||
zh: "音频压缩 - 压缩并转换音频文件",
|
zh: "音频压缩 - 免费在线压缩并转换音频文件",
|
||||||
};
|
};
|
||||||
|
|
||||||
const descriptions = {
|
const descriptions = {
|
||||||
en: "Compress and convert audio files to various formats including MP3, AAC, OGG, FLAC. Adjust bitrate and sample rate for optimal quality.",
|
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、AAC、OGG、FLAC。调整比特率和采样率以获得最佳质量。",
|
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 {
|
return {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
keywords: keywords[lang],
|
||||||
|
alternates: {
|
||||||
|
canonical: `${baseUrl}/tools/audio-compress`,
|
||||||
|
},
|
||||||
openGraph: {
|
openGraph: {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
url: `${baseUrl}/tools/audio-compress`,
|
||||||
|
type: "website",
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
card: "summary_large_image",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -35,5 +72,23 @@ export default function AudioCompressLayout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return children;
|
return (
|
||||||
|
<>
|
||||||
|
<SoftwareApplicationStructuredData
|
||||||
|
name="Audio Compressor - KYMR.TOP"
|
||||||
|
description="Free online audio compression and conversion tool. Support MP3, WAV, OGG, AAC, FLAC formats. Browser-based processing with no uploads."
|
||||||
|
url="/tools/audio-compress"
|
||||||
|
category="MultimediaApplication"
|
||||||
|
operatingSystem="Any (Browser-based)"
|
||||||
|
/>
|
||||||
|
<BreadcrumbStructuredData
|
||||||
|
items={[
|
||||||
|
{ name: "Home", url: "/" },
|
||||||
|
{ name: "Tools", url: "/tools" },
|
||||||
|
{ name: "Audio Compression", url: "/tools/audio-compress" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData";
|
||||||
|
|
||||||
export async function generateMetadata(): Promise<Metadata> {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
@@ -7,25 +8,61 @@ export async function generateMetadata(): Promise<Metadata> {
|
|||||||
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
||||||
|
|
||||||
const titles = {
|
const titles = {
|
||||||
en: "Image Compression - Optimize Images for Web & Mobile",
|
en: "Image Compression - Optimize PNG, JPEG, WebP Online Free",
|
||||||
zh: "图片压缩 - 为网页和移动端优化图片",
|
zh: "图片压缩 - 免费在线优化 PNG、JPEG、WebP 图片",
|
||||||
};
|
};
|
||||||
|
|
||||||
const descriptions = {
|
const descriptions = {
|
||||||
en: "Optimize images for web and mobile without quality loss. Support for batch processing and format conversion including 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。",
|
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 {
|
return {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
keywords: keywords[lang],
|
||||||
|
alternates: {
|
||||||
|
canonical: `${baseUrl}/tools/image-compress`,
|
||||||
|
},
|
||||||
openGraph: {
|
openGraph: {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
url: `${baseUrl}/tools/image-compress`,
|
||||||
|
type: "website",
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
card: "summary_large_image",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -35,5 +72,23 @@ export default function ImageCompressLayout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return children;
|
return (
|
||||||
|
<>
|
||||||
|
<SoftwareApplicationStructuredData
|
||||||
|
name="Image Compressor - KYMR.TOP"
|
||||||
|
description="Free online image compression tool. Optimize PNG, JPEG, WebP, AVIF images without quality loss. Browser-based processing with no uploads."
|
||||||
|
url="/tools/image-compress"
|
||||||
|
category="MultimediaApplication"
|
||||||
|
operatingSystem="Any (Browser-based)"
|
||||||
|
/>
|
||||||
|
<BreadcrumbStructuredData
|
||||||
|
items={[
|
||||||
|
{ name: "Home", url: "/" },
|
||||||
|
{ name: "Tools", url: "/tools" },
|
||||||
|
{ name: "Image Compression", url: "/tools/image-compress" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData";
|
||||||
|
|
||||||
export async function generateMetadata(): Promise<Metadata> {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
@@ -7,47 +8,55 @@ export async function generateMetadata(): Promise<Metadata> {
|
|||||||
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
||||||
|
|
||||||
const titles = {
|
const titles = {
|
||||||
en: "Texture Atlas Generator - Create Sprite Sheets Online",
|
en: "Texture Atlas Generator - Create Sprite Sheets Online Free",
|
||||||
zh: "纹理图集生成器 - 在线创建精灵图",
|
zh: "纹理图集生成器 - 免费在线创建精灵图",
|
||||||
};
|
};
|
||||||
|
|
||||||
const descriptions = {
|
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.",
|
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 数据。所有处理都在您的浏览器本地进行。",
|
zh: "免费在线纹理图集和精灵图生成器,专为游戏开发设计。将多个精灵打包到优化的图集中,支持导出 JSON 数据。浏览器本地处理,无需上传。",
|
||||||
};
|
};
|
||||||
|
|
||||||
const keywords = {
|
const keywords = {
|
||||||
en: [
|
en: [
|
||||||
"texture atlas",
|
"texture atlas",
|
||||||
"sprite sheet",
|
"sprite sheet generator",
|
||||||
"game development",
|
"texture packer online",
|
||||||
|
"sprite sheet creator",
|
||||||
|
"game development tools",
|
||||||
"sprite packer",
|
"sprite packer",
|
||||||
"texture packing",
|
|
||||||
"game assets",
|
|
||||||
"sprite generator",
|
|
||||||
"JSON export",
|
"JSON export",
|
||||||
|
"game assets",
|
||||||
|
"texture atlas generator",
|
||||||
"browser-based",
|
"browser-based",
|
||||||
],
|
],
|
||||||
zh: [
|
zh: [
|
||||||
"纹理图集",
|
"纹理图集",
|
||||||
"精灵图",
|
"精灵图生成器",
|
||||||
"游戏开发",
|
"在线纹理打包",
|
||||||
|
"精灵图制作",
|
||||||
|
"游戏开发工具",
|
||||||
"精灵打包",
|
"精灵打包",
|
||||||
"纹理打包",
|
|
||||||
"游戏资产",
|
|
||||||
"精灵生成器",
|
|
||||||
"JSON导出",
|
"JSON导出",
|
||||||
|
"游戏资产",
|
||||||
|
"纹理图集生成器",
|
||||||
"浏览器端",
|
"浏览器端",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || "https://kymr.top";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
keywords: keywords[lang],
|
keywords: keywords[lang],
|
||||||
|
alternates: {
|
||||||
|
canonical: `${baseUrl}/tools/texture-atlas`,
|
||||||
|
},
|
||||||
openGraph: {
|
openGraph: {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
url: `${baseUrl}/tools/texture-atlas`,
|
||||||
type: "website",
|
type: "website",
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
@@ -63,5 +72,23 @@ export default function TextureAtlasLayout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return children;
|
return (
|
||||||
|
<>
|
||||||
|
<SoftwareApplicationStructuredData
|
||||||
|
name="Texture Atlas Generator - KYMR.TOP"
|
||||||
|
description="Free online texture atlas and sprite sheet generator. Pack multiple sprites into optimized atlases with JSON export. Browser-based processing."
|
||||||
|
url="/tools/texture-atlas"
|
||||||
|
category="DeveloperApplication"
|
||||||
|
operatingSystem="Any (Browser-based)"
|
||||||
|
/>
|
||||||
|
<BreadcrumbStructuredData
|
||||||
|
items={[
|
||||||
|
{ name: "Home", url: "/" },
|
||||||
|
{ name: "Tools", url: "/tools" },
|
||||||
|
{ name: "Texture Atlas", url: "/tools/texture-atlas" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
import { SoftwareApplicationStructuredData, BreadcrumbStructuredData } from "@/components/seo/StructuredData";
|
||||||
|
|
||||||
export async function generateMetadata(): Promise<Metadata> {
|
export async function generateMetadata(): Promise<Metadata> {
|
||||||
const headersList = await headers();
|
const headersList = await headers();
|
||||||
@@ -7,25 +8,59 @@ export async function generateMetadata(): Promise<Metadata> {
|
|||||||
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
const lang = acceptLanguage.includes("zh") ? "zh" : "en";
|
||||||
|
|
||||||
const titles = {
|
const titles = {
|
||||||
en: "Video to Frame Sequence - Extract Frame Sequences from Videos",
|
en: "Video to Frame Sequence - Extract Frames from Video Online Free",
|
||||||
zh: "视频转序列帧 - 从视频中提取序列帧",
|
zh: "视频转序列帧 - 免费在线从视频提取帧图片",
|
||||||
};
|
};
|
||||||
|
|
||||||
const descriptions = {
|
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.",
|
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、MOV、AVI、WebM。",
|
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 {
|
return {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
keywords: keywords[lang],
|
||||||
|
alternates: {
|
||||||
|
canonical: `${baseUrl}/tools/video-frames`,
|
||||||
|
},
|
||||||
openGraph: {
|
openGraph: {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
url: `${baseUrl}/tools/video-frames`,
|
||||||
|
type: "website",
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
title: titles[lang],
|
title: titles[lang],
|
||||||
description: descriptions[lang],
|
description: descriptions[lang],
|
||||||
|
card: "summary_large_image",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -35,5 +70,23 @@ export default function VideoFramesLayout({
|
|||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return children;
|
return (
|
||||||
|
<>
|
||||||
|
<SoftwareApplicationStructuredData
|
||||||
|
name="Video Frame Extractor - KYMR.TOP"
|
||||||
|
description="Free online video to frame sequence tool. Extract PNG, WebP, JPEG frames from videos with custom frame rates. Browser-based processing."
|
||||||
|
url="/tools/video-frames"
|
||||||
|
category="MultimediaApplication"
|
||||||
|
operatingSystem="Any (Browser-based)"
|
||||||
|
/>
|
||||||
|
<BreadcrumbStructuredData
|
||||||
|
items={[
|
||||||
|
{ name: "Home", url: "/" },
|
||||||
|
{ name: "Tools", url: "/tools" },
|
||||||
|
{ name: "Video to Frames", url: "/tools/video-frames" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export const metadata: Metadata = {
|
|||||||
icons: {
|
icons: {
|
||||||
icon: "/icon.svg",
|
icon: "/icon.svg",
|
||||||
},
|
},
|
||||||
|
manifest: "/manifest.json",
|
||||||
openGraph: {
|
openGraph: {
|
||||||
type: "website",
|
type: "website",
|
||||||
siteName: "KYMR.TOP",
|
siteName: "KYMR.TOP",
|
||||||
|
|||||||
@@ -5,56 +5,61 @@ interface ToolPage {
|
|||||||
en: { title: string; description: string };
|
en: { title: string; description: string };
|
||||||
zh: { title: string; description: string };
|
zh: { title: string; description: string };
|
||||||
lastModified: Date;
|
lastModified: Date;
|
||||||
|
priority: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tools: ToolPage[] = [
|
const tools: ToolPage[] = [
|
||||||
{
|
{
|
||||||
path: "/tools/image-compress",
|
path: "/tools/image-compress",
|
||||||
en: {
|
en: {
|
||||||
title: "Image Compression - Optimize Images for Web & Mobile",
|
title: "Image Compression - Optimize PNG, JPEG, WebP Online Free",
|
||||||
description: "Optimize images for web and mobile without quality loss. Support for batch processing and format conversion including PNG, JPEG, WebP.",
|
description: "Free online image compressor. Optimize PNG, JPEG, WebP, AVIF images without quality loss. Batch processing, format conversion, browser-based.",
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
title: "图片压缩 - 为网页和移动端优化图片",
|
title: "图片压缩 - 免费在线优化 PNG、JPEG、WebP 图片",
|
||||||
description: "为网页和移动端优化图片,不影响质量。支持批量处理和格式转换,包括 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",
|
path: "/tools/video-frames",
|
||||||
en: {
|
en: {
|
||||||
title: "Video to Frame Sequence - Extract Frame Sequences from Videos",
|
title: "Video to Frame Sequence - Extract Frames from Video Online Free",
|
||||||
description: "Extract frame sequences from videos with precision control. Support for MP4, WebM and other video formats. Export as PNG, WebP or ZIP.",
|
description: "Free online video to frame sequence extractor. Extract PNG, WebP, JPEG frames from MP4, WebM, MOV videos with custom frame rates.",
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
title: "视频转序列帧 - 从视频中提取序列帧",
|
title: "视频转序列帧 - 免费在线从视频提取帧图片",
|
||||||
description: "精确控制从视频中提取序列帧。支持 MP4、WebM 等视频格式。导出为 PNG、WebP 或 ZIP。",
|
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",
|
path: "/tools/audio-compress",
|
||||||
en: {
|
en: {
|
||||||
title: "Audio Compression - Compress & Convert Audio Files",
|
title: "Audio Compression - Compress & Convert Audio Files Online Free",
|
||||||
description: "Compress and convert audio files with ease. Support for MP3, WAV, OGG and more. Adjustable quality settings.",
|
description: "Free online audio compressor and converter. Compress MP3, WAV, OGG, AAC, FLAC files. Browser-based with no uploads required.",
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
title: "音频压缩 - 压缩并转换音频文件",
|
title: "音频压缩 - 免费在线压缩并转换音频文件",
|
||||||
description: "轻松压缩和转换音频文件。支持 MP3、WAV、OGG 等格式。可调节质量设置。",
|
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",
|
path: "/tools/texture-atlas",
|
||||||
en: {
|
en: {
|
||||||
title: "Texture Atlas Generator - Create Sprite Sheets Online",
|
title: "Texture Atlas Generator - Create Sprite Sheets Online Free",
|
||||||
description: "Generate texture atlases and sprite sheets for game development. Pack multiple sprites into a single texture atlas with JSON data export.",
|
description: "Free online texture atlas and sprite sheet generator for game development. Pack multiple sprites into optimized atlases with JSON data export.",
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
title: "纹理图集生成器 - 在线创建精灵图",
|
title: "纹理图集生成器 - 免费在线创建精灵图",
|
||||||
description: "为游戏开发生成纹理图集和精灵图。将多个精灵打包到单个纹理图集中,支持导出 JSON 数据。",
|
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<MetadataRoute.Sitemap> {
|
|||||||
{
|
{
|
||||||
url: baseUrl,
|
url: baseUrl,
|
||||||
lastModified: new Date(),
|
lastModified: new Date(),
|
||||||
changeFrequency: "daily",
|
|
||||||
priority: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: `${baseUrl}/tools`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
changeFrequency: "weekly",
|
changeFrequency: "weekly",
|
||||||
priority: 0.9,
|
priority: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -80,7 +79,7 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
|||||||
url: `${baseUrl}${tool.path}`,
|
url: `${baseUrl}${tool.path}`,
|
||||||
lastModified: tool.lastModified,
|
lastModified: tool.lastModified,
|
||||||
changeFrequency: "weekly" as const,
|
changeFrequency: "weekly" as const,
|
||||||
priority: 0.8,
|
priority: tool.priority,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return [...staticPages, ...toolPages];
|
return [...staticPages, ...toolPages];
|
||||||
|
|||||||
@@ -37,14 +37,6 @@ export function WebSiteStructuredData({ lang = "en" }: WebSiteProps) {
|
|||||||
keywords:
|
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",
|
"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",
|
inLanguage: "en-US",
|
||||||
potentialAction: {
|
|
||||||
"@type": "SearchAction",
|
|
||||||
target: {
|
|
||||||
"@type": "EntryPoint",
|
|
||||||
urlTemplate: `${baseUrl}/search?q={search_term_string}`,
|
|
||||||
},
|
|
||||||
"query-input": "required name=search_term_string",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
zh: {
|
zh: {
|
||||||
name: "KYMR.TOP",
|
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 (
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user