From c71916cf08c22c3c538fc93d5fe020e306a4d34b Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Sat, 3 Oct 2026 19:20:05 +0200 Subject: [PATCH] feat: new homepage with hero, proof, offers and live references Co-Authored-By: Claude Sonnet 5.5 --- apps/web/app/(site)/page.tsx | 345 ++---------------- .../src/components/home/AvailabilityPill.tsx | 28 ++ .../src/components/home/BuiltAndRunning.tsx | 47 +++ .../src/components/home/CapacityBlocks.tsx | 35 ++ apps/web/src/components/home/FinalCta.tsx | 20 + apps/web/src/components/home/Hero.tsx | 58 +++ apps/web/src/components/home/HomeJsonLd.tsx | 21 ++ apps/web/src/components/home/HowIShip.tsx | 61 ++++ apps/web/src/components/home/ProofStrip.tsx | 23 ++ .../src/components/home/WebsitesSection.tsx | 33 ++ apps/web/src/components/home/WhatIDo.tsx | 46 +++ 11 files changed, 411 insertions(+), 306 deletions(-) create mode 100644 apps/web/src/components/home/AvailabilityPill.tsx create mode 100644 apps/web/src/components/home/BuiltAndRunning.tsx create mode 100644 apps/web/src/components/home/CapacityBlocks.tsx create mode 100644 apps/web/src/components/home/FinalCta.tsx create mode 100644 apps/web/src/components/home/Hero.tsx create mode 100644 apps/web/src/components/home/HomeJsonLd.tsx create mode 100644 apps/web/src/components/home/HowIShip.tsx create mode 100644 apps/web/src/components/home/ProofStrip.tsx create mode 100644 apps/web/src/components/home/WebsitesSection.tsx create mode 100644 apps/web/src/components/home/WhatIDo.tsx diff --git a/apps/web/app/(site)/page.tsx b/apps/web/app/(site)/page.tsx index 3023b47..eb085a9 100644 --- a/apps/web/app/(site)/page.tsx +++ b/apps/web/app/(site)/page.tsx @@ -1,311 +1,44 @@ -"use client"; +import type { Metadata } from "next"; +import { BuiltAndRunning } from "@/src/components/home/BuiltAndRunning"; +import { CapacityBlocks } from "@/src/components/home/CapacityBlocks"; +import { FinalCta } from "@/src/components/home/FinalCta"; +import { Hero } from "@/src/components/home/Hero"; +import { HomeJsonLd } from "@/src/components/home/HomeJsonLd"; +import { HowIShip } from "@/src/components/home/HowIShip"; +import { ProofStrip } from "@/src/components/home/ProofStrip"; +import { WebsitesSection } from "@/src/components/home/WebsitesSection"; +import { WhatIDo } from "@/src/components/home/WhatIDo"; +import { SITE_NAME } from "@/src/content/site"; -import { Reveal } from "@/src/components/Reveal"; -import { Section } from "@/src/components/Section"; -import { H1, H3, LeadText, BodyText, Label } from "@/src/components/Typography"; -import { Button } from "@/src/components/Button"; -import { HeroSection } from "@/src/components/HeroSection"; -import { Availability } from "@/src/components/Availability"; -import { AbstractCircuit, GradientMesh } from "@/src/components/Effects"; -import { Marker } from "@/src/components/Marker"; -import { GlitchText } from "@/src/components/GlitchText"; +const TITLE = `${SITE_NAME}: senior engineer for AI-built software`; +const DESCRIPTION = + "Senior engineer for teams that build fast with AI and don't want chaos. Spec-first, test-driven, mutation-checked. Booked in weekly capacity blocks."; -export default function LandingPage() { +export const metadata: Metadata = { + title: { absolute: TITLE }, + description: DESCRIPTION, + alternates: { canonical: "/" }, + openGraph: { + title: TITLE, + description: DESCRIPTION, + url: "/", + type: "website", + siteName: SITE_NAME, + }, +}; + +export default function HomePage() { return ( -
- - - - {/* Section 02: Ihr Vorteil */} -
-
- -

- Sie kümmern sich um Ihr Geschäft.{" "} - - Ich mich um Ihre Website. - -

-
- -
- {[ - { - title: "Ein Ansprechpartner", - text: "Direkte Kommunikation. Keine Agentur, keine Projektmanager, kein Stille-Post-Effekt.", - }, - { - title: "Fixpreis", - text: "Keine versteckten Kosten, keine Stundenzettel. Sie wissen exakt, was es kostet.", - }, - { - title: "Schnelle Ergebnisse", - text: "Kein monatelanges Warten. Erste Entwürfe innerhalb weniger Tage.", - }, - { - title: "Null Arbeit für Sie", - text: "Keine CMS-Einarbeitung. Änderungen oder Updates? Eine kurze E-Mail genügt.", - }, - ].map((item, i) => ( - -
-
- - - {item.text} - -
- - ))} -
-
-
- - {/* Section 03: Der Unterschied */} -
-
- -

- Warum nicht einfach{" "} - eine Agentur? -

-
- -
- {[ - { - label: "Agentur", - text: "Projektmanager, Designer, Entwickler — Sie erklären alles drei Mal. Stundenabrechnungen, unklare Endkosten.", - }, - { - label: "Baukasten (Wix, etc.)", - text: "Sie bauen selbst, kämpfen mit Templates und sind auf sich allein gestellt, wenn etwas nicht funktioniert.", - }, - { - label: "Bei mir", - text: "Ein Ansprechpartner. Fixpreis. Ich baue, Sie lehnen sich zurück. Sie brauchen eine Änderung? Kurze Nachricht genügt.", - highlight: true, - }, - ].map((item, i) => ( - -
-
- -
-
- - {item.text} - -
-
-
- ))} -
-
-
- - {/* Section 04: Zielgruppe */} -
-
- -

- Fokus auf das Wesentliche. -

-
- -
- -
-

- Unternehmer & Geschäftsführer -

- - Sie brauchen eine professionelle Website, die Ihr Unternehmen - repräsentiert — ohne sich selbst mit Technik beschäftigen zu - müssen. Ich übernehme alles. - -
-
- -
-

- Selbstständige & kleine Teams -

- - Sie wollen online sichtbar sein, aber keine Zeit in eine - Website stecken. Ich liefere eine fertige Lösung, damit Sie - sich auf Ihre Kunden konzentrieren können. - -
-
-
-
-
- - {/* Section 05: Leistungen */} -
-
- {[ - { - title: "Websites", - text: "Professionelle, schnelle Websites — individuell für Ihr Unternehmen gestaltet. Ohne Overhead.", - href: "/websites", - }, - { - title: "Sorglos-Paket", - text: "Änderungen, Wartung, Sicherheit — alles inklusive. Sie sagen Bescheid, ich erledige das.", - href: "/contact", - }, - { - title: "Web-Anwendungen", - text: "Kundenportale, interne Tools oder individuelle Lösungen für Ihr Business.", - href: "/showcase", - }, - ].map((service, i) => ( - - -
-
-

- {service.title} -

- - {service.text} - -
-
- - - - -
-
-
-
- ))} -
-
- - {/* Section 06: Blog / Insights */} -
-
- -

- Wissen statt Werbung. -

-
- -
- -
- -

- Warum Websites nach Updates oft brechen – und wie man das - verhindert. -

-
- -
-
-
- -
- - Ich teile meine Gedanken zu digitaler Architektur, Fixpreisen - und warum weniger oft mehr ist. - - - Alle Artikel ansehen → - -
-
-
-
-
- - {/* Section 07: Contact */} -
} - > -
- -
-

- Bereit für den Start?
- - - Sagen Sie Hallo. - - -

- -
-
- - Schreiben Sie mir kurz, was Sie vorhaben. Ich melde mich - innerhalb von 24 Stunden bei Ihnen. - -
- -
-
- -
-
-
- -
- - Aktuell nehme ich Projekte für{" "} - - - {" "} - an. - -
-
-
-
-
-
-
+ <> + + + + + + + + + + ); } diff --git a/apps/web/src/components/home/AvailabilityPill.tsx b/apps/web/src/components/home/AvailabilityPill.tsx new file mode 100644 index 0000000..3a3f370 --- /dev/null +++ b/apps/web/src/components/home/AvailabilityPill.tsx @@ -0,0 +1,28 @@ +"use client"; + +import * as React from "react"; +import { Pill } from "@/src/components/site"; +import { AVAILABILITY_CONFIG } from "@/src/content/site"; +import { + formatAvailability, + resolveAvailability, +} from "@/src/domain/availability"; + +const todayIso = (): string => new Date().toISOString().slice(0, 10); + +/** Computes "today" in the browser so a statically rendered page never shows stale availability. */ +export const AvailabilityPill: React.FC = () => { + const [today, setToday] = React.useState(null); + + React.useEffect(() => { + setToday(todayIso()); + }, []); + + if (today === null) return null; + + return ( + + {formatAvailability(resolveAvailability(AVAILABILITY_CONFIG, today))} + + ); +}; diff --git a/apps/web/src/components/home/BuiltAndRunning.tsx b/apps/web/src/components/home/BuiltAndRunning.tsx new file mode 100644 index 0000000..16c0e5c --- /dev/null +++ b/apps/web/src/components/home/BuiltAndRunning.tsx @@ -0,0 +1,47 @@ +import { Container } from "@/src/components/site"; + +type Reference = { + readonly name: string; + readonly href: string; + readonly built: string; +}; + +const REFERENCES: readonly Reference[] = [ + { + name: "klz-cables.com", + href: "https://klz-cables.com", + built: + "multilingual (DE/EN) Next.js site with a headless CMS and generated PDF datasheets", + }, + { + name: "e-tib.com", + href: "https://e-tib.com", + built: + "multilingual Next.js site with structured data, automated QA and CI/CD", + }, +]; + +export const BuiltAndRunning: React.FC = () => ( +
+ +

+ + Built and running + + {REFERENCES.map((ref, index) => ( + + {index > 0 ? " · " : null} + + {ref.name} + {" "} + {ref.built} + + ))} +

+
+
+); diff --git a/apps/web/src/components/home/CapacityBlocks.tsx b/apps/web/src/components/home/CapacityBlocks.tsx new file mode 100644 index 0000000..36ad8bf --- /dev/null +++ b/apps/web/src/components/home/CapacityBlocks.tsx @@ -0,0 +1,35 @@ +import { Container, SectionHeader } from "@/src/components/site"; +import { ENGAGEMENT_BLOCKS } from "@/src/content/site"; + +export const CapacityBlocks: React.FC = () => ( +
+ + +
    + {ENGAGEMENT_BLOCKS.map((block) => ( +
  • +

    + {block.name} +

    +

    + {block.hoursPerWeek} +

    +

    + {block.pricePerMonth} +

    +
  • + ))} +
+

+ 2-week notice, transparent time tracking, no fixed-scope surprises. +

+
+
+); diff --git a/apps/web/src/components/home/FinalCta.tsx b/apps/web/src/components/home/FinalCta.tsx new file mode 100644 index 0000000..79d5346 --- /dev/null +++ b/apps/web/src/components/home/FinalCta.tsx @@ -0,0 +1,20 @@ +import { ButtonLink, Container } from "@/src/components/site"; + +export const FinalCta: React.FC = () => ( +
+ +

+ Tell me what you are building +

+

+ A 20 minute call is enough to see whether a capacity block fits. +

+
+ Book a 20 min call + + Read the notes + +
+
+
+); diff --git a/apps/web/src/components/home/Hero.tsx b/apps/web/src/components/home/Hero.tsx new file mode 100644 index 0000000..a034f05 --- /dev/null +++ b/apps/web/src/components/home/Hero.tsx @@ -0,0 +1,58 @@ +import { ButtonLink, Container, TerminalCard } from "@/src/components/site"; +import { STACK } from "@/src/content/site"; +import { AvailabilityPill } from "./AvailabilityPill"; + +const REPORT_LINES: readonly { label: string; value: string }[] = [ + { label: "spec", value: "12 cases written before code" }, + { label: "red", value: "12 failing for the right reason" }, + { label: "green", value: "12 passing" }, + { label: "mutation", value: "changed files checked, survivors fixed" }, + { label: "coverage", value: "changed lines reviewed for gaps" }, +]; + +export const Hero: React.FC = () => ( +
+ +
+
+
+ +
+

+ AI makes code cheap. +
+ I make it correct. +

+

+ Senior engineer for teams that build fast with AI and don't + want chaos. Spec-first, test-driven, mutation-checked. Booked in + weekly capacity blocks. +

+
+ Book a 20 min call + + See how I ship + +
+
+ +
    + {REPORT_LINES.map((line) => ( +
  • + {line.label} + {line.value} +
  • + ))} +
+

+ Example format. Every real delivery lists the exact commands and + their results. +

+
+
+

+ {STACK.join(" · ")} +

+
+
+); diff --git a/apps/web/src/components/home/HomeJsonLd.tsx b/apps/web/src/components/home/HomeJsonLd.tsx new file mode 100644 index 0000000..8c8d6bc --- /dev/null +++ b/apps/web/src/components/home/HomeJsonLd.tsx @@ -0,0 +1,21 @@ +import { SITE_NAME, SITE_URL } from "@/src/content/site"; + +const STRUCTURED_DATA = { + "@context": "https://schema.org", + "@type": "ProfessionalService", + name: SITE_NAME, + url: SITE_URL, + description: + "Senior freelance engineer for teams that build fast with AI: web apps, AI-code rescue, automation and Web3 frontends.", + founder: { "@type": "Person", name: SITE_NAME }, +} as const; + +/** Serialized server-side from constants only; "<" is escaped to keep it inert inside a script tag. */ +export const HomeJsonLd: React.FC = () => ( +