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:
@@ -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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -20,13 +20,13 @@ export const HOME_DE: HomePageCopy = {
|
||||
{
|
||||
id: 'workplaces',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'servers',
|
||||
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',
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@ export const HOME_DE: HomePageCopy = {
|
||||
{
|
||||
id: 'ai',
|
||||
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',
|
||||
},
|
||||
],
|
||||
@@ -57,7 +57,7 @@ export const HOME_DE: HomePageCopy = {
|
||||
{
|
||||
id: 'implement',
|
||||
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',
|
||||
@@ -72,7 +72,7 @@ export const HOME_DE: HomePageCopy = {
|
||||
sections: [
|
||||
{
|
||||
id: 'scope',
|
||||
headline: 'Was diese Seite abdeckt',
|
||||
headline: 'Vier Arbeitsbereiche',
|
||||
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.',
|
||||
],
|
||||
|
||||
@@ -5,17 +5,17 @@ export const PITCH_DE: PitchPageCopy = {
|
||||
routeId: 'pitch',
|
||||
title: 'Profil | Antonio Ledebuhr',
|
||||
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: {
|
||||
headline: 'Fullstack- und DevOps-Ingenieur in Tangermünde',
|
||||
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',
|
||||
},
|
||||
profile: [
|
||||
'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.',
|
||||
'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.',
|
||||
],
|
||||
metrics: [
|
||||
@@ -43,38 +43,38 @@ export const PITCH_DE: PitchPageCopy = {
|
||||
{
|
||||
id: 'self-employed',
|
||||
period: 'seit 12/2021',
|
||||
role: 'unternehmerisch selbständig seit 12/2021',
|
||||
body: 'Eigene Verantwortung für Auftrag, Technik und Betrieb — ohne die früheren Angestelltenverhältnisse auf dieser Seite zu listen.',
|
||||
role: 'unternehmerisch selbständig',
|
||||
body: 'Eigene Verantwortung für Auftrag, Technik und Betrieb; eigene Rechnungsstellung und Kundenbeziehungen.',
|
||||
},
|
||||
{
|
||||
id: 'freelance',
|
||||
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.',
|
||||
},
|
||||
{
|
||||
id: 'hdi',
|
||||
period: '05/2023 – 01/2024',
|
||||
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',
|
||||
period: 'seit 10/2023',
|
||||
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',
|
||||
period: '03/2024 – 09/2024',
|
||||
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',
|
||||
period: 'seit 09/2025',
|
||||
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',
|
||||
@@ -88,13 +88,13 @@ export const PITCH_DE: PitchPageCopy = {
|
||||
{
|
||||
id: 'angular',
|
||||
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: 'containers',
|
||||
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',
|
||||
@@ -113,14 +113,14 @@ export const PITCH_DE: PitchPageCopy = {
|
||||
id: 'profile',
|
||||
headline: 'In dreißig Sekunden',
|
||||
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',
|
||||
headline: 'Ausgewählte Fälle',
|
||||
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.',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -4,7 +4,7 @@ export const HOME_EN: HomePageCopy = {
|
||||
routeId: 'home',
|
||||
title: 'Home | Antonio Ledebuhr',
|
||||
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: {
|
||||
headline:
|
||||
'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.',
|
||||
playfulLine: 'Full-stack, full throttle',
|
||||
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: [
|
||||
{
|
||||
id: 'workplaces',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'servers',
|
||||
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',
|
||||
},
|
||||
{
|
||||
@@ -38,7 +38,7 @@ export const HOME_EN: HomePageCopy = {
|
||||
{
|
||||
id: 'ai',
|
||||
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',
|
||||
},
|
||||
],
|
||||
@@ -57,12 +57,12 @@ export const HOME_EN: HomePageCopy = {
|
||||
{
|
||||
id: 'implement',
|
||||
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',
|
||||
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',
|
||||
@@ -72,7 +72,7 @@ export const HOME_EN: HomePageCopy = {
|
||||
sections: [
|
||||
{
|
||||
id: 'scope',
|
||||
headline: 'What this page covers',
|
||||
headline: 'Four areas of work',
|
||||
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.',
|
||||
],
|
||||
|
||||
@@ -14,9 +14,9 @@ export const PITCH_EN: PitchPageCopy = {
|
||||
},
|
||||
profile: [
|
||||
'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.',
|
||||
'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: [
|
||||
{
|
||||
@@ -43,38 +43,38 @@ export const PITCH_EN: PitchPageCopy = {
|
||||
{
|
||||
id: 'self-employed',
|
||||
period: 'since 12/2021',
|
||||
role: 'entrepreneurially self-employed since 12/2021',
|
||||
body: 'Own responsibility for the brief, the technology and operations — earlier employment stations are not listed on this site.',
|
||||
role: 'entrepreneurially self-employed',
|
||||
body: 'Own responsibility for the brief, the technology and operations; own invoicing and client relationships.',
|
||||
},
|
||||
{
|
||||
id: 'freelance',
|
||||
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.',
|
||||
},
|
||||
{
|
||||
id: 'hdi',
|
||||
period: '05/2023 – 01/2024',
|
||||
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',
|
||||
period: 'since 10/2023',
|
||||
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 company’s technology as a whole; the economic stake stays disclosed.',
|
||||
},
|
||||
{
|
||||
id: 'myspa',
|
||||
period: '03/2024 – 09/2024',
|
||||
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',
|
||||
period: 'since 09/2025',
|
||||
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',
|
||||
@@ -82,13 +82,13 @@ export const PITCH_EN: PitchPageCopy = {
|
||||
{
|
||||
id: 'java',
|
||||
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: 'angular',
|
||||
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.' },
|
||||
{
|
||||
@@ -113,14 +113,14 @@ export const PITCH_EN: PitchPageCopy = {
|
||||
id: 'profile',
|
||||
headline: 'Thirty seconds',
|
||||
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',
|
||||
headline: 'Selected cases',
|
||||
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.',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user