feat: Add professional portfolio images and Hero redesign
- 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>
This commit is contained in:
@@ -1,53 +1,160 @@
|
||||
import { setRequestLocale } from 'next-intl/server';
|
||||
import type { Metadata } from 'next';
|
||||
import { getTranslations } from 'next-intl/server';
|
||||
import Link from 'next/link';
|
||||
import { PortfolioGrid } from '@/components/portfolio';
|
||||
|
||||
type Props = {
|
||||
params: Promise<{ locale: string }>;
|
||||
};
|
||||
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://damjan-savic.com';
|
||||
|
||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
const t = await getTranslations({ locale, namespace: 'portfolio.seo' });
|
||||
|
||||
const keywords: Record<string, string[]> = {
|
||||
de: [
|
||||
'Portfolio Damjan Savić',
|
||||
'KI Projekte',
|
||||
'Automatisierung Projekte',
|
||||
'Python Entwicklung',
|
||||
'React Projekte',
|
||||
'RFID IoT',
|
||||
'n8n Automatisierung',
|
||||
'Web Entwicklung Köln',
|
||||
],
|
||||
en: [
|
||||
'AI Developer Portfolio',
|
||||
'AI Projects',
|
||||
'Automation Projects',
|
||||
'Python Development',
|
||||
'React Projects',
|
||||
'n8n Automation',
|
||||
'Remote Developer Portfolio',
|
||||
'Hire AI Developer',
|
||||
'AI Agent Projects',
|
||||
'Voice AI Projects',
|
||||
'SaaS Development Portfolio',
|
||||
],
|
||||
sr: [
|
||||
'Portfolio Damjan Savić',
|
||||
'AI Projekti',
|
||||
'Automatizacija Projekti',
|
||||
'Python Razvoj',
|
||||
'React Projekti',
|
||||
'RFID IoT',
|
||||
'n8n Automatizacija',
|
||||
'Web Razvoj Keln',
|
||||
],
|
||||
};
|
||||
|
||||
const localePath = locale === 'de' ? '/portfolio' : `/${locale}/portfolio`;
|
||||
|
||||
return {
|
||||
title: t('title'),
|
||||
description: t('description'),
|
||||
keywords: keywords[locale] || keywords.de,
|
||||
alternates: {
|
||||
canonical: `${BASE_URL}${localePath}`,
|
||||
languages: {
|
||||
'x-default': `${BASE_URL}/portfolio`,
|
||||
de: `${BASE_URL}/portfolio`,
|
||||
en: `${BASE_URL}/en/portfolio`,
|
||||
sr: `${BASE_URL}/sr/portfolio`,
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: t('title'),
|
||||
description: t('description'),
|
||||
url: `${BASE_URL}${localePath}`,
|
||||
type: 'website',
|
||||
locale: locale === 'de' ? 'de_DE' : locale === 'sr' ? 'sr_RS' : 'en_US',
|
||||
alternateLocale: ['de_DE', 'en_US', 'sr_RS'].filter(l => l !== (locale === 'de' ? 'de_DE' : locale === 'sr' ? 'sr_RS' : 'en_US')),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Project data for SSG
|
||||
const projects = [
|
||||
{
|
||||
slug: 'ai-data-reader',
|
||||
title: 'AI Data Reader',
|
||||
description: 'KI-gestuetzte PDF-Datenextraktion mit Claude AI und JTL-Integration',
|
||||
category: 'Data Processing',
|
||||
technologies: ['Python', 'FastAPI', 'Claude AI', 'JTL-Wawi'],
|
||||
title: 'AI Document Reader',
|
||||
description: 'KI-gestützte Dokumentenanalyse mit OLLAMA und Python',
|
||||
excerpt: 'KI-gestützte PDF-Datenextraktion mit Claude AI und JTL-Integration',
|
||||
category: 'AI Development',
|
||||
date: '2024-01',
|
||||
technologies: ['Python', 'OLLAMA', 'FastAPI', 'React', 'Claude AI', 'JTL-Wawi'],
|
||||
featured: true,
|
||||
},
|
||||
{
|
||||
slug: 'smart-warehouse',
|
||||
title: 'Smart Warehouse',
|
||||
description: 'RFID-basierte Lagerverwaltung mit IoT-Integration',
|
||||
category: 'Integration',
|
||||
technologies: ['Python', 'RFID', 'Zebra Hardware', 'PostgreSQL'],
|
||||
title: 'Smart Warehouse RFID',
|
||||
description: 'RFID-basiertes Lagerverwaltungssystem mit IoT-Integration',
|
||||
excerpt: 'RFID-basierte Lagerverwaltung mit Zebra-Hardware und Echtzeit-Tracking',
|
||||
category: 'IoT',
|
||||
date: '2024-02',
|
||||
technologies: ['Python', 'RFID', 'IoT', 'PostgreSQL', 'Zebra Hardware'],
|
||||
featured: true,
|
||||
},
|
||||
{
|
||||
slug: 'website-mit-ki',
|
||||
title: 'KI-Portfolio Website',
|
||||
description: 'Diese Portfolio-Website mit Next.js und modernen Web-Technologien',
|
||||
category: 'Web Development',
|
||||
technologies: ['Next.js', 'TypeScript', 'Tailwind CSS', 'Vercel'],
|
||||
title: 'Portfolio mit KI',
|
||||
description: 'Moderne Portfolio-Website mit KI-Integration',
|
||||
excerpt: 'Next.js 15 Portfolio mit SSR, i18n und modernen Web-Technologien',
|
||||
category: 'Full-Stack',
|
||||
date: '2024-03',
|
||||
technologies: ['Next.js', 'TypeScript', 'Tailwind', 'Supabase', 'React'],
|
||||
featured: true,
|
||||
},
|
||||
{
|
||||
slug: 'power-platform-governance',
|
||||
title: 'Power Platform Governance',
|
||||
description: 'Enterprise Governance-Loesung fuer Microsoft Power Platform',
|
||||
description: 'Enterprise Governance-Lösung für Microsoft Power Platform',
|
||||
excerpt: 'Automatisierte Compliance-Prüfungen und Ressourcenverwaltung',
|
||||
category: 'Enterprise Software',
|
||||
technologies: ['Power Automate', 'SharePoint', 'Azure', 'TypeScript'],
|
||||
date: '2023-11',
|
||||
technologies: ['Power Automate', 'SharePoint', 'Azure', 'TypeScript', 'Power Apps'],
|
||||
featured: false,
|
||||
},
|
||||
{
|
||||
slug: 'automated-ad-creatives',
|
||||
title: 'Automated Ad Creatives',
|
||||
description: 'Automatisierte Erstellung von Werbeanzeigen',
|
||||
excerpt: 'KI-gestützte Generierung von Marketing-Creatives',
|
||||
category: 'AI Development',
|
||||
date: '2023-10',
|
||||
technologies: ['Python', 'OpenAI', 'Pillow', 'FastAPI'],
|
||||
featured: false,
|
||||
},
|
||||
{
|
||||
slug: 'kamenpro',
|
||||
title: 'KamenPro',
|
||||
description: 'E-Commerce Platform für Steinprodukte',
|
||||
excerpt: 'Shopify-basierte E-Commerce-Lösung mit ERP-Integration',
|
||||
category: 'E-Commerce',
|
||||
date: '2023-08',
|
||||
technologies: ['Shopify', 'JavaScript', 'Liquid', 'ERP Integration'],
|
||||
featured: false,
|
||||
},
|
||||
{
|
||||
slug: 'ai-music-production',
|
||||
title: 'AI Music Production',
|
||||
description: 'KI-gestützte Musikproduktion',
|
||||
excerpt: 'Automatisierte Musikgenerierung mit Machine Learning',
|
||||
category: 'AI Development',
|
||||
date: '2023-06',
|
||||
technologies: ['Python', 'TensorFlow', 'MIDI', 'Audio Processing'],
|
||||
featured: false,
|
||||
},
|
||||
{
|
||||
slug: 'cursor-ide',
|
||||
title: 'Cursor IDE Integration',
|
||||
description: 'AI-gestützte Entwicklungsumgebung',
|
||||
excerpt: 'Integration von KI-Assistenten in den Entwicklungsworkflow',
|
||||
category: 'Developer Tools',
|
||||
date: '2023-05',
|
||||
technologies: ['TypeScript', 'VS Code API', 'Claude AI', 'GPT-4'],
|
||||
featured: false,
|
||||
},
|
||||
];
|
||||
@@ -59,65 +166,21 @@ export default async function PortfolioPage({ params }: Props) {
|
||||
const t = await getTranslations('portfolio');
|
||||
|
||||
return (
|
||||
<main className="min-h-screen py-20 px-4">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Breadcrumb */}
|
||||
<nav className="mb-8">
|
||||
<Link href={`/${locale}`} className="text-zinc-400 hover:text-white transition-colors">
|
||||
Home
|
||||
</Link>
|
||||
<span className="text-zinc-600 mx-2">/</span>
|
||||
<span className="text-white">Portfolio</span>
|
||||
</nav>
|
||||
|
||||
{/* Header */}
|
||||
<section className="mb-16">
|
||||
<h1 className="text-4xl sm:text-5xl font-bold mb-4">{t('sections.title')}</h1>
|
||||
<p className="text-zinc-400 text-lg max-w-2xl">
|
||||
{t('sections.subtitle')}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{/* Projects Grid */}
|
||||
<section>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
{projects.map((project) => (
|
||||
<Link
|
||||
key={project.slug}
|
||||
href={`/${locale}/portfolio/${project.slug}`}
|
||||
className="group bg-zinc-800/50 rounded-lg overflow-hidden border border-zinc-700/50 hover:border-zinc-600 transition-colors"
|
||||
>
|
||||
<div className="aspect-video bg-zinc-700/50 flex items-center justify-center">
|
||||
<span className="text-zinc-500 text-sm">{project.category}</span>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="flex items-start justify-between mb-2">
|
||||
<h2 className="text-xl font-semibold text-white group-hover:text-blue-400 transition-colors">
|
||||
{project.title}
|
||||
</h2>
|
||||
{project.featured && (
|
||||
<span className="text-xs bg-blue-600/20 text-blue-400 px-2 py-1 rounded">
|
||||
Featured
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-zinc-400 mb-4">{project.description}</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{project.technologies.map((tech) => (
|
||||
<span
|
||||
key={tech}
|
||||
className="text-xs bg-zinc-700/50 text-zinc-300 px-2 py-1 rounded"
|
||||
>
|
||||
{tech}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
<div className="relative min-h-screen">
|
||||
<section className="py-24">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="text-center mb-16">
|
||||
<h1 className="text-3xl font-bold text-white mb-4">
|
||||
{t('sections.title')}
|
||||
</h1>
|
||||
<p className="text-zinc-400 max-w-2xl mx-auto">
|
||||
{t('sections.subtitle')}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<PortfolioGrid projects={projects} />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user