Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/andrea-lisi-cv-it.pdf
Binary file not shown.
Binary file modified public/andrea-lisi-cv.pdf
Binary file not shown.
26 changes: 3 additions & 23 deletions public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/components/contact.astro
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Props = {
const { locale } = Astro.props;
const copy = getCopy(locale);
const head = copy.sections.contact;
const cvFile = locale === 'it' ? 'andrea-lisi-cv-it.pdf' : 'andrea-lisi-cv.pdf';
---
<section class="contact section" id="contact">
<SectionTitle num={head.num} title={head.title} />
Expand All @@ -22,7 +23,7 @@ const head = copy.sections.contact;
</div>

<div class="row">
<a class="cv" href="/andrea-lisi-cv.pdf" download="andrea-lisi-cv.pdf">
<a class="cv" href={`/${cvFile}`} download={cvFile}>
{copy.hero.buttons.cv}
</a>
<a
Expand Down
3 changes: 2 additions & 1 deletion src/components/hero.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type Props = {

const { locale } = Astro.props;
const { hero } = getCopy(locale);
const cvFile = locale === 'it' ? 'andrea-lisi-cv-it.pdf' : 'andrea-lisi-cv.pdf';

/* Hero content is above the fold, so it enters on load with a short stagger
rather than waiting for a scroll observer. */
Expand All @@ -32,7 +33,7 @@ const step = (i: number): string => `animation-delay:${(0.05 * i).toFixed(2)}s`;
</div>

<div class="actions enter" style={step(6)}>
<a class="cv" href="/andrea-lisi-cv.pdf" download="andrea-lisi-cv.pdf">{hero.buttons.cv}</a>
<a class="cv" href={`/${cvFile}`} download={cvFile}>{hero.buttons.cv}</a>
<a
class="social"
href="https://github.com/karedas"
Expand Down
3 changes: 0 additions & 3 deletions src/components/work.astro
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ const ICONS: Record<string, Parameters<typeof Icon>[0]['name']> = {
Web: 'box',
Backend: 'server',
Design: 'pen',
'Full-stack': 'stack',
Infrastructure: 'server',
Infrastruttura: 'server',
};
Expand Down Expand Up @@ -83,6 +82,4 @@ const ROOT_TAGS = new Set(['Design']);
</div>
</article>
))}

<p class="closing" data-reveal set:html={copy.workClosing} />
</section>
105 changes: 55 additions & 50 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const en: Copy = {
aiMeta: {
title: 'AI · Andrea Lisi · Frontend Platform & Governance',
description:
'How I use AI in engineering work: generated code follows the same review, testing and verification as code written by hand.',
'How I use AI assistants and agents in development: where they help, how I review the result and what checks I apply.',
},

skipLink: 'Skip to content',
Expand Down Expand Up @@ -45,14 +45,14 @@ export const en: Copy = {
{ label: 'FOUNDATION', value: 'Art school, Florence', tone: 'root' },
],
intro:
'I am a Senior Software Engineer with over 18 years of experience, focused on frontend platforms and the problems that appear when many teams work on the same codebase. I came to code through art and design, and I still care whether the structure makes sense at a glance.',
'I’m a Senior Software Engineer with over 18 years of experience. Today I work on the frontend platform behind Tosca Cloud, a monorepo containing 16 projects and shared by more than 12 teams. My focus is architecture, dependencies, builds and shared standards.',
buttons: { github: 'GITHUB', linkedin: 'LINKEDIN', email: 'EMAIL', cv: 'CV.PDF ↓' },
},

