Skip to contentIván Gómez Dell’Osa

Iván Gómez Dell’Osa

Full Stack Developer

The projects, on video
Project list

Personal project · 2026 · Applied AI · RAG

Ask Leonardo da Vinci

Leonardo da Vinci left more than 7,500 written pages. For the first time, software uses them to speak with him without inventing answers. A neural network finds, among 1,565 passages from his notebooks, the ones that answer each question, and the system checks that every quotation exists in the original.

“Act as if you were…” is one of the most common requests an artificial intelligence receives. When asked to be someone, the model claims it can, but it invents answers, changes the way that person speaks and gives opinions on things they never considered. To stop inventing it would need an enormous amount of context about that person: their thoughts, their experiences, what they once wondered. Leonardo left it in writing. All his life he filled notebooks, a mind transfusion onto paper: anatomy, optics, painting, machines, fables and even his shopping lists. His expressions, his answers and his opinions do not need to be invented: he wrote them himself.

The site welcomes visitors into Leonardo's workshop, seated right in front of him: you ask him a question and he answers in the first person, with the sources in plain view. Everything in quotation marks comes word for word from his notebooks. For those who do not know what to ask, Guided questions offer a map of 22 sections and 396 subjects, each one turned into a question with one click. What is not in his notebooks is not invented: the site says so. All of it in Spanish and English, with a 3D library, a 3D virtual museum and a vector space that shows how it works on the inside.

It runs on a RAG pipeline written from scratch, with no frameworks such as LangChain or LlamaIndex, so that every step can be controlled and measured on its own. The question becomes a vector right in the browser; if no passage is close enough, the system abstains without calling the model. If there is material, a hybrid search picks three passages, Gemini answers with them in front of it, and the code verifies every quotation.

0 of 187

invented quotations. With the same model and the same questions, an AI acting as Leonardo makes up 96.9% (156 of 161).

Stack

  • Next.js
  • React
  • TypeScript
  • Three.js
  • RAG
  • Transformers.js
  • Gemini API
  • Python

The difference can be measured

Quotations attributed to Leonardo that do not exist in his notebooks

Language model acting as Leonardo

96.9%156 of 161 quotations

Ask Leonardo da Vinci

0%0 of 187 quotations

Same model, same prompt and the same 120 questions. Every quotation was searched for in the full text, in both languages.

Also measuredResult
Questions answerable from the notebooks that the system wrongly refused0, across 170 test questions
Notebook subjects the search finds in both languages94%
The two runs behind the chart, with every answer in full, are published in evals/out/.

Asking Leonardo

The codex: the subject map on the left and an answer from Leonardo with a verbatim quotation and its sources.
  • Answers with sources. Leonardo answers in the first person from the retrieved passages, with the sources below and a link to each passage on Project Gutenberg.
  • Verbatim quotations. Everything in quotation marks comes word for word from his notebooks. If a quotation does not match the original, it is not shown as a quotation.
  • Guided questions. What do you ask one of the most brilliant minds in history? He wrote about so many things that it can even feel intimidating. That is why there is a map of 22 sections and 396 subjects he did write about, plus six suggested questions: pick a subject and one click turns it into a question. Anyone not used to AI can focus on reading the answers instead of crafting a prompt.
  • What he could not write. Some things Leonardo, naturally, did not leave in his notebooks, like his own death, along with facts he rarely wrote down about himself (“what day were you born?”, “who was your teacher?”). There, the site says so and shows the exact Wikipedia excerpt, with attribution, outside his voice.
  • What was lost. Over the centuries, part of his notebooks was lost. The Mona Lisa? His manuscripts never mention it, and the site shows the editor's note that confirms it. The mystery remains, but nothing is invented.
  • Bilingual. The whole site, including Leonardo's answers, is complete in Spanish and English.

3D Library

The library shelf, with the Anatomy volume taken out.
An open volume while a leaf is turning, with the loupe over a plate.

Five volumes with 27 plates by Leonardo. The volumes come off the shelf, leaves turn with the curl of a real book and, on desktop, a loupe lets you read the handwriting up close.

3D Virtual museum

The museum gallery with the Mona Lisa and The Last Supper, the visitor's avatar and the label of the work.

