- Add 15 optimized WebP images for portfolio (21-53KB each) - Redesign Hero section with full-width background image - Add SSR support for Hero component - Update About section with new portrait image - Update Contact page with professional headshot - Add images to Services/Leistungen page - Add image optimization script (sharp) - Update translations for gallery section Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
759 lines
21 KiB
TypeScript
759 lines
21 KiB
TypeScript
import { type Locale } from '@/i18n/config';
|
|
|
|
interface JsonLdProps {
|
|
locale: Locale;
|
|
}
|
|
|
|
export function PersonJsonLd({ locale }: JsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Person',
|
|
'@id': `${baseUrl}/#person`,
|
|
name: 'Damjan Savić',
|
|
givenName: 'Damjan',
|
|
familyName: 'Savić',
|
|
jobTitle: locale === 'de'
|
|
? 'AI & Automation Specialist | Fullstack Entwickler'
|
|
: locale === 'sr'
|
|
? 'AI & Automation Specialist | Fullstack Developer'
|
|
: 'AI & Automation Specialist | Fullstack Developer',
|
|
description: locale === 'de'
|
|
? 'Entwicklung von KI-Agenten und Automatisierungslösungen. Von Voice-AI-Plattformen bis zu autonomen Web-Agenten.'
|
|
: locale === 'sr'
|
|
? 'Razvoj AI agenata i rešenja za automatizaciju. Od voice AI platformi do autonomnih web agenata.'
|
|
: 'Remote AI developer building AI agents and automation solutions for clients in USA, UK and Europe. From voice AI platforms to autonomous web agents.',
|
|
url: baseUrl,
|
|
image: `${baseUrl}/images/og-image.jpg`,
|
|
email: 'info@damjan-savic.com',
|
|
telephone: '+491756950979',
|
|
address: {
|
|
'@type': 'PostalAddress',
|
|
addressLocality: locale === 'sr' ? 'Keln' : locale === 'en' ? 'Cologne' : 'Köln',
|
|
addressRegion: 'NRW',
|
|
addressCountry: 'DE',
|
|
},
|
|
sameAs: [
|
|
'https://www.linkedin.com/in/damjansavic/',
|
|
'https://github.com/damjansavic',
|
|
],
|
|
knowsAbout: [
|
|
'Artificial Intelligence',
|
|
'Machine Learning',
|
|
'Process Automation',
|
|
'Voice AI',
|
|
'Web Development',
|
|
'Python',
|
|
'TypeScript',
|
|
'React',
|
|
'Next.js',
|
|
'n8n',
|
|
'SaaS Development',
|
|
],
|
|
alumniOf: [
|
|
{
|
|
'@type': 'EducationalOrganization',
|
|
name: 'FOM Hochschule für Ökonomie & Management',
|
|
},
|
|
],
|
|
hasCredential: [
|
|
{
|
|
'@type': 'EducationalOccupationalCredential',
|
|
name: 'M.A. Software Development',
|
|
credentialCategory: 'degree',
|
|
},
|
|
{
|
|
'@type': 'EducationalOccupationalCredential',
|
|
name: 'B.Sc. Wirtschaftsinformatik',
|
|
credentialCategory: 'degree',
|
|
},
|
|
],
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function ProfessionalServiceJsonLd({ locale }: JsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const serviceNames = {
|
|
de: [
|
|
'KI-Entwicklung',
|
|
'Prozessautomatisierung',
|
|
'Voice AI Entwicklung',
|
|
'SaaS Entwicklung',
|
|
'Fullstack Webentwicklung',
|
|
'n8n Automatisierung',
|
|
],
|
|
en: [
|
|
'AI Development',
|
|
'Process Automation',
|
|
'Voice AI Development',
|
|
'SaaS Development',
|
|
'Fullstack Web Development',
|
|
'n8n Automation',
|
|
],
|
|
sr: [
|
|
'AI Razvoj',
|
|
'Automatizacija procesa',
|
|
'Voice AI Razvoj',
|
|
'SaaS Razvoj',
|
|
'Fullstack Web Razvoj',
|
|
'n8n Automatizacija',
|
|
],
|
|
};
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'ProfessionalService',
|
|
'@id': `${baseUrl}/#business`,
|
|
name: 'Damjan Savić - AI & Automation Specialist',
|
|
description: locale === 'de'
|
|
? 'Freelance AI & Automation Specialist aus Köln. Spezialisiert auf KI-Agenten, Voice AI, Prozessautomatisierung und SaaS-Entwicklung.'
|
|
: locale === 'sr'
|
|
? 'Freelance AI & Automation Specialist iz Kelna. Specijalizovan za AI agente, Voice AI, automatizaciju procesa i SaaS razvoj.'
|
|
: 'Remote AI & Automation Specialist based in Germany, serving clients in USA, UK and Europe. Specialized in AI agents, Voice AI, n8n process automation and custom SaaS development.',
|
|
url: baseUrl,
|
|
logo: `${baseUrl}/images/og-image.jpg`,
|
|
image: `${baseUrl}/images/og-image.jpg`,
|
|
email: 'info@damjan-savic.com',
|
|
telephone: '+491756950979',
|
|
priceRange: '€€€',
|
|
address: {
|
|
'@type': 'PostalAddress',
|
|
streetAddress: 'Rotdornallee',
|
|
addressLocality: locale === 'sr' ? 'Keln' : locale === 'en' ? 'Cologne' : 'Köln',
|
|
addressRegion: 'NRW',
|
|
postalCode: '50769',
|
|
addressCountry: 'DE',
|
|
},
|
|
geo: {
|
|
'@type': 'GeoCoordinates',
|
|
latitude: 50.9375,
|
|
longitude: 6.9603,
|
|
},
|
|
areaServed: [
|
|
// Germany
|
|
{ '@type': 'City', name: 'Cologne' },
|
|
{ '@type': 'City', name: 'Düsseldorf' },
|
|
{ '@type': 'City', name: 'Frankfurt' },
|
|
{ '@type': 'City', name: 'Munich' },
|
|
{ '@type': 'City', name: 'Berlin' },
|
|
{ '@type': 'City', name: 'Hamburg' },
|
|
{ '@type': 'Country', name: 'Germany' },
|
|
// USA
|
|
{ '@type': 'City', name: 'New York' },
|
|
{ '@type': 'City', name: 'Los Angeles' },
|
|
{ '@type': 'City', name: 'San Francisco' },
|
|
{ '@type': 'City', name: 'Miami' },
|
|
{ '@type': 'City', name: 'Chicago' },
|
|
{ '@type': 'Country', name: 'United States' },
|
|
// UK
|
|
{ '@type': 'City', name: 'London' },
|
|
{ '@type': 'Country', name: 'United Kingdom' },
|
|
// Europe
|
|
{ '@type': 'Country', name: 'Austria' },
|
|
{ '@type': 'Country', name: 'Switzerland' },
|
|
],
|
|
hasOfferCatalog: {
|
|
'@type': 'OfferCatalog',
|
|
name: locale === 'de' ? 'Dienstleistungen' : locale === 'sr' ? 'Usluge' : 'Services',
|
|
itemListElement: serviceNames[locale].map((service, index) => ({
|
|
'@type': 'Offer',
|
|
itemOffered: {
|
|
'@type': 'Service',
|
|
name: service,
|
|
},
|
|
position: index + 1,
|
|
})),
|
|
},
|
|
founder: {
|
|
'@id': `${baseUrl}/#person`,
|
|
},
|
|
sameAs: [
|
|
'https://www.linkedin.com/in/damjansavic/',
|
|
'https://github.com/damjansavic',
|
|
],
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function BreadcrumbJsonLd({
|
|
items,
|
|
locale,
|
|
}: {
|
|
items: { name: string; url: string }[];
|
|
locale: Locale;
|
|
}) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'BreadcrumbList',
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
itemListElement: items.map((item, index) => ({
|
|
'@type': 'ListItem',
|
|
position: index + 1,
|
|
name: item.name,
|
|
item: item.url.startsWith('http') ? item.url : `${baseUrl}${item.url}`,
|
|
})),
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export function WebPageJsonLd({
|
|
title,
|
|
description,
|
|
url,
|
|
locale,
|
|
}: {
|
|
title: string;
|
|
description: string;
|
|
url: string;
|
|
locale: Locale;
|
|
}) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebPage',
|
|
name: title,
|
|
description: description,
|
|
url: url.startsWith('http') ? url : `${baseUrl}${url}`,
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
isPartOf: {
|
|
'@type': 'WebSite',
|
|
name: 'Damjan Savić',
|
|
url: baseUrl,
|
|
},
|
|
author: {
|
|
'@id': `${baseUrl}/#person`,
|
|
},
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
interface FAQItem {
|
|
question: string;
|
|
answer: string;
|
|
}
|
|
|
|
export function FAQJsonLd({ items, locale }: { items: FAQItem[]; locale?: Locale }) {
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'FAQPage',
|
|
inLanguage: locale ? (locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US') : 'de-DE',
|
|
mainEntity: items.map((item) => ({
|
|
'@type': 'Question',
|
|
name: item.question,
|
|
acceptedAnswer: {
|
|
'@type': 'Answer',
|
|
text: item.answer,
|
|
},
|
|
})),
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
interface ServiceJsonLdProps {
|
|
name: string;
|
|
description: string;
|
|
url: string;
|
|
locale: Locale;
|
|
areaServed?: string[];
|
|
}
|
|
|
|
export function ServiceJsonLd({
|
|
name,
|
|
description,
|
|
url,
|
|
locale,
|
|
areaServed = ['Köln', 'Düsseldorf', 'Frankfurt', 'Deutschland'],
|
|
}: ServiceJsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Service',
|
|
name: name,
|
|
description: description,
|
|
url: url.startsWith('http') ? url : `${baseUrl}${url}`,
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
availableLanguage: ['de-DE', 'en-US', 'sr-RS'],
|
|
provider: {
|
|
'@id': `${baseUrl}/#business`,
|
|
},
|
|
areaServed: areaServed.map((area) => ({
|
|
'@type': 'City',
|
|
name: area,
|
|
})),
|
|
serviceType: name,
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// Organization Schema
|
|
export function OrganizationJsonLd({ locale }: JsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Organization',
|
|
'@id': `${baseUrl}/#organization`,
|
|
name: 'Damjan Savić - AI & Automation Specialist',
|
|
alternateName: 'Damjan Savić',
|
|
url: baseUrl,
|
|
logo: {
|
|
'@type': 'ImageObject',
|
|
url: `${baseUrl}/images/og-image.jpg`,
|
|
width: 1200,
|
|
height: 630,
|
|
},
|
|
image: `${baseUrl}/images/og-image.jpg`,
|
|
description: locale === 'de'
|
|
? 'Freelance KI-Entwickler und Automatisierungsspezialist aus Köln. Spezialisiert auf KI-Agenten, Voice AI, Prozessautomatisierung mit n8n und SaaS-Entwicklung.'
|
|
: locale === 'sr'
|
|
? 'Freelance AI developer i specijalista za automatizaciju iz Kelna. Specijalizovan za AI agente, Voice AI, automatizaciju procesa sa n8n i SaaS razvoj.'
|
|
: 'Remote AI developer and automation specialist based in Germany. Working with clients in USA, UK & Europe. Specialized in AI agents, Voice AI, n8n automation and SaaS development.',
|
|
email: 'info@damjan-savic.com',
|
|
telephone: '+491756950979',
|
|
address: {
|
|
'@type': 'PostalAddress',
|
|
streetAddress: 'Rotdornallee',
|
|
addressLocality: locale === 'sr' ? 'Keln' : locale === 'en' ? 'Cologne' : 'Köln',
|
|
addressRegion: 'NRW',
|
|
postalCode: '50769',
|
|
addressCountry: 'DE',
|
|
},
|
|
geo: {
|
|
'@type': 'GeoCoordinates',
|
|
latitude: 50.9375,
|
|
longitude: 6.9603,
|
|
},
|
|
areaServed: [
|
|
// DACH Region
|
|
{ '@type': 'Country', name: 'Germany' },
|
|
{ '@type': 'Country', name: 'Austria' },
|
|
{ '@type': 'Country', name: 'Switzerland' },
|
|
// International (Remote)
|
|
{ '@type': 'Country', name: 'United States' },
|
|
{ '@type': 'Country', name: 'United Kingdom' },
|
|
{ '@type': 'Country', name: 'Serbia' },
|
|
// Major International Cities
|
|
{ '@type': 'City', name: 'New York' },
|
|
{ '@type': 'City', name: 'London' },
|
|
{ '@type': 'City', name: 'San Francisco' },
|
|
{ '@type': 'City', name: 'Los Angeles' },
|
|
],
|
|
founder: {
|
|
'@id': `${baseUrl}/#person`,
|
|
},
|
|
sameAs: [
|
|
'https://www.linkedin.com/in/damjansavic/',
|
|
'https://github.com/damjansavic',
|
|
],
|
|
contactPoint: {
|
|
'@type': 'ContactPoint',
|
|
contactType: 'customer service',
|
|
email: 'info@damjan-savic.com',
|
|
telephone: '+491756950979',
|
|
availableLanguage: ['German', 'English', 'Serbian'],
|
|
},
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// Article Schema for Blog Posts
|
|
interface ArticleJsonLdProps {
|
|
title: string;
|
|
description: string;
|
|
url: string;
|
|
imageUrl: string;
|
|
datePublished: string;
|
|
dateModified?: string;
|
|
authorName?: string;
|
|
tags?: string[];
|
|
locale: Locale;
|
|
}
|
|
|
|
export function ArticleJsonLd({
|
|
title,
|
|
description,
|
|
url,
|
|
imageUrl,
|
|
datePublished,
|
|
dateModified,
|
|
authorName = 'Damjan Savić',
|
|
tags = [],
|
|
locale,
|
|
}: ArticleJsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Article',
|
|
headline: title,
|
|
description: description,
|
|
image: imageUrl.startsWith('http') ? imageUrl : `${baseUrl}${imageUrl}`,
|
|
url: url.startsWith('http') ? url : `${baseUrl}${url}`,
|
|
datePublished: datePublished,
|
|
dateModified: dateModified || datePublished,
|
|
author: {
|
|
'@type': 'Person',
|
|
'@id': `${baseUrl}/#person`,
|
|
name: authorName,
|
|
url: baseUrl,
|
|
},
|
|
publisher: {
|
|
'@type': 'Organization',
|
|
'@id': `${baseUrl}/#organization`,
|
|
name: 'Damjan Savić',
|
|
logo: {
|
|
'@type': 'ImageObject',
|
|
url: `${baseUrl}/images/og-image.jpg`,
|
|
},
|
|
},
|
|
mainEntityOfPage: {
|
|
'@type': 'WebPage',
|
|
'@id': url.startsWith('http') ? url : `${baseUrl}${url}`,
|
|
},
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
keywords: tags.join(', '),
|
|
articleSection: 'Technology',
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// HowTo Schema for Tutorials
|
|
interface HowToStep {
|
|
name: string;
|
|
text: string;
|
|
url?: string;
|
|
image?: string;
|
|
}
|
|
|
|
interface HowToJsonLdProps {
|
|
name: string;
|
|
description: string;
|
|
steps: HowToStep[];
|
|
totalTime?: string; // ISO 8601 duration format, e.g., "PT30M" for 30 minutes
|
|
estimatedCost?: { currency: string; value: string };
|
|
tools?: string[];
|
|
supplies?: string[];
|
|
image?: string;
|
|
locale: Locale;
|
|
}
|
|
|
|
export function HowToJsonLd({
|
|
name,
|
|
description,
|
|
steps,
|
|
totalTime,
|
|
estimatedCost,
|
|
tools,
|
|
supplies,
|
|
image,
|
|
locale,
|
|
}: HowToJsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema: Record<string, unknown> = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'HowTo',
|
|
name: name,
|
|
description: description,
|
|
step: steps.map((step, index) => ({
|
|
'@type': 'HowToStep',
|
|
position: index + 1,
|
|
name: step.name,
|
|
text: step.text,
|
|
...(step.url && { url: step.url.startsWith('http') ? step.url : `${baseUrl}${step.url}` }),
|
|
...(step.image && { image: step.image.startsWith('http') ? step.image : `${baseUrl}${step.image}` }),
|
|
})),
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
};
|
|
|
|
if (totalTime) {
|
|
schema.totalTime = totalTime;
|
|
}
|
|
|
|
if (estimatedCost) {
|
|
schema.estimatedCost = {
|
|
'@type': 'MonetaryAmount',
|
|
currency: estimatedCost.currency,
|
|
value: estimatedCost.value,
|
|
};
|
|
}
|
|
|
|
if (tools && tools.length > 0) {
|
|
schema.tool = tools.map((tool) => ({
|
|
'@type': 'HowToTool',
|
|
name: tool,
|
|
}));
|
|
}
|
|
|
|
if (supplies && supplies.length > 0) {
|
|
schema.supply = supplies.map((supply) => ({
|
|
'@type': 'HowToSupply',
|
|
name: supply,
|
|
}));
|
|
}
|
|
|
|
if (image) {
|
|
schema.image = image.startsWith('http') ? image : `${baseUrl}${image}`;
|
|
}
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// ProfilePage Schema for About Page
|
|
interface ProfilePageJsonLdProps {
|
|
locale: Locale;
|
|
}
|
|
|
|
export function ProfilePageJsonLd({ locale }: ProfilePageJsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'ProfilePage',
|
|
dateCreated: '2024-01-01',
|
|
dateModified: new Date().toISOString().split('T')[0],
|
|
mainEntity: {
|
|
'@id': `${baseUrl}/#person`,
|
|
},
|
|
name: locale === 'de'
|
|
? 'Über Damjan Savić - KI-Entwickler & Automatisierungsspezialist'
|
|
: locale === 'sr'
|
|
? 'O Damjanu Saviću - AI Developer & Specijalista za automatizaciju'
|
|
: 'About Damjan Savić - AI Developer & Automation Specialist',
|
|
description: locale === 'de'
|
|
? 'Erfahren Sie mehr über Damjan Savić, Freelance KI-Entwickler und Automatisierungsspezialist aus Köln. Expertise in KI-Agenten, Voice AI, n8n und SaaS-Entwicklung.'
|
|
: locale === 'sr'
|
|
? 'Saznajte više o Damjanu Saviću, freelance AI developeru i specijalisti za automatizaciju iz Kelna. Ekspertiza u AI agentima, Voice AI, n8n i SaaS razvoju.'
|
|
: 'Learn more about Damjan Savić, freelance AI developer and automation specialist from Cologne. Expertise in AI agents, Voice AI, n8n and SaaS development.',
|
|
url: `${baseUrl}/${locale}/about`,
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// VideoObject Schema for embedded videos
|
|
interface VideoJsonLdProps {
|
|
name: string;
|
|
description: string;
|
|
thumbnailUrl: string;
|
|
uploadDate: string;
|
|
duration?: string; // ISO 8601 format, e.g., "PT1M30S"
|
|
contentUrl?: string;
|
|
embedUrl?: string;
|
|
locale: Locale;
|
|
}
|
|
|
|
export function VideoJsonLd({
|
|
name,
|
|
description,
|
|
thumbnailUrl,
|
|
uploadDate,
|
|
duration,
|
|
contentUrl,
|
|
embedUrl,
|
|
locale,
|
|
}: VideoJsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema: Record<string, unknown> = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'VideoObject',
|
|
name: name,
|
|
description: description,
|
|
thumbnailUrl: thumbnailUrl.startsWith('http') ? thumbnailUrl : `${baseUrl}${thumbnailUrl}`,
|
|
uploadDate: uploadDate,
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
author: {
|
|
'@id': `${baseUrl}/#person`,
|
|
},
|
|
};
|
|
|
|
if (duration) {
|
|
schema.duration = duration;
|
|
}
|
|
|
|
if (contentUrl) {
|
|
schema.contentUrl = contentUrl;
|
|
}
|
|
|
|
if (embedUrl) {
|
|
schema.embedUrl = embedUrl;
|
|
}
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// SoftwareApplication Schema for tools/projects
|
|
interface SoftwareAppJsonLdProps {
|
|
name: string;
|
|
description: string;
|
|
applicationCategory: string;
|
|
operatingSystem?: string;
|
|
offers?: {
|
|
price: string;
|
|
priceCurrency: string;
|
|
};
|
|
aggregateRating?: {
|
|
ratingValue: string;
|
|
ratingCount: string;
|
|
};
|
|
locale: Locale;
|
|
}
|
|
|
|
export function SoftwareAppJsonLd({
|
|
name,
|
|
description,
|
|
applicationCategory,
|
|
operatingSystem = 'Web',
|
|
offers,
|
|
aggregateRating,
|
|
locale,
|
|
}: SoftwareAppJsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema: Record<string, unknown> = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'SoftwareApplication',
|
|
name: name,
|
|
description: description,
|
|
applicationCategory: applicationCategory,
|
|
operatingSystem: operatingSystem,
|
|
author: {
|
|
'@id': `${baseUrl}/#person`,
|
|
},
|
|
inLanguage: locale === 'de' ? 'de-DE' : locale === 'sr' ? 'sr-RS' : 'en-US',
|
|
};
|
|
|
|
if (offers) {
|
|
schema.offers = {
|
|
'@type': 'Offer',
|
|
price: offers.price,
|
|
priceCurrency: offers.priceCurrency,
|
|
};
|
|
}
|
|
|
|
if (aggregateRating) {
|
|
schema.aggregateRating = {
|
|
'@type': 'AggregateRating',
|
|
ratingValue: aggregateRating.ratingValue,
|
|
ratingCount: aggregateRating.ratingCount,
|
|
};
|
|
}
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// WebSite Schema for Search Box
|
|
export function WebSiteJsonLd({ locale }: JsonLdProps) {
|
|
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
|
|
|
const schema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebSite',
|
|
'@id': `${baseUrl}/#website`,
|
|
name: 'Damjan Savić',
|
|
alternateName: locale === 'de'
|
|
? 'Damjan Savić - KI Entwickler Köln'
|
|
: locale === 'sr'
|
|
? 'Damjan Savić - AI Developer Keln'
|
|
: 'Damjan Savić - AI Developer Cologne',
|
|
url: baseUrl,
|
|
description: locale === 'de'
|
|
? 'Portfolio und Blog von Damjan Savić - KI-Entwickler und Automatisierungsspezialist aus Köln'
|
|
: locale === 'sr'
|
|
? 'Portfolio i blog Damjana Savića - AI developer i specijalista za automatizaciju iz Kelna'
|
|
: 'Portfolio and blog of Damjan Savić - AI Developer and Automation Specialist from Cologne',
|
|
publisher: {
|
|
'@id': `${baseUrl}/#organization`,
|
|
},
|
|
inLanguage: [
|
|
{ '@type': 'Language', name: 'German', alternateName: 'de' },
|
|
{ '@type': 'Language', name: 'English', alternateName: 'en' },
|
|
{ '@type': 'Language', name: 'Serbian', alternateName: 'sr' },
|
|
],
|
|
};
|
|
|
|
return (
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
|
|
/>
|
|
);
|
|
}
|