sections: {
approach: { num: '01', title: 'How I work' },
focus: { num: '02', title: 'What I work on' },
ai: { num: '03', title: 'AI', eyebrow: 'TOOLS, REVIEW AND VERIFICATION' },
ai: { num: '03', title: 'AI', eyebrow: 'USE, REVIEW AND TESTING' },
experience: { num: '04', title: 'Experience' },
projects: { num: '05', title: 'Personal projects' },
contact: { num: '06', title: 'Get in touch' },
Expand All @@ -62,18 +62,18 @@ export const en: Copy = {
{
label: 'Art_School',
tone: 'root',
title: 'I still look at code the way I looked at design',
body: '<b>I started in design</b>, then moved through frontend, full-stack work and infrastructure. That background probably explains why I care so much about structure. I like software that makes sense when you look at it, not only when you run it.',
title: 'From design to frontend engineering',
body: '<b>I started in design, but my career is in frontend engineering.</b> Over time I have also worked on backend systems and infrastructure. That experience helps me see what changes elsewhere in the system when I work on the frontend.',
},
{
label: 'The_Boundaries',
title: 'The rules should survive my absence',
body: '<b>A large part of my work sits between teams</b>: module boundaries, shared code, dependencies, build tooling and CI. I write down the reason for a rule, then turn it into a check when possible. The codebase should not depend on somebody remembering how things are supposed to work.',
title: 'Rules and automated checks',
body: '<b>I often work on problems that affect several teams</b>: module boundaries, dependencies, builds and CI. When a rule matters, I document the reason and add an automated check where I can. That lets the check do the reminding, so I do not have to repeat the same thing to dozens of people one at a time.',
},
{
label: 'Hands_On',
title: 'I stay close to the code',
body: '<b>I still spend a lot of time in implementation and debugging.</b> I work on shared tooling, investigate platform-wide breakage and automate decisions that would otherwise be repeated in reviews. When a problem belongs to another team, I document it, hand it over clearly and stay available without taking the work away from them.',
title: 'I work on the code and alongside the teams',
body: '<b>I continue to implement, debug and work on shared engineering tools.</b> Every day I work with developers across the teams, from junior to senior, and I regularly speak with their managers. When a decision affects several products, I also work with design, security and sales to understand what is needed and apply it consistently.',
},
],

Expand All @@ -84,39 +84,50 @@ export const en: Copy = {
'Monorepo architecture',
'Micro-frontends',
'Module boundaries',
'Dependency architecture',
'RFCs',
'Dependency governance',
'Technical RFCs',
],
},
{
title: 'Frontend',
items: ['React', 'TypeScript', 'Vue', 'GraphQL', 'Node.js'],
title: 'Frontend & integrations',
items: [
'React',
'TypeScript',
'Vue',
'GraphQL',
'Node.js',
'Frontend Okta integration',
'JWT handling',
'OpenTelemetry',
],
},
{
title: 'Tooling & delivery',
items: ['Nx', 'Vite', 'Webpack', 'CI/CD', 'Testing', 'Build performance', 'Quality gates'],
title: 'Build & delivery',
items: [
'CI architecture',
'Pipeline automation',
'Build caching & performance',
'Quality gates',
'Automated testing',
],
},
{
title: 'Developer experience',
items: [
'Shared tooling',
'Engineering standards',
'Developer experience',
'AI-assisted and agentic workflows',
],
items: ['Shared tooling', 'Engineering standards', 'Documentation', 'AI tooling evaluation'],
},
],