A gallery you walk through, on mobile too, with nine of his works and a label for each one.

Vector space

Section lit…

1,402 passages · 22 sections · 384 → 3 dimensions

It is the site's “How it works” section. It shows visitors the passages turned into vectors and how a question finds its own. It sits in a website for the general public on purpose: the technical soundness of the system is what backs every answer from Leonardo.

This is not an illustrative animation. These are the project's real vectors: the 1,402 passages the system searches, placed by its neural network and brought down from 384 dimensions to 3 so they can be seen. Light up a section and the closeness makes sense: to the neural network, passages about the same thing tend to sit together.

Architecture

The idea was the starting point, not the result. It took measuring and choosing models, calibrating the semantic search, letting only Leonardo speak (not his editor), reining in the prose AI models tend to invent, and checking that every quotation exists in the notebooks. The text the system searches is the edition Jean Paul Richter transcribed and translated in 1888, now in the public domain.

What happens to each question
  1. Questionembedding in the browserIt becomes a vector on the asker's device, with no API.
  2. Curated caseslayer 0What is known not to be in the notebooks: a refusal with the evidence cited.
  3. Similarity thresholdlayer 1If no passage is close enough, it abstains without calling the model.
  4. Hybrid retrievalcosine + BM25 · RRFPicks the three passages that will back the answer.
  5. Generationlayer 2 · GeminiThe model answers, or declines, with the passages in front of it.
  6. Verificationlayer 3 · codeEvery quotation is compared against the original passage.
  7. Answerwith its sourcesIn Leonardo's voice, with the passages in plain view.

At two of the steps the system can abstain before calling the model: it would rather say the notebooks do not cover a subject than invent an answer.

  • Cosine decides, fusion only orders. A ranking always has a first place, whether or not relevant material exists; what determines whether there is an answer is similarity against a calibrated threshold.
  • One index and one threshold per language. With a shared threshold, the filter's accuracy dropped from 88.4% to 70.5%.
  • Embeddings in the browser. The query is vectorised on the user's device: no cost per query and no quota that can run out.
  • No persistent server and no vector database. The index is an int8 binary versioned in Git, BM25 is precomputed, and the 3D sections load only when someone visits them.

Tech stack

LayerTechnology
FrontendNext.js 16 (App Router), React 19, TypeScript, Three.js
Embeddingsmultilingual-e5-small (384 dimensions, int8) · Transformers.js in the browser
RetrievalDense cosine + precomputed BM25, RRF fusion
GenerationGemini 3.1 Flash-Lite, with GPT-OSS 120B on Groq as fallback
IngestionPython: parsing the Gutenberg edition, voice separation, chunking, embeddings and calibration
Evaluation170 questions across 8 categories · automated judge validated against human labelling
SecurityCloudflare Turnstile, hashed-IP rate limiting and a global daily budget
Hosting & CIVercel · GitHub Actions

Personal project · 2026 · Data · ETL

Datos Pauta Oficial

The first and only unified database of Argentine government advertising: 540,413 advertising orders from the national government, Buenos Aires City, Buenos Aires Province and Santa Fe (2003–2025), with amounts adjusted for inflation (CPI). It is queried on the website through an explorable table, rankings and the “Cuánto recibió” (how much it received) search by supplier, media outlet or media group, with the methodology published.

Before, that data was scattered across portals, spreadsheets and PDFs from each jurisdiction, with no unified, simple way to access it or compare it. The Python ETL includes a Buenos Aires Province 2020–2024 dataset reconstructed from more than 500 PDF resolutions, data that does not exist in any open data portal.

Backendless architecture: the SQLite database (~173 MB) is hosted on Cloudflare R2 and the browser queries only the bytes it needs through HTTP Range Requests.

540,413

advertising orders unified from four jurisdictionsNación · CABA · PBA · Santa Fe · 2003–2025

Stack

  • Python
  • ETL
  • SQLite
  • Astro
  • React
  • TypeScript
  • Cloudflare R2/Pages

Buenos Aires Province, rebuilt from PDFs

