diff --git a/src/app/[locale]/contact/page.tsx b/src/app/[locale]/contact/page.tsx index 2bded31..237f3e6 100644 --- a/src/app/[locale]/contact/page.tsx +++ b/src/app/[locale]/contact/page.tsx @@ -2,7 +2,7 @@ import { setRequestLocale } from 'next-intl/server'; import type { Metadata } from 'next'; import { getTranslations } from 'next-intl/server'; import { ContactForm } from '@/components/contact'; -import { BreadcrumbJsonLd, WebPageJsonLd } from '@/components/seo'; +import { BreadcrumbJsonLd, WebPageJsonLd, ContactPageJsonLd } from '@/components/seo'; import { type Locale } from '@/i18n/config'; type Props = { @@ -80,6 +80,7 @@ export default async function ContactPage({ params }: Props) { url={`/${locale}/contact`} locale={locale as Locale} /> + ); diff --git a/src/app/[locale]/portfolio/page.tsx b/src/app/[locale]/portfolio/page.tsx index 96b2e3e..9aac3fe 100644 --- a/src/app/[locale]/portfolio/page.tsx +++ b/src/app/[locale]/portfolio/page.tsx @@ -2,6 +2,8 @@ import { setRequestLocale } from 'next-intl/server'; import type { Metadata } from 'next'; import { getTranslations } from 'next-intl/server'; import { PortfolioGrid } from '@/components/portfolio'; +import { BreadcrumbJsonLd, CollectionPageJsonLd } from '@/components/seo'; +import { type Locale } from '@/i18n/config'; type Props = { params: Promise<{ locale: string }>; @@ -165,8 +167,25 @@ export default async function PortfolioPage({ params }: Props) { const t = await getTranslations('portfolio'); + const breadcrumbItems = [ + { name: locale === 'de' ? 'Start' : locale === 'sr' ? 'Početna' : 'Home', url: `/${locale}` }, + { name: 'Portfolio', url: `/${locale}/portfolio` }, + ]; + + // Transform projects for JSON-LD schema + const portfolioProjects = projects.map((project) => ({ + name: project.title, + description: project.description, + url: `/${locale}/portfolio/${project.slug}`, + dateCreated: project.date, + technologies: project.technologies, + })); + return (
+ + +
diff --git a/src/components/seo/JsonLd.tsx b/src/components/seo/JsonLd.tsx index 0077eba..60ab37a 100644 --- a/src/components/seo/JsonLd.tsx +++ b/src/components/seo/JsonLd.tsx @@ -25,7 +25,12 @@ export function PersonJsonLd({ locale }: JsonLdProps) { ? '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`, + image: { + '@type': 'ImageObject', + url: `${baseUrl}/images/og-image.jpg`, + width: 1200, + height: 630, + }, email: 'info@damjan-savic.com', telephone: '+491756950979', address: { @@ -34,6 +39,33 @@ export function PersonJsonLd({ locale }: JsonLdProps) { addressRegion: 'NRW', addressCountry: 'DE', }, + // Languages known + knowsLanguage: [ + { '@type': 'Language', name: 'German', alternateName: 'de' }, + { '@type': 'Language', name: 'English', alternateName: 'en' }, + { '@type': 'Language', name: 'Serbian', alternateName: 'sr' }, + ], + // Current occupation + hasOccupation: { + '@type': 'Occupation', + name: locale === 'de' ? 'Freelance KI-Entwickler' : locale === 'sr' ? 'Freelance AI Developer' : 'Freelance AI Developer', + occupationLocation: { + '@type': 'City', + name: locale === 'sr' ? 'Keln' : locale === 'en' ? 'Cologne' : 'Köln', + }, + skills: [ + 'AI Development', + 'Process Automation', + 'Voice AI', + 'n8n Workflows', + 'SaaS Development', + 'Full-Stack Development', + ], + }, + // Works for self (freelancer) + worksFor: { + '@id': `${baseUrl}/#business`, + }, sameAs: [ 'https://www.linkedin.com/in/damjansavic/', 'https://github.com/damjansavic', @@ -50,6 +82,9 @@ export function PersonJsonLd({ locale }: JsonLdProps) { 'Next.js', 'n8n', 'SaaS Development', + 'Claude AI', + 'GPT-4', + 'LangChain', ], alumniOf: [ { @@ -69,6 +104,11 @@ export function PersonJsonLd({ locale }: JsonLdProps) { credentialCategory: 'degree', }, ], + // Nationality for geo-targeting + nationality: { + '@type': 'Country', + name: 'Germany', + }, }; return ( @@ -719,7 +759,7 @@ export function SoftwareAppJsonLd({ ); } -// WebSite Schema for Search Box +// WebSite Schema for Search Box with SearchAction export function WebSiteJsonLd({ locale }: JsonLdProps) { const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com'; @@ -747,6 +787,197 @@ export function WebSiteJsonLd({ locale }: JsonLdProps) { { '@type': 'Language', name: 'English', alternateName: 'en' }, { '@type': 'Language', name: 'Serbian', alternateName: 'sr' }, ], + // Potential site search action (for future implementation) + potentialAction: { + '@type': 'SearchAction', + target: { + '@type': 'EntryPoint', + urlTemplate: `${baseUrl}/${locale}/portfolio?search={search_term_string}`, + }, + 'query-input': 'required name=search_term_string', + }, + }; + + return ( +