feat: comprehensive SEO system with keywords and schema markup

- Add 4-locale keyword configurations (SR, EN, DE, FR)
- Create schema generators (Product, Organization, Breadcrumb)
- Add React components for JSON-LD rendering
- Implement caching for keyword performance
- Abstract all SEO logic for maintainability
This commit is contained in:
Unchained
2026-03-30 11:22:44 +02:00
parent 767afac606
commit 234b1f1739
17 changed files with 1957 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
import { OrganizationSchema, WebSiteSchema } from './types';
import { getBrandKeywords } from '../keywords';
import { Locale } from '../keywords/types';
interface OrganizationData {
logoUrl: string;
socialProfiles?: string[];
email?: string;
}
/**
* Generate Organization schema (JSON-LD)
* Pure function - takes data, returns schema object
*
* @param baseUrl - Site base URL
* @param locale - Locale code
* @param data - Organization data (logo, social links, etc.)
* @returns OrganizationSchema object
*/
export function generateOrganizationSchema(
baseUrl: string,
locale: Locale,
data: OrganizationData
): OrganizationSchema {
const brandKeywords = getBrandKeywords(locale);
const schema: OrganizationSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: brandKeywords.companyName,
url: baseUrl,
logo: data.logoUrl,
description: brandKeywords.tagline,
};
// Add social profiles if provided
if (data.socialProfiles && data.socialProfiles.length > 0) {
schema.sameAs = data.socialProfiles;
}
// Add contact point if email provided
if (data.email) {
schema.contactPoint = [{
'@type': 'ContactPoint',
contactType: 'customer service',
email: data.email,
availableLanguage: [locale.toUpperCase()],
}];
}
return schema;
}
/**
* Generate WebSite schema (JSON-LD)
* Includes search action for site search
*
* @param baseUrl - Site base URL
* @param locale - Locale code
* @returns WebSiteSchema object
*/
export function generateWebSiteSchema(
baseUrl: string,
locale: Locale
): WebSiteSchema {
const brandKeywords = getBrandKeywords(locale);
return {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: brandKeywords.companyName,
url: baseUrl,
potentialAction: {
'@type': 'SearchAction',
target: `${baseUrl}/search?q={search_term_string}`,
'query-input': 'required name=search_term_string',
},
};
}