Buenos Aires Province does not publish its 2020 to 2024 advertising orders in open datasets: the information sat in individual PDF resolutions. A script extracted the data resolution by resolution (more than 500) to reconstruct the detail of each order: supplier, media outlet, amount and file number. That stretch is a dataset of the project's own.

Coverage

Database coverage, by jurisdiction
CABA209,877CABA: 2003–2024, 209,877 orders.
Santa Fe61,187Santa Fe: 2008–2023, 61,187 orders.
Nación225,367Nación: 2009–2022, 225,367 orders.
PBA43,982PBA: 2020–2025, 43,982 orders.

PBA 2020–2024 · Rebuilt from more than 500 PDF resolutions

540,413 orders in total, 2003–2025

JurisdictionPeriodOrders
Nación2009–2022225,367
CABA2003–2024209,877
Santa Fe2008–202361,187
PBA2020–202543,982
Total2003–2025540,413
Coverage gaps are shown explicitly on the website: aggregates that could mislead due to incomplete coverage are never presented.

Architecture

The project runs with no backend or servers: the full SQLite database (~173 MB) lives on Cloudflare R2 split into chunks, and the browser queries only the bytes it needs through HTTP Range Requests, thanks to sql.js-httpvfs.

From the official source to the browser
  1. Official sourcesCSV · Excel · PDFEach jurisdiction publishes in its own way.
  2. ExtractionPythonOne extractor per jurisdiction.
  3. Unificationunificar.py · validar.pyA single validated canonical CSV: 8 columns, 540,413 rows.
  4. Databasebuild_db.py · SQLiteAmounts deflated by CPI (INDEC) and precomputed caches.
  5. StorageCloudflare R2The database, split into 20 MiB chunks.
  6. Queryingsql.js-httpvfsSQL from the browser, which requests only the chunks it needs.
  7. WebsiteAstro · React · Cloudflare PagesStatic, with React islands: no backend or servers.

Features

  • Explorable table of 540 thousand orders. Cross filters by jurisdiction and year, grouping by supplier or media outlet with expandable rows. The initial state is precomputed into the HTML, and the database opens only when the user interacts. The value shown is the exact raw figure from the official source.
  • “Cuánto recibió” (how much it received). Search by supplier, media outlet or media group; group mode consolidates each holding's companies according to the Media Ownership Monitor Argentina, with the source cited. It generates a 1080 × 1080 image for sharing, with pure Canvas, and links that restore the search.
  • Rankings of suppliers, media outlets and groups by jurisdiction and year, served from caches precomputed at build time.
  • Public methodology: sources, deflation and normalization criteria documented on the site.
The Datos Pauta Oficial home page: 540,413 advertising orders, 15,688 media outlets, 6,481 suppliers and 4 jurisdictions.
The Datos Pauta Oficial home page on a phone.

Data decisions

  • Deflated, not nominal amounts. Everything is in constant pesos (INDEC CPI): comparing 2009 advertising with 2024 in nominal pesos makes no sense in Argentina.
  • The exact figure, even at the cost of convenience. The table shows every order as it appears in the official source, without correcting or grouping names, even though that makes it less comfortable to read: the same supplier can appear spelled several ways. Rankings and “Cuánto recibió” only unify spelling variants of the same company name, from a conservatively curated list; consolidation by media group is a separate option, with its source cited.
  • Honesty about the gaps. Every source limitation (rows without a date, partial periods) is documented rather than hidden.
  • An informative stance: no accusation, no opinion.

Tech stack

LayerTechnology
ETLPython: per-jurisdiction extractors, unification and validation
DatabaseStatic SQLite, queried from the browser with sql.js-httpvfs
FrameworkAstro 6 (static output) + React 19 (islands)
LanguageTypeScript
SearchMiniSearch (client-side index)
HostingCloudflare Pages + Cloudflare R2
DeflationINDEC CPI, amounts in constant pesos

Freelance · Dec 2025 – Jun 2026 · Full stack

SeViVe

A booking and management application for a pilates studio, in production with more than 200 users. Students book their classes from their phones and the administration runs the studio from its panel. REST API in Python/FastAPI and PostgreSQL.

I built it as the sole developer for a studio in Canning, Buenos Aires (a franchise), from defining requirements with the client to production launch. Since development ended, I remain responsible for support, server administration and client-requested updates.

