Stop the Pitch timeline from repeating dates and talking about omitted stations.

Roles keep the date in period only, self-employment is described as the work itself, and Home workplace copy stays plain.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-26 13:13:40 +02:00
parent 359e887a7a
commit 255f0eace6
5 changed files with 67 additions and 41 deletions

View File

@@ -108,4 +108,30 @@ describe('content claims and attribution', () => {
); );
} }
}); });
it('keeps pitch timeline roles free of the period date', () => {
for (const locale of APP_LOCALES) {
for (const entry of SITE_CONTENT_DATA[locale].pitch.timeline) {
expect(entry.role, `${locale}.${entry.id}`).not.toMatch(/\d{2}\/\d{4}/);
}
}
});
it('keeps Pitch and Home free of editorial omission commentary', () => {
const editorial =
/not listed on this site|auf dieser Seite zu listen|This page shows the public selection|Diese Seite zeigt die öffentliche Auswahl|What this page covers|Was diese Seite abdeckt/i;
for (const locale of APP_LOCALES) {
const site = SITE_CONTENT_DATA[locale];
const text = [
...site.pitch.profile,
...site.pitch.timeline.map((entry) => entry.body),
...site.pitch.sections.flatMap((section) => [section.headline, ...(section.body ?? [])]),
...site.home.sections.flatMap((section) => [section.headline, ...(section.body ?? [])]),
...site.home.serviceAreas.map((area) => area.body),
].join('\n');
expect(editorial.test(text), locale).toBe(false);
}
});
}); });

View File

