feat: new homepage with hero, proof, offers and live references

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 19:20:05 +02:00
co-authored by Claude Sonnet 5.5
parent f258e2a483
commit c71916cf08
11 changed files with 411 additions and 306 deletions
@@ -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<string | null>(null);
React.useEffect(() => {
setToday(todayIso());
}, []);
if (today === null) return null;
return (
<Pill>
{formatAvailability(resolveAvailability(AVAILABILITY_CONFIG, today))}
</Pill>
);
};
@@ -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 = () => (
<section className="border-b border-border py-10 md:py-14">
<Container>
<p className="!mb-0 text-sm leading-relaxed text-muted md:text-base">
<span className="mr-2 font-mono text-xs uppercase tracking-widest text-accent">
Built and running
</span>
{REFERENCES.map((ref, index) => (
<span key={ref.name}>
{index > 0 ? " · " : null}
<a
href={ref.href}
rel="noopener"
className="underline underline-offset-4 hover:text-accent"
>
{ref.name}
</a>{" "}
{ref.built}
</span>
))}
</p>
</Container>
</section>
);
@@ -0,0 +1,35 @@
import { Container, SectionHeader } from "@/src/components/site";
import { ENGAGEMENT_BLOCKS } from "@/src/content/site";
export const CapacityBlocks: React.FC = () => (
<section className="border-b border-border py-14 md:py-20">
<Container>
<SectionHeader
kicker="capacity blocks"
title="Book weekly capacity"
lead="You reserve hours per week for a month at a time. No fixed-scope surprises."
/>
<ul className="!m-0 mt-10 grid list-none gap-4 !p-0 md:grid-cols-3">
{ENGAGEMENT_BLOCKS.map((block) => (
<li
key={block.name}
className="!mb-0 rounded-lg border border-border bg-surface p-5"
>
<h3 className="!mb-1 !mt-0 !text-lg !leading-snug md:!text-xl lg:!text-xl">
{block.name}
</h3>
<p className="!mb-4 font-mono text-sm text-muted">
{block.hoursPerWeek}
</p>
<p className="!mb-0 font-mono text-lg font-semibold text-fg">
{block.pricePerMonth}
</p>
</li>
))}
</ul>
<p className="!mb-0 mt-6 text-sm text-muted">
2-week notice, transparent time tracking, no fixed-scope surprises.
</p>
</Container>
</section>
);
+20
View File
@@ -0,0 +1,20 @@
import { ButtonLink, Container } from "@/src/components/site";
export const FinalCta: React.FC = () => (
<section className="py-16 md:py-24">
<Container>
<h2 className="!mb-4 !mt-0 !text-3xl !leading-tight md:!text-4xl">
Tell me what you are building
</h2>
<p className="!mb-8 max-w-xl text-base text-muted md:text-lg">
A 20 minute call is enough to see whether a capacity block fits.
</p>
<div className="flex flex-col gap-3 sm:flex-row">
<ButtonLink href="/book">Book a 20 min call</ButtonLink>
<ButtonLink href="/notes" variant="secondary">
Read the notes
</ButtonLink>
</div>
</Container>
</section>
);
+58
View File
@@ -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 = () => (
<section className="border-b border-border py-14 md:py-24">
<Container>
<div className="grid gap-12 lg:grid-cols-2 lg:items-center">
<div>
<div className="mb-6 min-h-7">
<AvailabilityPill />
</div>
<h1 className="!mb-6 !text-4xl !leading-[1.1] md:!text-6xl">
AI makes code cheap.
<br />
<span className="text-accent">I make it correct.</span>
</h1>
<p className="!mb-8 max-w-xl text-base leading-relaxed text-muted md:text-lg">
Senior engineer for teams that build fast with AI and don&apos;t
want chaos. Spec-first, test-driven, mutation-checked. Booked in
weekly capacity blocks.
</p>
<div className="flex flex-col gap-3 sm:flex-row">
<ButtonLink href="/book">Book a 20 min call</ButtonLink>
<ButtonLink href="/process" variant="secondary">
See how I ship
</ButtonLink>
</div>
</div>
<TerminalCard title="delivery-report (illustrative example)">
<ul className="!m-0 list-none !p-0">
{REPORT_LINES.map((line) => (
<li key={line.label} className="!mb-1 flex gap-3">
<span className="w-20 shrink-0 text-accent">{line.label}</span>
<span className="text-muted">{line.value}</span>
</li>
))}
</ul>
<p className="!mb-0 !mt-4 text-xs text-faint">
Example format. Every real delivery lists the exact commands and
their results.
</p>
</TerminalCard>
</div>
<p className="!mb-0 mt-12 font-mono text-xs text-faint md:text-sm">
{STACK.join(" · ")}
</p>
</Container>
</section>
);
@@ -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 = () => (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(STRUCTURED_DATA).replace(/</g, "\\u003c"),
}}
/>
);
+61
View File
@@ -0,0 +1,61 @@
import Link from "next/link";
import { Container, SectionHeader } from "@/src/components/site";
const STEPS: readonly { name: string; text: string }[] = [
{
name: "Spec first",
text: "The behavior is written down as concrete cases before any code.",
},
{
name: "Red",
text: "The tests run and fail for the right reason: missing behavior.",
},
{
name: "Green",
text: "The simplest clean implementation that makes them pass.",
},
{
name: "Mutation check",
text: "Mutation testing on the changed code shows whether the tests really catch bugs.",
},
{
name: "Delivery report",
text: "Every pull request lists the exact commands that were run and their results.",
},
];
export const HowIShip: React.FC = () => (
<section className="border-b border-border py-14 md:py-20">
<Container>
<SectionHeader
kicker="how I ship"
title="Fast with AI, checked by tests"
lead="AI writes the first draft. These five steps decide whether it ships."
/>
<ol className="!m-0 mt-10 grid list-none gap-4 !p-0 md:grid-cols-5">
{STEPS.map((step, index) => (
<li
key={step.name}
className="!mb-0 rounded-lg border border-border bg-surface p-4"
>
<p className="!mb-2 font-mono text-xs text-accent">
{String(index + 1).padStart(2, "0")}
</p>
<h3 className="!mb-2 !mt-0 !text-base !leading-snug md:!text-base lg:!text-base">
{step.name}
</h3>
<p className="!mb-0 text-sm text-muted">{step.text}</p>
</li>
))}
</ol>
<p className="!mb-0 mt-6 text-sm">
<Link
href="/process"
className="underline underline-offset-4 hover:text-accent"
>
Read the full process and a sample report
</Link>
</p>
</Container>
</section>
);
@@ -0,0 +1,23 @@
import { Container, Stat } from "@/src/components/site";
const FACTS: readonly { value: string; label: string }[] = [
{ value: "15 years", label: "in web, apprenticeship from 2011" },
{ value: "Team lead", label: "frontend team lead at an agency" },
{ value: "Since 2021", label: "working fully remote" },
{
value: "7 chains",
label: "Rust + Solidity DeFi system with a zero-survivor mutation gate",
},
];
export const ProofStrip: React.FC = () => (
<section aria-label="Background" className="border-b border-border py-10">
<Container>
<div className="grid grid-cols-2 gap-8 lg:grid-cols-4">
{FACTS.map((fact) => (
<Stat key={fact.value} value={fact.value} label={fact.label} />
))}
</div>
</Container>
</section>
);
@@ -0,0 +1,33 @@
import { Container, SectionHeader } from "@/src/components/site";
const SPRINT_POINTS: readonly string[] = [
"Time-boxed sprint with a clear scope list, from 3,800 EUR. Extra work is a follow-up block, not open scope.",
"Static Next.js site: no CMS and no server for you to run.",
"Hosting, SSL and domain renewal are included in a flat monthly plan.",
"Changes by email, no CMS training.",
];
export const WebsitesSection: React.FC = () => (
<section className="border-b border-border py-14 md:py-20">
<Container>
<SectionHeader
kicker="websites"
title="Websites, handled end to end"
lead="For clients who want a site and no involvement in the technical side."
/>
<ul className="!m-0 mt-8 max-w-2xl list-none !p-0">
{SPRINT_POINTS.map((point) => (
<li key={point} className="!mb-3 flex gap-3 text-base text-muted">
<span aria-hidden="true" className="font-mono text-accent">
+
</span>
<span>{point}</span>
</li>
))}
</ul>
<p className="!mb-0 mt-4 max-w-2xl font-mono text-sm text-faint">
Not part of it: email and DNS administration.
</p>
</Container>
</section>
);
+46
View File
@@ -0,0 +1,46 @@
import { Container, SectionHeader } from "@/src/components/site";
const OFFERS: readonly { title: string; text: string }[] = [
{
title: "Web and web apps",
text: "Next.js and TypeScript with strong design and frontend work, plus light backend for APIs, auth and integrations.",
},
{
title: "AI-code rescue",
text: "A 1-week entry block: audit of an AI-built codebase, test foundation, mutation baseline and a prioritized report.",
},
{
title: "CLI tools and automation",
text: "Command-line tools and automation, including AI agents and MCP servers.",
},
{
title: "Web3 frontends and systems",
text: "Wallet flows, dashboards and WebSockets, backed by a Rust and Solidity background.",
},
];
export const WhatIDo: React.FC = () => (
<section className="border-b border-border py-14 md:py-20">
<Container>
<SectionHeader kicker="what I do" title="What you can book" />
<ul className="!m-0 mt-10 grid list-none gap-4 !p-0 sm:grid-cols-2">
{OFFERS.map((offer) => (
<li
key={offer.title}
className="!mb-0 rounded-lg border border-border bg-surface p-5"
>
<h3 className="!mb-2 !mt-0 !text-lg !leading-snug md:!text-xl lg:!text-xl">
{offer.title}
</h3>
<p className="!mb-0 text-sm text-muted md:text-base">
{offer.text}
</p>
</li>
))}
</ul>
<p className="!mb-0 mt-6 font-mono text-sm text-faint">
Not offered: Windows apps, mobile apps, running your infrastructure.
</p>
</Container>
</section>
);