ai: {
heading: 'How I use AI in engineering work',
heading: 'How I use AI in development',
paragraphs: [
'AI-assisted and agentic development is part of my workflow, but generated code follows the same standard as any other code. If it cannot be reviewed, tested and verified, it does not go in.',
'I use AI assistants and agents to analyse a project’s code, prepare changes and reduce repetitive work. I use them only when I can understand what they did and check that it works.',
'I test them on real work to see where they lose context in the codebase. I use that to update the repository’s documentation, rules and tooling.',
],
rulesLead: 'Three rules keep that practical.',
rulesLead: 'In practice:',
rules: [
'<b>I only delegate what I can verify.</b> If I cannot review and understand the result, doing it faster is not useful.',
'<b>I check whether the change belongs before I check whether it works.</b> Agents will rebuild things that already exist and make the suggestion sound convincing. The first question is whether the new code should exist at all.',
'<b>The same gates apply to every contributor.</b> Human or generated, code has to respect the same module boundaries, tests and quality checks before it reaches main.',
'<b>First I check whether the change is needed.</b> An agent can suggest rebuilding something that already exists in the project.',
'<b>I review the result like any other contribution.</b> I read the diff, run the tests and check that it respects the project’s boundaries.',
'<b>I need to be able to explain and maintain every change.</b> If I cannot, I do not use it.',
],
backLabel: 'ANDREA LISI',
},
Expand All @@ -131,12 +142,11 @@ export const en: Copy = {
tags: ['Micro-frontends', '16 projects', '12+ teams', 'Quality gates'],
current: true,
paragraphs: [
'I work on the frontend platform behind Tosca Cloud, a micro-frontend monorepo shared across <b>16 projects and more than 12 teams</b>.',
'I own architectural and governance work across the monorepo, including module boundaries, dependency rules and shared frontend standards.',
'I work with the platform architect on build performance, CI topology and quality gates.',
'I handle platform-wide upgrades and shared integrations, <b>fixing breakage centrally before individual teams inherit it</b>.',
'I review RFCs and cross-team changes when they affect shared frontend boundaries.',
'I turn conventions into machine-checkable rules for both human and agent-generated code, and stay hands-on with implementation and debugging when issues affect the platform as a whole.',
'I work on the frontend platform behind Tosca Cloud, a micro-frontend monorepo containing <b>16 projects and shared by more than 12 teams</b>.',
'I work on the monorepo’s architecture and governance, particularly module boundaries, dependency rules and shared frontend standards. I also review RFCs that affect the shared frontend.',
'I administer the Tosca Cloud repository on GitHub and automate its pipelines, including on Azure. With the platform architect, I work on build caching and performance, CI structure and quality gates.',
'I implement and maintain integrations shared across multiple frontend applications. These include observability with OpenTelemetry and the application-side authentication flow after the Okta login, including JWT handling and HTTP interceptors. When an issue appears across several projects, I debug it at platform level.',
'I regularly evaluate AI tools, including Claude and Cursor, on real repository work. If they keep stumbling over the same parts of the codebase, I improve its documentation, rules or shared tooling.',
],
},
{
Expand All @@ -147,10 +157,10 @@ export const en: Copy = {
context: 'E-commerce platform for tree planting',
tags: ['React', 'Vue', 'GraphQL', 'Storefront migration'],
paragraphs: [
'Joined the frontend team and later led the frontend side of the storefront migration away from the monolith, working with React, Vue and GraphQL.',
'Rebuilt the storefront foundations as the company grew from around 20 to <b>more than 150 people</b>.',
'Built high-traffic campaign experiences for a platform that has planted millions of trees.',
'In my final year, built the frontend of the company’s internal back-office tools from scratch, working closely with the backend team and the people using those tools for forestry operations.',
'As part of the frontend team, I worked on moving the storefront out of the monolith using React, Vue and GraphQL.',
'I helped rebuild the storefront as the company grew from around 20 to <b>more than 150 people</b>.',
'I built interfaces for high-traffic campaigns. I worked regularly with the design and design system teams to integrate requests, match the mockups and follow the shared standards.',
'For my final two years, I built the frontend for the internal back-office tools from scratch. I was the project’s only frontend developer and worked alongside the backend team and the people who used those tools for forestry operations.',
],
},
{
Expand All @@ -161,25 +171,23 @@ export const en: Copy = {
context: 'Luxury e-commerce',
tags: ['ASP', 'jQuery', 'React', 'Webpack'],
paragraphs: [
'Modernized a live luxury e-commerce platform without a full rewrite, moving it from legacy ASP and jQuery to React with a Webpack-based frontend toolchain.',
'Kept shipping features while the migration was in progress and the production shop remained live.',
'Modernized a luxury e-commerce platform while it was in production. Gradually replaced ASP and jQuery with React and a new Webpack setup.',
'Continued to build new features during the migration without taking the shop offline.',
'Worked on both the storefront and the internal CMS used for orders and day-to-day shop operations.',
'Gradually replaced the legacy frontend while changing the architecture underneath it.',
],
},
{
years: '2007 · 2017',
place: 'FIGLINE VALDARNO, IT',
title: 'Head of Web · Full-Stack Designer',
title: 'Head of Web · Designer & Developer',
company: 'Easysystem',
context: 'Web agency and IT services',
tags: ['Design', 'Web', 'Backend', 'Infrastructure'],
paragraphs: [
'I joined Easysystem as a designer and gradually ended up doing almost every technical part of client work: web development, backend systems and eventually on-premise infrastructure.',
'I joined as a designer. Over the years I also worked on web development, backend systems and infrastructure installed at client sites.',
'Designed websites, interfaces, visual identities and print material from scratch for client projects.',
'Built and maintained both frontend and backend applications.',
'Installed servers, networks and firewalls on site for client companies, including manufacturers in Tuscany’s leather and fashion district.',
'Followed projects from the first design concepts through development and, in some cases, all the way down to the infrastructure they ran on.',
],
},
],
Expand All @@ -189,7 +197,7 @@ export const en: Copy = {
name: 'Lumina',
kind: 'FANTASY MUD',
description:
'A fantasy MUD I built end to end, from the Node.js/MongoDB backend to the React client and Cloudflare infrastructure.',
'A fantasy MUD I built myself: a Node.js/MongoDB backend, a React client and Cloudflare infrastructure.',
tags: ['Node.js', 'MongoDB', 'React', 'Cloudflare'],
},
{
Expand All @@ -202,19 +210,16 @@ export const en: Copy = {
},
],

workClosing:
'I started in design, moved through frontend, backend and infrastructure, and ended up working on the structure shared by many teams. The scale changed but the habit did not: <b>understand how the whole thing fits together, then fix the part that keeps making the same problem return</b>.',

footer: {
built: 'Written, designed and shipped by me.',
},

nowBadge: 'CURRENT',

contact: {
invite: 'Write any time, even just to talk.',
inviteMore:
'A new conversation has never once bothered me, and a proposal that makes me curious even less so.',
invite:
'Hey! If you want to talk about frontend platforms, developer experience or simply compare notes, send me a message.',
inviteMore: 'It doesn’t need to be formal. A quick message is fine too.',
cv: 'CV (PDF)',
github: 'GitHub',
linkedin: 'LinkedIn',
Expand Down
Loading
Loading