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
+52
View File
@@ -0,0 +1,52 @@
import * as React from "react";
const QUESTIONS = [
{
q: "I am not technical. Is that a problem?",
a: "No. I explain what I am doing in plain language, and you can ask at any time. You do not need to read code.",
},
{
q: "How long am I committed?",
a: "Project work is billed by effort. Either side can end it with two weeks notice to the end of a month.",
},
{
q: "Who owns what you build?",
a: "You do. Code and design belong to you, and you can hand them to another developer.",
},
{
q: "Can you work with our existing team and code?",
a: "Yes. I worked in agencies and product teams for years, so joining an existing project is familiar to me.",
},
{
q: "How do I reach you?",
a: "By email or video call. I work remotely and am available during European business hours.",
},
{
q: "What do you not do?",
a: "Mobile apps for the app stores, Windows software and running your servers. If your project needs those, I say so in the first call.",
},
] as const;
export const Faq: React.FC = () => (
<div className="grid grid-cols-1 gap-x-12 md:grid-cols-2">
{QUESTIONS.map((item) => (
<details
key={item.q}
className="group border-t border-slate-200 py-6 open:pb-8"
>
<summary className="flex cursor-pointer list-none items-start justify-between gap-6 font-sans text-xl font-bold tracking-tight text-slate-900 md:text-2xl [&::-webkit-details-marker]:hidden">
{item.q}
<span
className="mt-1 shrink-0 font-mono text-xl text-slate-400 transition-transform duration-300 group-open:rotate-45"
aria-hidden="true"
>
+
</span>
</summary>
<p className="m-0 mt-4 font-sans text-base leading-relaxed text-slate-500 md:text-lg">
{item.a}
</p>
</details>
))}
</div>
);