Bookings with concurrency control to prevent overbooking, expiring credits, recurring slots with automatic booking, attendance tracking and a calendar with configurable holidays. Accounts created by the administration merge automatically with the student's own account at sign-up (by national ID), preserving history, credits and slots.

It installs as a PWA on any device, with a step-by-step guide designed for non-technical users.

200+

users

Stack

  • Flutter
  • Python
  • FastAPI
  • PostgreSQL
  • Firebase
  • Docker
  • Nginx

What it solves

The goal: an easy-to-use application that lets the studio delegate and organize its management, while keeping any student from breaking the business rules.

  • Bookings with concurrency control. The backend validates spots, credits and schedules on every booking: two students cannot both take the same last spot.
  • Recurring slots and classes. The administration creates a class once and the system generates the weekly instances around holidays; memberships book themselves every week.
  • Expiring credits, deducted automatically on each booking, and cancellation with penalties for late notice or no-shows.
  • Account merging by national ID. The administration can add students who do not have the app yet, so that spots and statistics are real. When that student signs up with their ID, both accounts merge and keep recurring slots, credits and history.
  • Attendance. The administration takes it from the day's schedule, and the monthly calendar keeps every class taught with its occupancy and attendance.
  • Admin panel: per-student history, blocking users with cancellation of their future bookings, a global pause on bookings, and holidays added from the app, with no deploy.
  • Communication: announcements with push notifications and feedback after every class, with an email alert to the administration on a negative answer.
  • Medical certificate: PDF or image upload, with automatic compression.
  • Monthly raffle among active students, weighted by attendance, to encourage consistency.
  • Installation without an app store. It is a PWA: it installs from the browser on a phone, tablet or computer, with a step-by-step guide designed for non-technical users.

Architecture

How it is built
Flutter app (PWA)students · administration
VPS · Docker Compose
Nginx
FastAPIasync
PostgreSQLasyncpg · Alembic
FirebaseGoogle · Storage · push (FCM)
  • Bookings with concurrency control
  • Expiring credits
  • Recurring slots, booked automatically
  • Account merging by national ID

A single Flutter app (Riverpod, Freezed, GoRouter) for students and administration, served as a PWA. Sign-in is Google's, through Firebase, and the backend verifies that identity on every request.

Nginx receives the traffic over HTTPS, rate-limits requests per IP address and serves the app and the uploaded files. Behind it, the asynchronous FastAPI API (SQLModel, asyncpg) works on PostgreSQL 16, with schema changes versioned in Alembic. Push notifications go out through Firebase Cloud Messaging.

Everything runs in three Docker Compose containers (database, API and Nginx) on a VPS I manage: deployment with a script that applies the migrations, backups and troubleshooting.

Tech stack

LayerTechnology
AppFlutter 3, Riverpod, Freezed, GoRouter, Dio · installable as a PWA
BackendPython, FastAPI (async), SQLModel, asyncpg
DatabasePostgreSQL 16, Alembic
AuthenticationFirebase Authentication (Google)
Files and notificationsFirebase Storage, Firebase Cloud Messaging
InfrastructureDocker Compose, Nginx, VPS on Hetzner

Personal project · 2026 · AI · Automation

Inversiones en Argentina

Uses AI to track private investments in Argentina. It identifies the real investments, discards duplicates and publishes the results on the website and in a Telegram channel.

The information was scattered across news outlets, X accounts and official registries, and each investment shows up repeated in many outlets, written in different ways. A scheduled GitHub Actions workflow gathers those sources and adds a Google search with Gemini and Search Grounding.

A layered system decides what gets published: Gemini structures each mention, deterministic rules and Jev (TypeSafe) separate the real investments from everything else, and pgvector retrieves similar records. The same project, reported by two outlets, can read very differently, and two distinct projects in the same region can look almost identical: that is why similarity only suggests candidates, and the decision is made by identity rules and a decision model (Jev). FastAPI API and a Next.js frontend with server-side rendering, on Vercel.

Stack

  • Python
  • FastAPI
  • Gemini
  • Jev (TypeSafe)
  • PostgreSQL/pgvector
  • GitHub Actions
  • Next.js

