The Code Behind the Commercial
My day job is revenue retention and enterprise implementation. This page is the other half: the stack I work in, the tools I reach for, and what I have been committing.
Philosophy & Stack
I run Linux and prefer open-source tools, because I can see what they do.
I map CRM/ERP systems in raw SQL rather than through GUI tools, design the identity resolution that merges each customer's sources into single profiles, and configure the per-customer Snowflake tables myself. In the early days, while the platform's email editor caught up, I also hand-wrote the HTML behind client email templates.
I debug API integrations in Swagger, OpenAPI, Insomnia and Bruno, and find payload errors before they need an engineer.
I use AI where it removes the repetitive part of the work. At Data Talks I built a toolkit, backed by a knowledge library of the platform's configuration, that migrates customer accounts and builds dashboards through the platform's API. Here, AI is a daily pair programmer on this site and the API behind it.
I build this site with 11ty, Nunjucks and Tailwind CSS, and GitHub Actions deploys it. The signed-in app has its own section further down. For backend utilities and data formatting, I default to JavaScript and Python.
A system I run end to end
The signed-in app on this domain authenticates people, proxies ten third-party sources, writes to Postgres and deploys itself. I designed it, built it and keep it running. That is the same work as onboarding a customer onto a platform: making systems that were never built for each other agree on what a field means.
Ten sources mapped into one shape
Weather, Swedish timetables, live bus positions, Formula 1, GitHub Actions, three sports leagues' own sites and two newspapers each answer in their own vocabulary. I map thirty-six fields into one internal shape, and label the calculated ones (a delay in minutes, a position gained, which step of a build failed) as calculated, so nobody reads a derivation as a measurement.
A two-hour error that was not the vendor's fault
Every bus departure showed two hours out. The transit feed sends Swedish wall-clock time with no offset and the container runs in UTC, so the times parsed as the wrong instant. The API now resolves them against Europe/Stockholm, with tests across both daylight-saving changeovers.
Authorisation that does not trust its own token
A signed token proves who signed in. It does not prove what they may do now, so every request re-reads the role and approval state from the database before anything happens. Withdrawing someone's access takes effect on their next request rather than whenever their token happens to expire.
A database browser with no query box
Administrators can read the tables. There is nowhere to type SQL, the readable tables are an allowlist rather than whatever the catalogue reports, and the columns holding a sender's IP address are never selected at all. Someone who steals a session on this screen can read tables and cannot run a query.
The full reference lives inside the app: every endpoint, every field mapping, and why each cache window is the length it is. It is at app.tzortzoglou.eu/docs.
Live code activity
742 contributions in the last year, a darker square being a busier day. See the profile on GitHub.