fix(seo): add structured data for sitelinks and fix OG image

Replace Organization schema with WebSite schema, add SiteNavigationElement
for Documentation/FAQ/GitHub/Contact/Discord. Add BreadcrumbList to FAQ
and Contact pages. Remove outdated og-image.svg (source already uses PNG).
Update sitemap with lastmod and changefreq.
This commit is contained in:
SnapOtter
2026-05-16 23:11:39 +08:00
parent 148118d969
commit df2d1286d6
5 changed files with 96 additions and 18 deletions
-12
View File
@@ -1,12 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630">
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#f59e0b"/>
<stop offset="100%" style="stop-color:#ea580c"/>
</linearGradient>
</defs>
<rect width="1200" height="630" fill="url(#bg)"/>
<text x="600" y="280" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="72" font-weight="800" fill="white">SnapOtter</text>
<text x="600" y="350" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="28" font-weight="400" fill="rgba(255,255,255,0.85)">Self-Hosted Image Processing</text>
<text x="600" y="400" text-anchor="middle" font-family="system-ui, -apple-system, sans-serif" font-size="20" font-weight="400" fill="rgba(255,255,255,0.6)">50+ Tools · Local AI · 100% Offline · Open Source</text>
</svg>

Before

Width:  |  Height:  |  Size: 935 B

+11 -1
View File
@@ -2,22 +2,32 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://snapotter.com/</loc>
<lastmod>2026-05-16</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://snapotter.com/faq</loc>
<priority>0.7</priority>
<lastmod>2026-05-16</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
<url>
<loc>https://snapotter.com/contact</loc>
<lastmod>2026-05-16</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
</url>
<url>
<loc>https://snapotter.com/privacy</loc>
<lastmod>2026-05-16</lastmod>
<changefreq>yearly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://snapotter.com/terms</loc>
<lastmod>2026-05-16</lastmod>
<changefreq>yearly</changefreq>
<priority>0.3</priority>
</url>
</urlset>
+11
View File
@@ -6,8 +6,18 @@ import { useState } from "react";
import { FadeIn } from "@/components/fade-in";
import { Footer } from "@/components/footer";
import { JsonLd } from "@/components/json-ld";
import { Navbar } from "@/components/navbar";
const breadcrumbJsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: [
{ "@type": "ListItem", position: 1, name: "Home", item: "https://snapotter.com" },
{ "@type": "ListItem", position: 2, name: "Contact", item: "https://snapotter.com/contact" },
],
};
const benefits = [
{
icon: Monitor,
@@ -63,6 +73,7 @@ export default function ContactPage() {
return (
<>
<JsonLd data={breadcrumbJsonLd} />
<Navbar />
<main className="pt-16">
<section className="px-6 py-24 md:py-32">
+10
View File
@@ -85,10 +85,20 @@ const faqJsonLd = {
})),
};
const breadcrumbJsonLd = {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: [
{ "@type": "ListItem", position: 1, name: "Home", item: "https://snapotter.com" },
{ "@type": "ListItem", position: 2, name: "FAQ", item: "https://snapotter.com/faq" },
],
};
export default function FaqPage() {
return (
<>
<JsonLd data={faqJsonLd} />
<JsonLd data={breadcrumbJsonLd} />
<Navbar />
<main className="pt-16">
<section className="px-6 py-24 md:py-32">
+64 -5
View File
@@ -15,13 +15,27 @@ export const metadata: Metadata = {
alternates: { canonical: "https://snapotter.com" },
};
const organizationJsonLd = {
const websiteJsonLd = {
"@context": "https://schema.org",
"@type": "Organization",
"@type": "WebSite",
name: "SnapOtter",
url: "https://snapotter.com",
logo: "https://snapotter.com/logo.png",
sameAs: ["https://github.com/snapotter-hq/snapotter", "https://discord.gg/hr3s7HPUsr"],
description:
"52 image processing tools with local AI. Runs 100% offline. No data leaves your network.",
publisher: {
"@type": "Organization",
name: "SnapOtter",
url: "https://snapotter.com",
logo: {
"@type": "ImageObject",
url: "https://snapotter.com/logo.png",
},
sameAs: [
"https://github.com/snapotter-hq/snapotter",
"https://discord.gg/hr3s7HPUsr",
"https://hub.docker.com/r/snapotter/snapotter",
],
},
};
const softwareJsonLd = {
@@ -41,15 +55,60 @@ const softwareJsonLd = {
url: "https://snapotter.com",
downloadUrl: "https://hub.docker.com/r/snapotter/snapotter",
screenshot: "https://snapotter.com/og-image.png",
image: "https://snapotter.com/og-image.png",
featureList:
"Image Resize, Image Crop, Image Compression, Format Conversion, Watermarking, Background Removal, Image Upscaling, OCR, Face Detection, Photo Restoration, Batch Processing, REST API, Pipeline Automation",
};
const navigationJsonLd = {
"@context": "https://schema.org",
"@type": "ItemList",
name: "SnapOtter Site Navigation",
itemListElement: [
{
"@type": "SiteNavigationElement",
position: 1,
name: "Documentation",
description: "Installation guides, API reference, and configuration docs",
url: "https://docs.snapotter.com",
},
{
"@type": "SiteNavigationElement",
position: 2,
name: "FAQ",
description: "Frequently asked questions about SnapOtter",
url: "https://snapotter.com/faq",
},
{
"@type": "SiteNavigationElement",
position: 3,
name: "GitHub",
description: "Source code, issues, and discussions",
url: "https://github.com/snapotter-hq/snapotter",
},
{
"@type": "SiteNavigationElement",
position: 4,
name: "Contact",
description: "Book a demo or discuss enterprise licensing",
url: "https://snapotter.com/contact",
},
{
"@type": "SiteNavigationElement",
position: 5,
name: "Discord",
description: "Community chat and support",
url: "https://discord.gg/hr3s7HPUsr",
},
],
};
export default function Home() {
return (
<>
<JsonLd data={organizationJsonLd} />
<JsonLd data={websiteJsonLd} />
<JsonLd data={softwareJsonLd} />
<JsonLd data={navigationJsonLd} />
<Navbar />
<main>
<Hero />