[{"data":1,"prerenderedAt":246},["ShallowReactive",2],{"works":3},[4,55,83,111,138,169,207],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"order":11,"subtitle":12,"type":13,"company":14,"period":15,"url":8,"tags":16,"metrics":22,"body":26,"_type":49,"_id":50,"_source":51,"_file":52,"_stem":53,"_extension":54},"\u002Fwork\u002F01-catalog-platform","work",false,"","Catalog Platform","The Catalog squad's job is to give Everli's operational teams a way to manage 230,000 products across 2,000+ integrated European stores — prices, promotions, attributes, images, taxonomy — without breaking things for the warehouses and storefront that depended on the same data.",1,"Product data infrastructure for European grocery delivery","professional","Everli","2019 – present",[17,18,19,20,21],"Vue 3","Nuxt 3","TypeScript","Pinia","Jest",[23,24,25],"230k live SKUs","2,000+ stores","12-engineer team",{"type":27,"children":28,"toc":46},"root",[29,36,41],{"type":30,"tag":31,"props":32,"children":33},"element","p",{},[34],{"type":35,"value":10},"text",{"type":30,"tag":31,"props":37,"children":38},{},[39],{"type":35,"value":40},"I joined when the product was a thin admin layer over a database. The most consequential work wasn't the features — it was the cross-component architecture documents I wrote before building them: what data flows where, where ownership boundaries sit, what adjacent squads need to know. Those documents became the reference material for the entire Retail component and the basis for conversations with the CTO and VP Engineering on decisions with company-wide impact.",{"type":30,"tag":31,"props":42,"children":43},{},[44],{"type":35,"value":45},"The squad scaled from three to twelve engineers while I led it. I built the CI\u002FCD migration from Jenkins to GitHub Actions that cut build times from twenty minutes to under seven, and established the testing culture that took coverage from near zero to over seventy percent on a 4,000+ test suite.",{"title":8,"searchDepth":47,"depth":47,"links":48},2,[],"markdown","content:work:01-catalog-platform.md","content","work\u002F01-catalog-platform.md","work\u002F01-catalog-platform","md",{"_path":56,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":57,"description":58,"order":47,"subtitle":59,"type":13,"company":60,"period":61,"url":8,"tags":62,"metrics":66,"body":67,"_type":49,"_id":80,"_source":51,"_file":81,"_stem":82,"_extension":54},"\u002Fwork\u002F02-formula-e-telemetry","Formula E Telemetry Dashboard","During race weekends, Formula E trackside engineers need to read live telemetry from the cars — motor temperature, energy deployment, lap delta — and make decisions in seconds. The existing tools were either too slow or too generic for the team's specific needs.","Trackside race data visualisation for a Formula E team","Abinsula","2015 – 2018",[63,64,65],"React","WebSocket","Real-time",[],{"type":27,"children":68,"toc":78},[69,73],{"type":30,"tag":31,"props":70,"children":71},{},[72],{"type":35,"value":58},{"type":30,"tag":31,"props":74,"children":75},{},[76],{"type":35,"value":77},"I was the primary frontend consultant on a bespoke dashboard built for their trackside operations. It streamed live race data to engineers at the pit wall during actual championship events. The constraint that shaped every design decision was latency: the display had to be fast enough that what you were looking at was still true when you acted on it.",{"title":8,"searchDepth":47,"depth":47,"links":79},[],"content:work:02-formula-e-telemetry.md","work\u002F02-formula-e-telemetry.md","work\u002F02-formula-e-telemetry",{"_path":84,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":85,"description":86,"order":87,"subtitle":88,"type":13,"company":60,"period":61,"url":8,"tags":89,"metrics":93,"body":95,"_type":49,"_id":108,"_source":51,"_file":109,"_stem":110,"_extension":54},"\u002Fwork\u002F03-medical-sample-acceptance","Medical Sample Acceptance System","Anatomical pathology labs have a pre-analytical error rate around 65% — meaning the majority of problems that affect test results happen before the sample reaches the lab. Most are administrative: wrong label, wrong container, wrong patient. By the time the error is caught, the sample may be compromised and the patient needs to come back.",3,"Pre-analytical error reduction for Anatomical Pathology labs",[90,91,92],"Angular.js","MQTT","Hardware integration",[94],"65% pre-analytical error rate targeted",{"type":27,"children":96,"toc":106},[97,101],{"type":30,"tag":31,"props":98,"children":99},{},[100],{"type":35,"value":86},{"type":30,"tag":31,"props":102,"children":103},{},[104],{"type":35,"value":105},"I built a web-based acceptance system that integrates directly with barcode scanners and label printers via MQTT. When a sample arrives, the system validates it against the request, flags discrepancies immediately, and prints corrected labels on the spot. The goal was to catch errors at the point of reception, before they could propagate further into the workflow. Connecting a web application to physical lab equipment through a message broker was the interesting engineering problem; getting the validation logic right was the important one.",{"title":8,"searchDepth":47,"depth":47,"links":107},[],"content:work:03-medical-sample-acceptance.md","work\u002F03-medical-sample-acceptance.md","work\u002F03-medical-sample-acceptance",{"_path":112,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":113,"description":114,"order":115,"subtitle":116,"type":13,"company":60,"period":61,"url":8,"tags":117,"metrics":120,"body":122,"_type":49,"_id":135,"_source":51,"_file":136,"_stem":137,"_extension":54},"\u002Fwork\u002F04-snai","SNAI Betting Platform","SNAI is Italy's largest online betting operator. Their in-play interface needed to display live odds across thousands of simultaneous daily matches — prices updating continuously as events unfolded, markets opening and closing, results flowing in from dozens of concurrent events.",4,"Real-time in-play and pre-match betting interface",[118,65,119],"JavaScript","CMS",[121],"7,000+ daily quoted matches",{"type":27,"children":123,"toc":133},[124,128],{"type":30,"tag":31,"props":125,"children":126},{},[127],{"type":35,"value":114},{"type":30,"tag":31,"props":129,"children":130},{},[131],{"type":35,"value":132},"I built two things: the custom CMS that operators used to configure and manage betting markets, and the public-facing real-time interface that users actually bet on. The constraint that connected both was latency — odds displayed to users had to be current enough that they were still valid when someone clicked. A number that's already moved by the time you act on it is worse than no number at all.",{"title":8,"searchDepth":47,"depth":47,"links":134},[],"content:work:04-snai.md","work\u002F04-snai.md","work\u002F04-snai",{"_path":139,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":140,"description":141,"order":142,"subtitle":143,"type":13,"company":144,"period":145,"url":8,"tags":146,"metrics":150,"body":153,"_type":49,"_id":166,"_source":51,"_file":167,"_stem":168,"_extension":54},"\u002Fwork\u002F05-ofootball","oFootball","oFootball was a fantasy football platform with 100,000 monthly active users at its peak. A football weekend generates thousands of events across hundreds of simultaneous matches — goals, assists, cards, substitutions — each of which needs to be processed, scored, and reflected in users' fantasy leagues in something close to real time.",5,"Fantasy football platform for the Italian market","Bangbite","2013 – 2015",[147,148,65,149],"Vue 2","Node.js","Gaming",[151,152],"100k monthly active users","−95% match processing time",{"type":27,"children":154,"toc":164},[155,159],{"type":30,"tag":31,"props":156,"children":157},{},[158],{"type":35,"value":141},{"type":30,"tag":31,"props":160,"children":161},{},[162],{"type":35,"value":163},"When I joined, the processing pipeline was batch-based and lagged by hours. Users spent Sunday afternoons refreshing a page that hadn't updated yet and emailing support to ask why. I rebuilt the pipeline and reduced processing time by 95%. The support emails stopped.",{"title":8,"searchDepth":47,"depth":47,"links":165},[],"content:work:05-ofootball.md","work\u002F05-ofootball.md","work\u002F05-ofootball",{"_path":170,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":171,"description":172,"order":173,"subtitle":174,"type":175,"period":176,"url":177,"tags":178,"metrics":180,"body":181,"_type":49,"_id":204,"_source":51,"_file":205,"_stem":206,"_extension":54},"\u002Fwork\u002F06-portale-case-vacanze","Portale Case Vacanze","I built this to manage the rental of my own apartment in Sardinia after an agency I'd signed with stopped sharing occupancy data and pricing with me. The platform lets owners create a mini-site for their property — photos, calendar, optional services with pricing, a direct request form — with no commission on bookings. It sits alongside Airbnb and Booking rather than replacing them; the next step is syncing calendars across all three via iCal.",6,"Self-managed vacation rental platform for property owners","personal","2025 – present","https:\u002F\u002Faw-properties.netlify.app",[18,17,19,179],"Supabase",[],{"type":27,"children":182,"toc":202},[183,187,192],{"type":30,"tag":31,"props":184,"children":185},{},[186],{"type":35,"value":172},{"type":30,"tag":31,"props":188,"children":189},{},[190],{"type":35,"value":191},"The interesting part turned out to be Italian vacation rental bureaucracy: SCIA filings, tourist tax collection, Alloggiati Web submissions within 24 hours of check-in, ROSS1000 regional registry. None of it is explained in one place, the government portals are painful, and the fines are not trivial. The bureaucracy layer is still to be built.",{"type":30,"tag":31,"props":193,"children":194},{},[195],{"type":30,"tag":196,"props":197,"children":199},"a",{"href":198},"\u002Fblog\u002Fportale-case-vacanze",[200],{"type":35,"value":201},"More on why I built this →",{"title":8,"searchDepth":47,"depth":47,"links":203},[],"content:work:06-portale-case-vacanze.md","work\u002F06-portale-case-vacanze.md","work\u002F06-portale-case-vacanze",{"_path":208,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":209,"description":210,"order":211,"subtitle":212,"type":175,"period":213,"url":214,"tags":215,"metrics":217,"body":221,"_type":49,"_id":243,"_source":51,"_file":244,"_stem":245,"_extension":54},"\u002Fwork\u002F07-opera-guide","Opera Guide","I went to see Rigoletto and spent the first act confidently lost. Wikipedia during the interval didn't help — three paragraphs of character names I'd already forgotten, written with the emotional tone of a property deed.",7,"Interactive guide to opera for people going to the theater","2024 – present","https:\u002F\u002Fopera-lirica.statichost.page\u002Fit",[17,19,216],"i18n",[218,219,220],"20 operas","7 composers","IT \u002F EN",{"type":27,"children":222,"toc":241},[223,227,232],{"type":30,"tag":31,"props":224,"children":225},{},[226],{"type":35,"value":210},{"type":30,"tag":31,"props":228,"children":229},{},[230],{"type":35,"value":231},"So I built what I wanted: a guide that tells you the story in a way that makes you want to watch it, with opinionated character descriptions and plot summaries by act that don't assume you already care. It covers twenty operas across Verdi, Mozart, Puccini, Donizetti, Wagner, Strauss, and a few others. Available in Italian and English. I open it on my phone before performances and sometimes in the interval.",{"type":30,"tag":31,"props":233,"children":234},{},[235],{"type":30,"tag":196,"props":236,"children":238},{"href":237},"\u002Fblog\u002Fopera-guide",[239],{"type":35,"value":240},"More on how it was built →",{"title":8,"searchDepth":47,"depth":47,"links":242},[],"content:work:07-opera-guide.md","work\u002F07-opera-guide.md","work\u002F07-opera-guide",1788876800016]