mirror of
https://github.com/Such-Software/such.software.git
synced 2026-10-21 06:08:32 +02:00
SEO: keyword-led titles/descriptions, structured data, internal linking
- Rewrite title tags + meta descriptions site-wide to front-load search intent (home, products index, services, apps, support, about, blog, and every product page); keep brand suffix, fix overlong/truncated descriptions, use colons not em dashes. Home keeps the visible 'Precision Engineering' hero; only the <title> changed. De-jargon Webshops away from leading with 'headless'. - Add reusable JSON-LD helper (JsonLd + breadcrumb/softwareApp/article builders). WebSite schema site-wide; BreadcrumbList on all product + blog pages; SoftwareApplication on the apps/games; BlogPosting on posts. - Cross-link the Monero/Wownero cluster (Neroswap, Smirk, Wownerogue, Such Moon Launch) and link products to services. - Data fixes: Vegan IQ corrected to 1,000+ questions with Daily Challenge and Weekly Quiz (page + index); generalize Support page off a single game.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* JSON-LD helpers. `JsonLd` renders a structured-data <script>; the builders return
|
||||
* schema.org objects so pages can stay declarative. Server components only (no client JS).
|
||||
*/
|
||||
const SITE = "https://such.software";
|
||||
|
||||
export function JsonLd({ data }: { data: object }) {
|
||||
return (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Breadcrumb trail for a deep page, e.g. Home › Products › Neroswap. */
|
||||
export function breadcrumbLd(items: { name: string; path: string }[]) {
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: items.map((it, i) => ({
|
||||
"@type": "ListItem",
|
||||
position: i + 1,
|
||||
name: it.name,
|
||||
item: `${SITE}${it.path}`,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
type SoftwareAppOpts = {
|
||||
name: string;
|
||||
path: string;
|
||||
description: string;
|
||||
/** schema.org applicationCategory, e.g. "GameApplication", "FinanceApplication". */
|
||||
category: string;
|
||||
operatingSystem: string;
|
||||
/** Price as a string; "0" for free. */
|
||||
price?: string;
|
||||
/** External play/download URL the offer points at (defaults to the on-site path). */
|
||||
offerUrl?: string;
|
||||
/** Optional store rating, rendered as AggregateRating when provided. */
|
||||
rating?: { value: string; count: string };
|
||||
};
|
||||
|
||||
/** SoftwareApplication node: drives app/game rich results (and star ratings when rated). */
|
||||
export function softwareAppLd(opts: SoftwareAppOpts) {
|
||||
const data: Record<string, unknown> = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
name: opts.name,
|
||||
url: `${SITE}${opts.path}`,
|
||||
description: opts.description,
|
||||
applicationCategory: opts.category,
|
||||
operatingSystem: opts.operatingSystem,
|
||||
offers: {
|
||||
"@type": "Offer",
|
||||
price: opts.price ?? "0",
|
||||
priceCurrency: "USD",
|
||||
url: opts.offerUrl ?? `${SITE}${opts.path}`,
|
||||
},
|
||||
publisher: { "@type": "Organization", name: "Such Software" },
|
||||
};
|
||||
if (opts.rating) {
|
||||
data.aggregateRating = {
|
||||
"@type": "AggregateRating",
|
||||
ratingValue: opts.rating.value,
|
||||
ratingCount: opts.rating.count,
|
||||
};
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/** BlogPosting node for an article page. */
|
||||
export function articleLd(opts: { title: string; description: string; slug: string; date: string }) {
|
||||
const url = `${SITE}/blog/${opts.slug}`;
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BlogPosting",
|
||||
headline: opts.title,
|
||||
description: opts.description,
|
||||
url,
|
||||
mainEntityOfPage: url,
|
||||
datePublished: opts.date,
|
||||
dateModified: opts.date,
|
||||
author: { "@type": "Organization", name: "Such Software" },
|
||||
publisher: {
|
||||
"@type": "Organization",
|
||||
name: "Such Software",
|
||||
logo: { "@type": "ImageObject", url: `${SITE}/images/branding/clean_dark_w_text.svg` },
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user