The pipeline of each run

What gets published
  1. SourcesX · RSS · RIGISpecialised accounts, outlets by sector and the official registry.
  2. FilterdeterministicRemoves the noise: fewer tokens and simpler decisions downstream.
  3. ExtractionGemini + GroundingEvery mention becomes structured data.
  4. ValidationrulesOut go debt, loans, share purchases and launches.
  5. JudgementJev (TypeSafe)Is it a concrete private investment?
  6. Deduplicationpgvector + identitySimilarity retrieves; identity decides.
  7. Publishingweb · TelegramOnly what is new, unattended.

Each layer discards something and leaves the next one less noise and less room for error. Without Jev, the pipeline runs the same on its deterministic layers.

  • Collection. Specialised X accounts (Apify API), outlets from different sectors via RSS, paginated until the whole window is covered, and the official RIGI registry (the incentive regime for large investments) incrementally: a fingerprint of each project is stored and only new or changed ones are re-sent.
  • Relevance filter. A deterministic filter discards the structural noise in the feeds before it reaches Gemini. It does more than save tokens: the following steps receive less irrelevant material, so their decisions are simpler and leave less room for error. It favours not losing anything: when in doubt it lets an item through, because over-filtering means losing a real investment.
  • Extraction with Gemini and Search Grounding. The collected material goes in as the first source and Gemini searches Google for news from the period as the second, focused on the sectors the owned sources cover least. It returns each investment as structured JSON.
  • Validation. A deterministic net discards whatever is not a new productive investment: debt issuance, loans, company incorporations, share purchases, contracts won by suppliers and product launches.
  • Semantic judgement with Jev. A model that returns typed decisions with calibrated probability, instead of text, answers whether each record is a concrete private investment.
  • Deduplication. The embedding retrieves the closest candidates; the decision is made by identity rules and Jev, answering whether two records describe the same project.
  • Publishing and status report. New records are stored and published at once to the website and Telegram. Each run ends by reporting the status of every source, and fails if one that should be responding returned nothing.

Why similarity retrieves but does not decide. Over a thematically narrow corpus, the vector space compresses. Two distinct projects in the same sector and region can look as alike as the same project reported by two outlets, and no threshold separates those two cases.

Features

The inversionesargentina.com.ar home page: the flag, the search box and the investment timeline.
  • Interactive timeline sorted by announcement date, with each investment's status (confirmed, announced or under evaluation), readable amounts (USD 40M, USD 1.2B), province and jobs when available.
  • Real-time search across company, description and location, accent-insensitive: “Neuquen” finds the investments in Neuquén.
  • Indexable: the first page is server-rendered, with structured data (JSON-LD), sitemap.xml and robots.txt.
  • REST API in FastAPI with automatic documentation.

Tech stack

LayerTechnology
AutomationGitHub Actions (every 72 hours)
SourcesApify (X), outlet RSS feeds, official RIGI registry
Generative AIGemini 2.5 Flash with Google Search Grounding
Semantic judgementJev (TypeSafe)
Embeddingsgemini-embedding (768 dimensions)
DatabasePostgreSQL (Neon) with pgvector and unaccent
APIPython, FastAPI (async), Mangum, on Vercel
FrontendServer-rendered Next.js 16, TypeScript, Tailwind CSS, Framer Motion
PublishingTelegram Bot API

Personal project · 2026 · Computer vision

FaceHunt 2

A facial recognition system with AI and deep learning that, from a photo, finds every appearance of a person in hours of video, even in profile, partially covered or at low resolution.

Everything is processed locally with GPU acceleration, without sending data to the cloud. It is a desktop application that returns exact time ranges, with a thumbnail, a mini-clip and direct access to each moment, for a local file or a YouTube video. Applicable to security, investigation and video analysis.

Facial recognition with InsightFace (ArcFace, 512-dimensional embeddings) on ONNX Runtime, with GPU acceleration based on the available hardware and cross-frame tracking. It is a full rebuild of the first version, FaceHunt (2025): from TensorFlow on CPU to ONNX Runtime on GPU.

7 s

to find a one-second appearance in a 70-second video

