From 0e817f525717d027161d4eec52d0a9d46660bdd8 Mon Sep 17 00:00:00 2001 From: Andrea Lisi Date: Thu, 24 Sep 2026 15:10:19 +0200 Subject: [PATCH] content: clarify frontend platform and design systems specialization --- src/components/hero.astro | 1 + src/components/hero.css | 6 ++++++ src/components/work.astro | 1 + src/components/work.css | 7 +++++++ src/i18n/en.ts | 5 +++-- src/i18n/it.ts | 5 +++-- src/i18n/types.ts | 2 ++ tests/e2e/homepage.spec.ts | 24 ++++++++++++++++++++++-- 8 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/components/hero.astro b/src/components/hero.astro index 9497ad1..6b84e66 100644 --- a/src/components/hero.astro +++ b/src/components/hero.astro @@ -16,6 +16,7 @@ const cvFile = locale === 'it' ? 'andrea-lisi-cv-it.pdf' : 'andrea-lisi-cv.pdf';

{hero.greeting}

Andrea Lisi.

{hero.tagline}

+

{hero.eyebrow}

{hero.intro}

diff --git a/src/components/hero.css b/src/components/hero.css index ee6c9eb..19671cf 100644 --- a/src/components/hero.css +++ b/src/components/hero.css @@ -23,6 +23,12 @@ line-height: 1.3; color: var(--head); } +.hero .specialization { + margin: 8px 0 0; + font-size: 17px; + line-height: 1.5; + color: var(--body); +} .hero .intro { margin: 22px 0 0; font-size: 17px; diff --git a/src/components/work.astro b/src/components/work.astro index f4bcf76..0ec184c 100644 --- a/src/components/work.astro +++ b/src/components/work.astro @@ -61,6 +61,7 @@ const ROOT_TAGS = new Set(['Design']); )} {job.years}
+ {job.specialization &&

{job.specialization}

}

{job.context} · {job.place}

