feat: rebuild mintel.me as a single-page freelance site

The site now presents one freelance developer on one page: hero, introduction,
four typical cases (developer for a product, make an app reliable, automate a
process, a website) with what you get, how it runs and what it costs, a
process automation section, technology and project fit, how I work, two live
references, questions and contact.

- Hero and closing headline are drawn from running binary digits.
- Each case explains its four steps with an animated drawing; the automation
  section shows example workflows with work travelling between systems; a
  pipeline run shows what a test catches before a release.
- Contact is one email address, kept in parts and assembled in the browser so
  it never appears in the page source (src/domain/email.ts, spec first).
- Imprint and privacy pages added.
- The old site (blog, case studies, contact form, fixed-price pages, video
  rendering and related scripts) is removed. Its URLs redirect to the homepage.
- The deploy smoke test checks the legal pages and the redirects instead of
  the removed case study.
- Dev scripts use docker compose v2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 22:33:06 +02:00
co-authored by Claude Opus 5.5
parent 4eb663f42a
commit fa40fefe2f
781 changed files with 4925 additions and 55137 deletions
@@ -0,0 +1,85 @@
import * as React from "react";
import { Button } from "@/src/components/Button";
import { AbstractCircuit } from "@/src/components/Effects";
import { BitHeadline, type BitLine } from "./BitHeadline";
const HEADLINE: readonly BitLine[] = [
{ text: "WEB APPS", tone: "solid" },
{ text: "& WEBSITES.", tone: "bits" },
];
const TRUST = ["15 years in web", "Remote, EU core hours"] as const;
export const HeroStatement: React.FC = () => (
<section className="relative overflow-hidden bg-white">
<div className="absolute inset-0 opacity-70">
<AbstractCircuit />
</div>
<div className="relative z-10 mx-auto flex min-h-[calc(100dvh-5rem)] w-full max-w-[1400px] flex-col justify-center px-5 py-16 md:px-12 md:py-24">
<BitHeadline
lines={HEADLINE}
className="font-sans text-[12.5vw] font-black leading-[0.88] tracking-tighter md:text-[11.5vw] xl:text-[10.5rem]"
/>
<div className="mt-10 grid grid-cols-1 gap-10 md:mt-14 md:grid-cols-12 md:items-end md:gap-12">
<p className="m-0 max-w-2xl font-sans text-xl leading-snug text-slate-500 md:col-span-7 md:text-3xl">
Freelance developer with 15 years of experience.{" "}
<span className="text-slate-900">
I build web apps, interfaces and websites.
</span>
</p>
<div className="flex flex-col gap-4 md:col-span-5 md:items-end">
<div
id="hero-cta"
className="flex w-full flex-col gap-4 sm:flex-row md:w-auto"
>
<Button href="#contact" size="large" className="w-full sm:w-auto">
Get in touch
</Button>
<Button
href="#hello"
variant="outline"
size="large"
className="w-full sm:w-auto"
>
What I do
</Button>
</div>
</div>
</div>
<ul className="m-0 mt-14 flex list-none flex-wrap gap-x-8 gap-y-3 border-t border-slate-200 p-0 pt-6 md:mt-20">
{TRUST.map((item) => (
<li
key={item}
className="font-mono text-[10px] uppercase tracking-[0.2em] text-slate-500 md:text-[11px]"
>
{item}
</li>
))}
<li className="font-mono text-[10px] uppercase tracking-[0.2em] text-slate-500 md:text-[11px]">
Built and running:{" "}
<a
href="https://klz-cables.com"
target="_blank"
rel="noopener noreferrer"
className="text-slate-900 underline-offset-4 hover:underline"
>
klz-cables.com
</a>
{" · "}
<a
href="https://e-tib.com"
target="_blank"
rel="noopener noreferrer"
className="text-slate-900 underline-offset-4 hover:underline"
>
e-tib.com
</a>
</li>
</ul>
</div>
</section>
);