Stack

  • Python
  • InsightFace
  • ArcFace
  • ONNX Runtime
  • FastAPI
  • pywebview
  • pytest

What it does

You load one or more photos of the person and a video (a local file or a YouTube URL). The application returns the exact time ranges in which they appear, each with a thumbnail of the face, an animated mini-clip of the moment and a direct jump, plus a clickable timeline of the whole video.

How a search works

  • Reference. The photos are validated and a 512-dimensional embedding is computed per face; with several photos they are averaged, for a more stable identification.
  • Video. The file or URL is validated (YouTube is downloaded with yt-dlp).
  • Background analysis. A producer thread reads frames and another analyses them: detection with SCRFD, cosine comparison against the reference and tracking of each face across frames.
  • Live progress. Progress, remaining time and matches arrive through Server-Sent Events, and the search can be cancelled at any moment.
  • Results. Matches are grouped into ranges, each with its thumbnail, mini-clip and link.
The FaceHunt 2 interface at the first step: uploading the reference photo.
The interface runs in a native window (pywebview) on top of a local FastAPI server.

Features

  • 100% local and private. Photos and videos never leave the computer: no online server and no cloud upload.
  • Current facial recognition. InsightFace antelopev2 (SCRFD-10G + ArcFace ResNet100 trained on Glint360K, 512-dimensional embeddings) on ONNX Runtime, with flip-TTA so appearances are not missed.
  • Automatic GPU acceleration. It picks the best available provider (CUDA, DirectML or CPU): it works with NVIDIA, AMD and Intel cards on Windows.
  • Temporal tracking. It groups faces into tracklets across frames and compares against the aggregated embedding, which recovers appearances in degraded frames (in profile, covered or at low resolution).
  • Two modes: fast (2 frames per second) and thorough (5 frames per second and smaller faces).
  • One-click executable for Windows, with pytest tests for the pure logic.

From FaceHunt to FaceHunt 2

FaceHunt (2025)FaceHunt 2 (2026)
EngineTensorFlow on CPUONNX Runtime on GPU (CUDA, DirectML or CPU)
ModelFaceNet, 128 dimensionsArcFace ResNet100, 512 dimensions
ResultLoose timestampsRanges with thumbnail, mini-clip and timeline
UseWeb interface: demo on Hugging Face Spaces or a Docker imageOne-click desktop application, no server or cloud

Tech stack

LayerTechnology
RecognitionInsightFace (SCRFD + ArcFace), ONNX Runtime
VideoOpenCV, yt-dlp
BackendPython, FastAPI, Server-Sent Events
InterfaceHTML, CSS and JavaScript with no build step, in a pywebview window
Testing and packagingpytest, PyInstaller, Windows installer

First version

The web interface of the first version of FaceHunt, at the reference photo step.

FaceHunt 2025

Deep learning facial recognition in video: DeepFace (FaceNet) with two analysis modes (high precision with RetinaFace, balanced with MTCNN), batched frame extraction with OpenCV and YouTube downloads with yt-dlp. It started as a Tkinter desktop app and gained a FastAPI API with a step-by-step web interface. It was published as a web demo on Hugging Face Spaces and as an image on Docker Hub, and runs on Windows, macOS and Linux.

  • Python
  • DeepFace
  • FaceNet
  • RetinaFace
  • FastAPI
  • Docker
  • Hugging Face Spaces

Personal project · 2026 · Chrome extension

MementoLife

A Chrome extension published on the Chrome Web Store that replaces the new tab with a grid of the weeks of a life, calculated from the date of birth.

Light, dark or system theme, a full interface in 6 languages and a historical fact for every day of the year. No network connections and a single permission (storage): the date of birth is stored only on the device.

TypeScript with no framework or bundler: native ESM compiled with tsc. Unit and snapshot tests with Vitest, end-to-end tests with Playwright on the packaged extension, and CI with GitHub Actions.

3 paths

in SVG to draw 4,160 weeks, instead of one element per week. Rendering drops from 10.00 ms to 1.30 ms.

Stack

  • TypeScript
  • Manifest V3
  • SVG
  • Vitest
  • Playwright
  • GitHub Actions

What it does