@@ -20,13 +20,13 @@ export const HOME_DE: HomePageCopy = {
{ {
id: 'workplaces', id: 'workplaces',
title: 'Arbeitsplätze und Netz', title: 'Arbeitsplätze und Netz',
body: 'Geräte, Netz und die Dienste, mit denen Dein Team täglich arbeitet — so geschnitten, dass sich der Alltag tragen lässt.', body: 'Geräte, Netz und die Dienste, mit denen Dein Team täglich arbeitet, bleiben zuverlässig.',
routeId: 'servicesHardwareNetwork', routeId: 'servicesHardwareNetwork',
}, },
{ {
id: 'servers', id: 'servers',
title: 'Server und Cluster', title: 'Server und Cluster',
body: 'Einzelne Hosts, Virtualisierung oder ein Cluster. Der Weg dorthin bleibt nachvollziehbar, on-premise oder auf Azure AKS.', body: 'Einzelne Hosts, Virtualisierung oder ein Cluster. Der Weg dorthin bleibt nachvollziehbar, vor Ort oder auf Azure AKS.',
routeId: 'servicesClusters', routeId: 'servicesClusters',
}, },
{ {
@@ -38,7 +38,7 @@ export const HOME_DE: HomePageCopy = {
{ {
id: 'ai', id: 'ai',
title: 'KI-Abläufe', title: 'KI-Abläufe',
body: 'Zwei umgesetzte Werkzeuge bei der Rösterei Tangermünde. Weitere Bausteine — lokale Modelle, RAG, Mensch in der Schleife — werden auftragsbezogen geprüft.', body: 'Zwei umgesetzte Werkzeuge bei der Rösterei Tangermünde. Weitere Bausteine — lokale Modelle, Suche in eigenen Unterlagen, Prüfung durch einen Menschen — werden je Auftrag geprüft.',
routeId: 'servicesAi', routeId: 'servicesAi',
}, },
], ],
@@ -57,7 +57,7 @@ export const HOME_DE: HomePageCopy = {
{ {
id: 'implement', id: 'implement',
title: 'Umsetzung', title: 'Umsetzung',
body: 'Ein Ansprechpartner setzt um: Software, Infrastruktur, Cluster oder ein schmales KI-Werkzeug, je nach Briefing.', body: 'Ein Ansprechpartner setzt um: Software, Infrastruktur, Cluster oder ein klar umrissenes KI-Werkzeug, je nach Briefing.',
}, },
{ {
id: 'operate', id: 'operate',
@@ -72,7 +72,7 @@ export const HOME_DE: HomePageCopy = {
sections: [ sections: [
{ {
id: 'scope', id: 'scope',
headline: 'Was diese Seite abdeckt', headline: 'Vier Arbeitsbereiche',
body: [ body: [
'Vier Bereiche: Arbeitsplätze und Netz, Server und Cluster, Software und Daten sowie KI-Abläufe. Was nicht dazu gehört, wird im Briefing benannt — nicht stillschweigend mitverkauft.', 'Vier Bereiche: Arbeitsplätze und Netz, Server und Cluster, Software und Daten sowie KI-Abläufe. Was nicht dazu gehört, wird im Briefing benannt — nicht stillschweigend mitverkauft.',
], ],

View File

@@ -5,17 +5,17 @@ export const PITCH_DE: PitchPageCopy = {
routeId: 'pitch', routeId: 'pitch',
title: 'Profil | Antonio Ledebuhr', title: 'Profil | Antonio Ledebuhr',
description: description:
'Fullstack- und DevOps-Ingenieur in Tangermünde: rund sieben Jahre Webanwendungen, direkter Kundenkontakt und Teamverantwortung. Freelance seit 04/2023.', 'Fullstack- und DevOps-Ingenieur in Tangermünde: rund sieben Jahre Webanwendungen, direkter Kundenkontakt und Teamverantwortung. Freiberuflich seit 04/2023.',
hero: { hero: {
headline: 'Fullstack- und DevOps-Ingenieur in Tangermünde', headline: 'Fullstack- und DevOps-Ingenieur in Tangermünde',
proof: proof:
'Rund sieben Jahre berufliche Erfahrung mit dem Bau und Betrieb von Webanwendungen. Freelance seit 04/2023.', 'Rund sieben Jahre berufliche Erfahrung mit dem Bau und Betrieb von Webanwendungen. Freiberuflich seit 04/2023.',
playfulLine: 'IT mit Drehmoment', playfulLine: 'IT mit Drehmoment',
}, },
profile: [ profile: [
'Rund sieben Jahre berufliche Erfahrung mit dem Bau und Betrieb von Webanwendungen.', 'Rund sieben Jahre berufliche Erfahrung mit dem Bau und Betrieb von Webanwendungen.',
'Fullstack-Entwicklung, DevOps, direkter Kundenkontakt vom ersten Anforderungsworkshop bis in den Produktivbetrieb sowie Personal- und Teamverantwortung.', 'Fullstack-Entwicklung, DevOps, direkter Kundenkontakt vom ersten Anforderungsworkshop bis in den Produktivbetrieb sowie Personal- und Teamverantwortung.',
'Freelance seit 04/2023, mit Sitz in Tangermünde.', 'Freiberuflich seit 04/2023, mit Sitz in Tangermünde.',
'Heimspiel Java mit Spring; dazu C# und .NET, Angular, SQL, Docker und Kubernetes, Azure einschließlich AKS sowie GitLab CI/CD und Azure DevOps.', 'Heimspiel Java mit Spring; dazu C# und .NET, Angular, SQL, Docker und Kubernetes, Azure einschließlich AKS sowie GitLab CI/CD und Azure DevOps.',
], ],
metrics: [ metrics: [
@@ -43,38 +43,38 @@ export const PITCH_DE: PitchPageCopy = {
{ {
id: 'self-employed', id: 'self-employed',
period: 'seit 12/2021', period: 'seit 12/2021',
role: 'unternehmerisch selbständig seit 12/2021', role: 'unternehmerisch selbständig',
body: 'Eigene Verantwortung für Auftrag, Technik und Betrieb — ohne die früheren Angestelltenverhältnisse auf dieser Seite zu listen.', body: 'Eigene Verantwortung für Auftrag, Technik und Betrieb; eigene Rechnungsstellung und Kundenbeziehungen.',
}, },
{ {
id: 'freelance', id: 'freelance',
period: 'seit 04/2023', period: 'seit 04/2023',
role: 'freiberuflich seit 04/2023', role: 'freiberuflich',
body: 'Freiberufliche Fullstack- und DevOps-Arbeit mit direktem Kundenkontakt, vom Anforderungsworkshop bis in den Produktivbetrieb.', body: 'Freiberufliche Fullstack- und DevOps-Arbeit mit direktem Kundenkontakt, vom Anforderungsworkshop bis in den Produktivbetrieb.',
}, },
{ {
id: 'hdi', id: 'hdi',
period: '05/2023 01/2024', period: '05/2023 01/2024',
role: 'Senior Fullstack / DevOps bei HDI Specialty', role: 'Senior Fullstack / DevOps bei HDI Specialty',
body: 'Exposure-Management-Software und die Migration der Umgebungen von Azure App Services auf Azure AKS.', body: 'Fullstack- und DevOps-Verantwortung in einem regulierten Versicherungsumfeld.',
}, },
{ {
id: 'roesterei', id: 'roesterei',
period: 'seit 10/2023', period: 'seit 10/2023',
role: 'Gesamtverantwortung für die Technik der Rösterei Tangermünde', role: 'Gesamtverantwortung für die Technik der Rösterei Tangermünde',
body: 'Netz, Arbeitsplätze, Shop und zwei interne KI-Werkzeuge aus einer Hand. Antonio Ledebuhr hält eine wirtschaftliche Beteiligung an der Rösterei.', body: 'Ein Ansprechpartner für die gesamte Betriebstechnik; die wirtschaftliche Beteiligung bleibt offengelegt.',
}, },
{ {
id: 'myspa', id: 'myspa',
period: '03/2024 09/2024', period: '03/2024 09/2024',
role: 'Lead Backend / DevOps bei Aracom IT Services / MySpa', role: 'Lead Backend / DevOps bei Aracom IT Services / MySpa',
body: 'Leitung des Backend-Teams (4) und des DevOps-Teams (2) bis zum Start der Software, mit direktem Kundenkontakt.', body: 'Führung von Backend und DevOps bis zum Softwarestart, Anforderungen direkt vom Kunden.',
}, },
{ {
id: 'innofocus', id: 'innofocus',
period: 'seit 09/2025', period: 'seit 09/2025',
role: 'Senior Backend- und Datenbankingenieur bei Innofocus / reifen.com', role: 'Senior Backend- und Datenbankingenieur bei Innofocus / reifen.com',
body: 'Alleinverantwortung für die ERP-Datenmigration. Laufzeit von rund acht Stunden auf etwa 90 Minuten.', body: 'Alleinverantwortung für die Migration, als einziger Freiberufler im direkten Kontakt mit dem Endkunden.',
}, },
], ],
stackHeading: 'Kernstack', stackHeading: 'Kernstack',
@@ -88,13 +88,13 @@ export const PITCH_DE: PitchPageCopy = {
{ {
id: 'angular', id: 'angular',
title: 'Angular und TypeScript', title: 'Angular und TypeScript',
body: 'Einzelanwendungen, RxJS-zeitige SPA-Arbeit und SCSS.', body: 'Angular-SPAs, RxJS und SCSS.',
}, },
{ id: 'sql', title: 'SQL', body: 'Microsoft SQL Server, T-SQL, MySQL und MariaDB.' }, { id: 'sql', title: 'SQL', body: 'Microsoft SQL Server, T-SQL, MySQL und MariaDB.' },
{ {
id: 'containers', id: 'containers',
title: 'Docker und Kubernetes', title: 'Docker und Kubernetes',
body: 'Container und Cluster on-premise und in der Cloud.', body: 'Container und Cluster vor Ort und in der Cloud.',
}, },
{ {
id: 'azure', id: 'azure',
@@ -113,14 +113,14 @@ export const PITCH_DE: PitchPageCopy = {
id: 'profile', id: 'profile',
headline: 'In dreißig Sekunden', headline: 'In dreißig Sekunden',
body: [ body: [
'Antonio Ledebuhr arbeitet als Fullstack- und DevOps-Ingenieur aus Tangermünde. Diese Seite zeigt die öffentliche Auswahl von Stationen; der vollständige Lebenslauf steht als PDF bereit.', 'Antonio Ledebuhr arbeitet als Fullstack- und DevOps-Ingenieur aus Tangermünde. Der Lebenslauf als PDF führt die Stationen vollständig.',
], ],
}, },
{ {
id: 'featured-cases', id: 'featured-cases',
headline: 'Ausgewählte Fälle', headline: 'Ausgewählte Fälle',
body: [ body: [
'Die vier öffentlichen Fälle decken eCommerce und ERP, Laden-IT, IoT und Versicherung ab. Jeder Fall ist auf der Projektseite vollständig beschrieben.', 'Vier Fälle decken eCommerce und ERP, Laden-IT, IoT und Versicherung ab. Jeder Fall ist auf der Projektseite vollständig beschrieben.',
], ],
}, },
], ],

View File

@@ -4,7 +4,7 @@ export const HOME_EN: HomePageCopy = {
routeId: 'home', routeId: 'home',
title: 'Home | Antonio Ledebuhr', title: 'Home | Antonio Ledebuhr',
description: description:
'You describe what the business needs to achieve. One technical counterpart owns the path from diagnosis through delivery to operations or handover.', 'You describe what the business needs to achieve. One technical contact takes the path from diagnosis through delivery to operations or handover.',
hero: { hero: {
headline: headline:
'You describe what the business needs to achieve. I take the technical path from there.', 'You describe what the business needs to achieve. I take the technical path from there.',
@@ -12,21 +12,21 @@ export const HOME_EN: HomePageCopy = {
'At Rösterei Tangermünde the public work runs from the network and workplaces through to the shop and two in-house AI tools.', 'At Rösterei Tangermünde the public work runs from the network and workplaces through to the shop and two in-house AI tools.',
playfulLine: 'Full-stack, full throttle', playfulLine: 'Full-stack, full throttle',
body: [ body: [
'You put the outcome, the bottleneck or the recurring process in your own words. One counterpart then owns diagnosis, implementation and operations or handover.', 'You put the outcome, the bottleneck or the recurring process in your own words. One person then handles diagnosis, implementation and operations or handover.',
], ],
}, },
serviceAreasHeading: 'Where this work fits', serviceAreasHeading: 'What I can help with',
serviceAreas: [ serviceAreas: [
{ {
id: 'workplaces', id: 'workplaces',
title: 'Workplaces and network', title: 'Workplaces and network',
body: 'Devices, the network and the services your team uses every day — cut so that Tuesday still works.', body: 'Devices, the network and the everyday services your team uses stay reliable.',
routeId: 'servicesHardwareNetwork', routeId: 'servicesHardwareNetwork',
}, },
{ {
id: 'servers', id: 'servers',
title: 'Servers and clusters', title: 'Servers and clusters',
body: 'A single host, virtualisation or a cluster. The path there stays readable, on-premise or on Azure AKS.', body: 'A single host, virtualisation or a cluster. The path there stays clear, on-premise or on Azure AKS.',
routeId: 'servicesClusters', routeId: 'servicesClusters',
}, },
{ {
@@ -38,7 +38,7 @@ export const HOME_EN: HomePageCopy = {
{ {
id: 'ai', id: 'ai',
title: 'AI workflows', title: 'AI workflows',
body: 'Two delivered tools at Rösterei Tangermünde. Further building blocks — local models, retrieval, a person in the loop — are scoped per engagement.', body: 'Two delivered tools at Rösterei Tangermünde. Further building blocks — local models, search over your own documents, review by a person — are agreed for each assignment.',
routeId: 'servicesAi', routeId: 'servicesAi',
}, },
], ],
@@ -57,12 +57,12 @@ export const HOME_EN: HomePageCopy = {
{ {
id: 'implement', id: 'implement',
title: 'Implementation', title: 'Implementation',
body: 'One counterpart delivers: software, infrastructure, a cluster or a narrow AI tool, according to the brief.', body: 'One person delivers: software, infrastructure, a cluster or a clearly defined AI tool, according to the brief.',
}, },
{ {
id: 'operate', id: 'operate',
title: 'Operations or handover', title: 'Operations or handover',
body: 'The result stays operable. Handover means readable structures, not an undocumented snapshot.', body: 'The result stays operable. Handover means structures you can follow, not an undocumented snapshot.',
}, },
], ],
proofCaseId: 'roesterei', proofCaseId: 'roesterei',
@@ -72,7 +72,7 @@ export const HOME_EN: HomePageCopy = {
sections: [ sections: [
{ {
id: 'scope', id: 'scope',
headline: 'What this page covers', headline: 'Four areas of work',
body: [ body: [
'Four areas: workplaces and network, servers and clusters, software and data, and AI workflows. What sits outside that set is named in the briefing — it is not sold by implication.', 'Four areas: workplaces and network, servers and clusters, software and data, and AI workflows. What sits outside that set is named in the briefing — it is not sold by implication.',
], ],

View File

@@ -14,9 +14,9 @@ export const PITCH_EN: PitchPageCopy = {
}, },
profile: [ profile: [
'About seven years of professional experience building and operating web applications.', 'About seven years of professional experience building and operating web applications.',
'Fullstack development, DevOps, direct customer contact from the first requirements workshop through to production, and personnel and team responsibility.', 'Fullstack development, DevOps, direct customer contact from the first requirements workshop through to production, and line management and team leadership.',
'Freelance since 04/2023, based in Tangermünde.', 'Freelance since 04/2023, based in Tangermünde.',
'Home ground is Java with Spring; also C# and .NET, Angular, SQL, Docker and Kubernetes, Azure including AKS, plus GitLab CI/CD and Azure DevOps.', 'Java with Spring is the home stack; also C# and .NET, Angular, SQL, Docker and Kubernetes, Azure including AKS, plus GitLab CI/CD and Azure DevOps.',
], ],
metrics: [ metrics: [
{ {
@@ -43,38 +43,38 @@ export const PITCH_EN: PitchPageCopy = {
{ {
id: 'self-employed', id: 'self-employed',
period: 'since 12/2021', period: 'since 12/2021',
role: 'entrepreneurially self-employed since 12/2021', role: 'entrepreneurially self-employed',
body: 'Own responsibility for the brief, the technology and operations — earlier employment stations are not listed on this site.', body: 'Own responsibility for the brief, the technology and operations; own invoicing and client relationships.',
}, },
{ {
id: 'freelance', id: 'freelance',
period: 'since 04/2023', period: 'since 04/2023',
role: 'freelance since 04/2023', role: 'freelance',
body: 'Freelance fullstack and DevOps work with direct customer contact, from the requirements workshop through to production.', body: 'Freelance fullstack and DevOps work with direct customer contact, from the requirements workshop through to production.',
}, },
{ {
id: 'hdi', id: 'hdi',
period: '05/2023 01/2024', period: '05/2023 01/2024',
role: 'Senior fullstack / DevOps at HDI Specialty', role: 'Senior fullstack / DevOps at HDI Specialty',
body: 'Exposure-management software and the move of the environments from Azure App Services onto Azure AKS.', body: 'Fullstack and DevOps ownership in a regulated insurance setting.',
}, },
{ {
id: 'roesterei', id: 'roesterei',
period: 'since 10/2023', period: 'since 10/2023',
role: 'Full technical responsibility at Rösterei Tangermünde', role: 'Full technical responsibility at Rösterei Tangermünde',
body: 'Network, workplaces, shop and two in-house AI tools from one counterpart. Antonio Ledebuhr holds an economic stake in the roastery.', body: 'One contact for the companys technology as a whole; the economic stake stays disclosed.',
}, },
{ {
id: 'myspa', id: 'myspa',
period: '03/2024 09/2024', period: '03/2024 09/2024',
role: 'Lead backend / DevOps at Aracom IT Services / MySpa', role: 'Lead backend / DevOps at Aracom IT Services / MySpa',
body: 'Led the backend team (4) and the DevOps team (2) through the software launch, with direct customer contact.', body: 'Led backend and DevOps through go-live, taking requirements directly from the customer.',
}, },
{ {
id: 'innofocus', id: 'innofocus',
period: 'since 09/2025', period: 'since 09/2025',
role: 'Senior backend and database engineer at Innofocus / reifen.com', role: 'Senior backend and database engineer at Innofocus / reifen.com',
body: 'Sole responsibility for the ERP data migration. Run time from about eight hours down to about 90 minutes.', body: 'Sole ownership of the migration, as the only freelancer in direct contact with the end customer.',
}, },
], ],
stackHeading: 'Core stack', stackHeading: 'Core stack',
@@ -82,13 +82,13 @@ export const PITCH_EN: PitchPageCopy = {
{ {
id: 'java', id: 'java',
title: 'Java and Spring', title: 'Java and Spring',
body: 'Home ground: Java with Spring Boot, Spring Data and tests.', body: 'Home stack: Java with Spring Boot, Spring Data and tests.',
}, },
{ id: 'dotnet', title: 'C# and .NET', body: 'ASP.NET Core, Entity Framework and xUnit.' }, { id: 'dotnet', title: 'C# and .NET', body: 'ASP.NET Core, Entity Framework and xUnit.' },
{ {
id: 'angular', id: 'angular',
title: 'Angular and TypeScript', title: 'Angular and TypeScript',
body: 'Single-page apps, RxJS-era SPA work and SCSS.', body: 'Angular SPAs with RxJS and SCSS.',
}, },
{ id: 'sql', title: 'SQL', body: 'Microsoft SQL Server, T-SQL, MySQL and MariaDB.' }, { id: 'sql', title: 'SQL', body: 'Microsoft SQL Server, T-SQL, MySQL and MariaDB.' },
{ {
@@ -113,14 +113,14 @@ export const PITCH_EN: PitchPageCopy = {
id: 'profile', id: 'profile',
headline: 'Thirty seconds', headline: 'Thirty seconds',
body: [ body: [
'Antonio Ledebuhr works as a fullstack and DevOps engineer from Tangermünde. This page shows the public selection of stations; the full curriculum vitae is available as a PDF.', 'Antonio Ledebuhr works as a fullstack and DevOps engineer from Tangermünde. The CV PDF carries the full record.',
], ],
}, },
{ {
id: 'featured-cases', id: 'featured-cases',
headline: 'Selected cases', headline: 'Selected cases',
body: [ body: [
'The four public cases cover eCommerce and ERP, shop-floor IT, IoT and insurance. Each case is written in full on the projects page.', 'Four cases cover eCommerce and ERP, shop IT, IoT and insurance. Each case is written in full on the projects page.',
], ],
}, },
], ],