feat: add hero background images to case study detail pages
Some checks failed
Build & Push / build-and-push (push) Has been cancelled
Some checks failed
Build & Push / build-and-push (push) Has been cancelled
Each project page now has its image behind the hero text with a dark gradient overlay for readability. Tags use a glass-morphism style on the image background. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import Image from 'next/image';
|
||||||
import { notFound } from 'next/navigation';
|
import { notFound } from 'next/navigation';
|
||||||
import { setRequestLocale } from 'next-intl/server';
|
import { setRequestLocale } from 'next-intl/server';
|
||||||
import { routing } from '@/i18n/routing';
|
import { routing } from '@/i18n/routing';
|
||||||
@@ -17,6 +18,7 @@ interface Project {
|
|||||||
outcome: string;
|
outcome: string;
|
||||||
techStack: string[];
|
techStack: string[];
|
||||||
tags: string[];
|
tags: string[];
|
||||||
|
image: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Data (will come from Payload CMS) ────────────────────────────────────────
|
// ─── Data (will come from Payload CMS) ────────────────────────────────────────
|
||||||
@@ -35,6 +37,7 @@ const PROJECTS: Record<string, Project> = {
|
|||||||
"The platform processed over 200 submissions in its first season, reducing judge workload by 40% through AI-assisted pre-screening. The client praised the system's reliability and the elegance of its interface.",
|
"The platform processed over 200 submissions in its first season, reducing judge workload by 40% through AI-assisted pre-screening. The client praised the system's reliability and the elegance of its interface.",
|
||||||
techStack: ['Next.js', 'PostgreSQL', 'OpenAI API', 'Docker', 'Private Cloud'],
|
techStack: ['Next.js', 'PostgreSQL', 'OpenAI API', 'Docker', 'Private Cloud'],
|
||||||
tags: ['AI Integration', 'Platform'],
|
tags: ['AI Integration', 'Platform'],
|
||||||
|
image: '/images/monaco_high_res.jpg',
|
||||||
},
|
},
|
||||||
'port-nimara': {
|
'port-nimara': {
|
||||||
title: 'Port Nimara',
|
title: 'Port Nimara',
|
||||||
@@ -48,6 +51,7 @@ const PROJECTS: Record<string, Project> = {
|
|||||||
'The new platform increased online berth inquiries by 3x and provided the port authority with real-time content management capabilities they previously lacked.',
|
'The new platform increased online berth inquiries by 3x and provided the port authority with real-time content management capabilities they previously lacked.',
|
||||||
techStack: ['Nuxt.js', 'Directus CMS', 'Node.js', 'Docker'],
|
techStack: ['Nuxt.js', 'Directus CMS', 'Node.js', 'Docker'],
|
||||||
tags: ['Website', 'Infrastructure'],
|
tags: ['Website', 'Infrastructure'],
|
||||||
|
image: '/images/anguilla.png',
|
||||||
},
|
},
|
||||||
'port-amador': {
|
'port-amador': {
|
||||||
title: 'Port Amador',
|
title: 'Port Amador',
|
||||||
@@ -61,6 +65,7 @@ const PROJECTS: Record<string, Project> = {
|
|||||||
"The redesigned platform elevated Port Amador's digital presence to match their premium positioning, with a 60% improvement in page load times and significantly increased organic traffic.",
|
"The redesigned platform elevated Port Amador's digital presence to match their premium positioning, with a 60% improvement in page load times and significantly increased organic traffic.",
|
||||||
techStack: ['Next.js', 'Tailwind CSS', 'Framer Motion', 'Vercel'],
|
techStack: ['Next.js', 'Tailwind CSS', 'Framer Motion', 'Vercel'],
|
||||||
tags: ['Website', 'Infrastructure'],
|
tags: ['Website', 'Infrastructure'],
|
||||||
|
image: '/images/panama.png',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -123,38 +128,53 @@ export default async function CaseStudyPage({ params }: Props) {
|
|||||||
<main>
|
<main>
|
||||||
|
|
||||||
{/* ── Hero ── */}
|
{/* ── Hero ── */}
|
||||||
<section className="bg-surface-low py-24">
|
<section className="relative min-h-[420px] md:min-h-[480px] flex items-end overflow-hidden">
|
||||||
<div className="container mx-auto px-6">
|
{/* Background image */}
|
||||||
<div className="max-w-3xl mx-auto flex flex-col items-center text-center gap-6">
|
<Image
|
||||||
|
src={project.image}
|
||||||
|
alt=""
|
||||||
|
fill
|
||||||
|
className="object-cover"
|
||||||
|
sizes="100vw"
|
||||||
|
priority
|
||||||
|
/>
|
||||||
|
{/* Dark overlay for text readability */}
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-t from-[rgba(25,28,29,0.85)] via-[rgba(25,28,29,0.55)] to-[rgba(25,28,29,0.3)]" />
|
||||||
|
|
||||||
|
<div className="relative z-10 container mx-auto px-6 pb-16 pt-32">
|
||||||
|
<div className="max-w-3xl mx-auto flex flex-col items-center text-center gap-5">
|
||||||
|
|
||||||
{/* Tags */}
|
{/* Tags */}
|
||||||
<ScrollReveal variant="fadeIn">
|
<ScrollReveal variant="fadeIn">
|
||||||
<div className="flex flex-wrap items-center justify-center gap-2">
|
<div className="flex flex-wrap items-center justify-center gap-2">
|
||||||
{project.tags.map((tag) => (
|
{project.tags.map((tag) => (
|
||||||
<Chip key={tag} size="md">
|
<span
|
||||||
|
key={tag}
|
||||||
|
className="inline-flex items-center bg-white/15 backdrop-blur-sm text-white/90 text-[0.75rem] font-semibold px-3 py-1 rounded-full leading-none tracking-wide"
|
||||||
|
>
|
||||||
{tag}
|
{tag}
|
||||||
</Chip>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<ScrollReveal variant="fadeUp" delay={0.08}>
|
<ScrollReveal variant="fadeUp" delay={0.08}>
|
||||||
<h1 className="font-serif font-semibold text-on-surface text-4xl md:text-5xl lg:text-[3.25rem] leading-[1.1] tracking-[-0.02em]">
|
<h1 className="font-serif font-semibold text-white text-4xl md:text-5xl lg:text-[3.25rem] leading-[1.1] tracking-[-0.02em]">
|
||||||
{project.title}
|
{project.title}
|
||||||
</h1>
|
</h1>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
{/* Subtitle */}
|
{/* Subtitle */}
|
||||||
<ScrollReveal variant="fadeUp" delay={0.16}>
|
<ScrollReveal variant="fadeUp" delay={0.16}>
|
||||||
<p className="label-md text-primary tracking-widest">
|
<p className="label-md text-white/70 tracking-widest">
|
||||||
{project.subtitle}
|
{project.subtitle}
|
||||||
</p>
|
</p>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|
||||||
{/* Description */}
|
{/* Description */}
|
||||||
<ScrollReveal variant="fadeUp" delay={0.22}>
|
<ScrollReveal variant="fadeUp" delay={0.22}>
|
||||||
<p className="text-outline text-lg leading-relaxed max-w-2xl">
|
<p className="text-white/80 text-lg leading-relaxed max-w-2xl">
|
||||||
{project.description}
|
{project.description}
|
||||||
</p>
|
</p>
|
||||||
</ScrollReveal>
|
</ScrollReveal>
|
||||||
|
|||||||
Reference in New Issue
Block a user