Every dot is one week. The weeks lived are drawn filled in, the ones ahead barely there, and a ring marks the current week. Life expectancy can be set between 20 and 100 years, and every day shows a different historical fact, in all 6 languages, which can be turned off.

The grid, live

An 80-year life, week by week
—week — of 4,160

The grid on this page is drawn with the same technique as the extension: three accumulated SVG paths (past, future and ring) instead of one element per cell. In the extension, that avoids 4,160 elements and brings rendering down from 10.00 ms to 1.30 ms, measured against the alternative of one element per week.

Screenshots

MementoLife in dark theme: the percentage of life, the current week and the dot grid.
MementoLife in light theme.
The options page: date of birth, life expectancy, theme and language.
The fact of the day under the percentage.

Privacy

  • No network connections.
  • A single permission: storage.
  • The date of birth is stored in chrome.storage.local, never in sync: it never travels through the Google account.

Tech stack

LayerTechnology
LanguageTypeScript
RuntimeNo framework, no bundler: native ESM, tsc as the only build step
RenderSVG from a pure core: no DOM, no chrome.*, the date comes in as a parameter
TestingVitest (unit + snapshots) + Playwright (end-to-end on the real package)
PackagingManifest V3, a single permission, no service worker
CIGitHub Actions on every push

Project history

MementoLife started as an Android app that put the grid on the lock screen. It worked, but MIUI and One UI silently ignore attempts to update only the lock screen (setBitmap(..., FLAG_LOCK) does not fail: it does nothing). Rather than break one of the project's design decisions, the platform changed.

Rugidos Fiestas Tandil · 2023 – present · Commercial website

Rugidos Fiestas

Commercial website for an events company, mobile first and optimized for local search.

I designed, built and maintain the company's commercial website, in production. The current version is built with Next.js, TypeScript, Tailwind CSS and Framer Motion, with my own UX/UI design.

Heavy effects are turned off on phones to keep scrolling smooth, the Instagram feed and the reviews are local content instead of external widgets, and structured data helps with local search.

95 / 100

Lighthouse performance with the mobile profile, on the live site (99 on desktop)Median of 3 runs · September 2026

Stack

  • Next.js
  • TypeScript
  • Tailwind CSS
  • Framer Motion
  • Lenis
  • shadcn/ui
  • Vercel

The website

The website is the sales channel of Rugidos Fiestas Tandil, a children's events business: it has to show the venue, the services and the extras, and lead visitors to a WhatsApp enquiry. That is why it was designed for phones first.

The “Why choose us?” section: the years and events counters and the cards for service, ideas, venue and experience.
The website on a phone.

Sections and features

  • Our venue: a gallery with a keyboard-navigable lightbox and a grid of the venue's features.
  • Star Academy: on desktop, a radial mask that follows the cursor reveals the “superstar” look under the casual one; on phones, a before/after slider dragged with a finger.
  • Real hover detection (hover: hover and pointer: fine) instead of a width breakpoint, so the experience does not break on touch tablets.
  • Reviews: a Google Reviews summary and marquees with a manual pause, with no dependency on widgets.
  • Contact: a WhatsApp button that opens the chat with the message already written, the venue's address with its Google map, the social links and a selection of Instagram posts.

Performance

LighthouseMobileDesktop
Performance9599
Accessibility9696
Best practices100100
SEO100100
LCP2.9 s0.8 s
CLS00
Lighthouse 12 on the live site, median of 3 runs per profile (September 2026).
  • Parallax, the cards' 3D effect, frosted glass and entrance animations are turned off on phones, so content arrives sooner and scrolling stays smooth on mid-range devices.
  • The logo went from PNG (127 KB) to WebP (7 KB), and the hero's critical asset is requested with high priority.
  • The venue and extras photos were batch-processed with Sharp: from ~15.6 MB to ~1.8 MB.
  • The Instagram feed and the Google reviews are served as local content: no external dependencies and no layout shifts while they load.
The service cards and the purple section with birthdays, capacity and frozen price.

Tech stack

LayerTechnology
FrameworkNext.js (App Router), TypeScript
Styling and componentsTailwind CSS, shadcn/ui, Radix UI, Lucide
MotionFramer Motion, Lenis (desktop only)
DeployVercel, Vercel Analytics