diff --git a/src/components/work.css b/src/components/work.css index b9d7369..15b29c5 100644 --- a/src/components/work.css +++ b/src/components/work.css @@ -77,6 +77,13 @@ } } +.work .job-specialization { + margin: 7px 0 0; + font-size: 16px; + line-height: 1.5; + color: var(--body); +} + .work .meta { margin: 5px 0 16px; font-family: var(--font-mono); diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 85dc836..c6e34d7 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -36,7 +36,7 @@ export const en: Copy = { hero: { greeting: 'Ciao. My name is', tagline: 'Senior Software Engineer.', - eyebrow: 'Frontend engineering, architecture and developer tools', + eyebrow: 'Frontend platforms, developer tooling & design systems', stats: [ { label: 'Based in', value: 'Vienna, Austria' }, { label: 'Working', value: 'Remote or hybrid', tone: 'now' }, @@ -163,8 +163,9 @@ export const en: Copy = { place: 'VIENNA, AT', title: 'Senior Software Engineer', company: 'Tricentis', + specialization: 'Frontend Platform, Governance & Design Systems', context: 'Work on Tosca Cloud', - tags: ['Micro-frontends', '16 projects', '12+ teams', 'Quality gates'], + tags: ['React', 'TypeScript', 'Micro-frontends', '16 projects', '12+ teams', 'Quality gates'], current: true, paragraphs: [ 'Cross-team decisions. On Tosca Cloud, together with the team’s architect, I was a point of contact for initiatives spanning the monorepo. I worked with developers, engineering managers, principal engineers from other platforms and product stakeholders to define shared solutions.', diff --git a/src/i18n/it.ts b/src/i18n/it.ts index f05d74c..30394c7 100644 --- a/src/i18n/it.ts +++ b/src/i18n/it.ts @@ -37,7 +37,7 @@ export const it: Copy = { hero: { greeting: 'Ciao. Mi chiamo', tagline: 'Senior Software Engineer.', - eyebrow: 'Sviluppo frontend, architettura e strumenti per sviluppatori', + eyebrow: 'Piattaforme frontend, strumenti per sviluppatori e design system', stats: [ { label: 'Dove vivo', value: 'Vienna, Austria' }, { label: 'Come lavoro', value: 'Remoto o ibrido', tone: 'now' }, @@ -171,8 +171,9 @@ export const it: Copy = { place: 'VIENNA, AT', title: 'Senior Software Engineer', company: 'Tricentis', + specialization: 'Piattaforma frontend, governance e design system', context: 'Esperienza su Tosca Cloud', - tags: ['Microfrontend', '16 progetti', '12+ team', 'Quality gates'], + tags: ['React', 'TypeScript', 'Microfrontend', '16 progetti', '12+ team', 'Quality gates'], current: true, paragraphs: [ 'Decisioni tra team. Su Tosca Cloud, insieme all’architetto del team, sono stato un riferimento per le iniziative dell’intera monorepo. Ho lavorato con sviluppatori, engineering manager, principal engineer di altre piattaforme e referenti di prodotto per definire le soluzioni condivise.', diff --git a/src/i18n/types.ts b/src/i18n/types.ts index 5e31601..1132602 100644 --- a/src/i18n/types.ts +++ b/src/i18n/types.ts @@ -60,6 +60,8 @@ export type WorkEntry = { years: string; place: string; company: string; + /** Scope of the experience, separate from the official job title. */ + specialization?: string; /** * What the place was, on the line under the title. Never the job title again: * three of these repeated it word for word, which the phone layout made diff --git a/tests/e2e/homepage.spec.ts b/tests/e2e/homepage.spec.ts index bcdc529..62be37f 100644 --- a/tests/e2e/homepage.spec.ts +++ b/tests/e2e/homepage.spec.ts @@ -58,13 +58,15 @@ for (const locale of ['en', 'it'] as const) { expect((description as string).length).toBeLessThan(155); }); - test('opens with the greeting, the name and the tagline', async ({ page }) => { + test('opens with the greeting, the name and the tagline', async ({ page }, testInfo) => { await page.goto(home); await expect(page.getByText(copy.hero.greeting)).toBeVisible(); await expect(page.getByRole('heading', { level: 1 })).toHaveText('Andrea Lisi.'); await expect(page.getByText(copy.hero.tagline)).toBeVisible(); + await expect(page.locator('.hero .specialization')).toHaveText(copy.hero.eyebrow); await expect(page.getByText(copy.hero.intro)).toBeVisible(); + await page.locator('.hero').screenshot({ path: testInfo.outputPath('hero-desktop.png') }); }); test('shows the portrait, served as WebP with a JPEG fallback', async ({ page }) => { @@ -226,6 +228,19 @@ for (const locale of ['en', 'it'] as const) { await expect(page.locator('.work .job-title').first()).toContainText( 'Senior Software Engineer', ); + await expect(page.locator('.work .job-specialization')).toHaveCount(1); + await expect(page.locator('.work .job-specialization')).toHaveText( + copy.work[0]?.specialization ?? '', + ); + await expect(page.locator('.work .job').first().locator('.meta')).toContainText( + 'Tosca Cloud', + ); + for (const tag of ['React', 'TypeScript']) { + await expect( + page.locator('.work .job').first().locator('.chip').filter({ hasText: tag }), + ).toBeVisible(); + await expect(page.locator('.work .job-title').first()).not.toContainText(tag); + } await expect(page.locator('#examples')).toHaveCount(0); await expect( page @@ -298,7 +313,7 @@ for (const locale of ['en', 'it'] as const) { await context.close(); }); - test('holds together at phone width', async ({ page }) => { + test('holds together at phone width', async ({ page }, testInfo) => { await page.setViewportSize({ width: 375, height: 812 }); await page.goto(home); @@ -310,6 +325,11 @@ for (const locale of ['en', 'it'] as const) { const cv = await page.locator('.hero .cv').boundingBox(); expect(cv).not.toBeNull(); expect((cv?.y ?? 1000) + (cv?.height ?? 0)).toBeLessThanOrEqual(812); + await page.locator('.hero').screenshot({ path: testInfo.outputPath('hero-mobile.png') }); + await page + .locator('.work .job') + .first() + .screenshot({ path: testInfo.outputPath('tricentis-mobile.png') }); }); test('passes axe accessibility checks (no critical/serious violations)', async ({ page }) => {