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.

Linux
SQL
Snowflake
Terraform
JS
Python
HTML
Insomnia
Git
11ty

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.

In your hands Served as files · no secret is in them The only thing that decides What it asks, on your behalf Your browser tzortzoglou.eu the portfolio · one call: the contact form app.tzortzoglou.eu signed in · pages only api.tzortzoglou.eu checks the token · re-reads your role · holds every key nothing below this line is reachable without it Firebase who you are Postgres messages · caches Ten upstreams three need a key Open-Meteo · Trafiklab ResRobot · Jolpica · GitHub Actions ESPN · shl.se · hockeyallsvenskan.se · Expressen · Aftonbladet none of these ten is ever called from your browserthe app’s map tiles are the one exception, fetched by your browser itself

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 GitHub contributions between 2025-10-19 and 2026-10-19, shown as a grid of days shaded by how many contributions each holds, darker squares meaning more.

742 contributions in the last year, a darker square being a busier day. See the profile on GitHub.