First version

The 2023 site's home page: pink background, the Rugidos lion and the social links.

RugidosWebSite 2023 2023 – 2026

In production from 2023 until it was replaced by the current version. HTML, CSS and JavaScript with no frameworks, with automatic deploy to cPanel. Built without AI assistance.

  • HTML5
  • CSS3
  • JavaScript

Rugidos Fiestas Tandil · 2025 · Desktop application

FreeMagicMirror

A touchscreen photo booth application in use at the Rugidos venue, distributed as a portable Windows executable.

Capture with an animated countdown, a multitouch editor with free drawing and stickers that scale and rotate with the fingers, and automatic saving to a local gallery. Designed for children: animated videos, smooth transitions and large controls.

Python, Kivy and OpenCV. A hidden admin panel (five taps in a corner) sets the camera, orientation and monitor, and the app runs in kiosk mode, full screen and borderless.

Stack

  • Python
  • Kivy
  • OpenCV
  • PyInstaller
  • Docker

The on-screen flow

The application's screens, in order
  • Start: a looping video invites people to touch the screen.
  • Pose: an animation suggests poses for the photo.
  • Countdown and capture from the camera.
  • Editor: free drawing in five colors, stickers that scale, rotate and move with several fingers, and undo.
  • Saving to a local gallery, with incremental numbering.

Technical decisions

  • The camera starts after the videos, at 10 frames per second, so playback does not stutter.
  • Videos decoded with FFPyPlayer, integrated into Kivy, and the whole canvas (photo, drawings and stickers) exported to PNG.
  • Hidden admin panel: camera detection with OpenCV, portrait or landscape orientation with window adjustment, and choice of output monitor.
  • Paths that detect whether the app runs packaged with PyInstaller, so the executable finds its resources when copied to another computer.

Distribution

A portable Windows executable (.exe) with no external dependencies, published in the repository's Releases, and an image on Docker Hub for Linux.

Iván Gómez Dell’Osa

About

I build complete software products, from design to production, with a focus on backend and applied artificial intelligence. I have experience with end-to-end projects, personal and freelance, with real clients and users, using Python, React and Next.js, PostgreSQL and REST APIs.

Building on the foundation my Systems Engineering studies give me (programming logic, mathematical analysis and algorithm design), I teach myself current technologies and apply them in personal projects with published code. I combine this with running the operations of a small business, where I am gaining knowledge of business administration, product and team management.

I am proficient in AI applied to work and to product solutions: it is part of my development process and of the products I build. The product, design and architecture decisions are my own.

Location
Argentina · Remote work
Languages
Spanish (native) · English (B2)
Citizenship
Argentine and Italian (EU passport)
Education
Systems Engineering · UNICEN · 2022 – present
Certification
Scrum Fundamentals Certified (SFC) · VMEdu · 2024

Experience

  1. Rugidos Fiestas Tandil

    Events SME · Tandil, Argentina

    • Software DeveloperSep 2023 – present
    • Operations ManagerSep 2019 – present
    • Designed, built and maintain the company's commercial website, in production: first version in 2023 and a full redesign in 2026, with my own UX/UI design.
    • Built FreeMagicMirror, a touchscreen photo booth application used at events.
    • Manage daily operations: event organization, internal process optimization and service model improvements, some of them implemented with in-house software.

    Rugidos FiestasFreeMagicMirror

  2. SeViVe

    Pilates studio (franchise) · Canning, Buenos Aires

    • Freelance Full Stack DeveloperDec 2025 – Jun 2026
    • Built, as the sole developer, a booking and management application with more than 200 users, from defining requirements with the client to production launch: bookings with concurrency control, expiring credits, recurring slots and an admin panel.
    • Since development ended, I remain responsible for support, server administration and client-requested updates.

    SeViVe

  3. Navkok Security Group SRL

    Private security company · Argentina

    • Freelance Web DeveloperMar 2026 – Apr 2026
    • Redesigned the corporate website, from selling the project to its completion: information architecture, UX/UI design, corporate copy and multimedia content produced with AI tools.

    Navkok Security Group