feat: add downloadable German CV PDF to portfolio hero section

Task: Downloadbarer Lebenslauf als PDF (#5)

Changes:
- Generated a professional German-language PDF CV for Joachim Hummel
  and placed it at artifacts/joachim-portfolio/public/lebenslauf-joachim-hummel.pdf
- PDF includes: header with contact info, Profil summary, full Berufserfahrung
  (5 stations from 2015–present), Skills & Technologien (8 categories with
  styled tags), Methodik & Compliance badges, and Online-Präsenz links
- PDF generated via a temporary pdfkit Node.js script — no new runtime
  dependency added to the workspace packages
- Added "Lebenslauf herunterladen" button to hero.tsx CTA button row,
  with a Download icon from lucide-react and the `download` attribute
  set so the browser triggers a file save dialog
- Button links to /lebenslauf-joachim-hummel.pdf (served from Vite public/)
  and is fully accessible on mobile

No deviations from the task spec.

Replit-Task-Id: 476fd3be-9524-477c-a069-edf58213f2e2
This commit is contained in:
joachimhummel
2026-05-15 15:54:22 +00:00
parent eb5e4dc5e1
commit 6840b32713
3 changed files with 12 additions and 1 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -1,5 +1,5 @@
import { motion } from "framer-motion"; import { motion } from "framer-motion";
import { ArrowRight, ChevronDown } from "lucide-react"; import { ArrowRight, ChevronDown, Download } from "lucide-react";
const badges = [ const badges = [
"30+ Jahre IT-Erfahrung", "30+ Jahre IT-Erfahrung",
@@ -76,6 +76,17 @@ export function Hero() {
> >
Projekte ansehen Projekte ansehen
</a> </a>
<a
href="/lebenslauf-joachim-hummel.pdf"
download="Lebenslauf-Joachim-Hummel.pdf"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-6 py-3 bg-white text-foreground font-semibold rounded-xl border border-border hover:bg-secondary transition-all"
data-testid="button-hero-cv-download"
>
<Download className="w-4 h-4" />
Lebenslauf herunterladen
</a>
</div> </div>
</motion.div> </motion.div>