AlbertaOS
.txt
README
.pdf
CV.pdf
MarketingHub.app

Marketing Hub my own tool · in use every day

At some point SEO work across several clients stops fitting in a spreadsheet. The usual road, once you get there, is to pay for a platform that decides how you have to work. I preferred to work out what I actually needed and build it.

Marketing Hub is the working archive of my job: for every client, in one place, the editorial plan, the inventory of the site's pages, the tracked keywords, the competitors and the real figures read from Search Console and GA4. It is not a product and it is not for sale. It runs on my own machine, it has no login and no users, because the user is me.

What the agents are allowed to touch

I am not the only one filling this archive: the agents I work with write into it. They save an article, update keywords, record an analysis. The hard part was not getting them to write, it was deciding what they are not allowed to touch. Try asking.

waitingPick a request above.

What fills itself in, and what I write

The numbers fill themselves in: sessions and page views from GA4, impressions, clicks and position from Search Console, and the real titles and descriptions of the pages, read straight from the site. I write everything else, which is everything that takes a judgement: why an article should exist, who it speaks to, where it has got to, what I learned when it went wrong.

The history of every article is written by hand too, one event at a time: a hundred and thirty-five entries, one after another. No application knows how to record on its own the reason why something happened.

How it is built

Flask and SQLite behind, and in front a single-page interface in JavaScript with no framework and no build step: you edit a file and reload. The database runs in WAL mode, and that is not a technical detail dropped in for show: it is what lets an agent read it while the app is open, without either of them waiting for the other. It is the first line of the schema, so living alongside the agents was a decision taken at the start and not an afterthought.

From one client to every client

At first I had designed it to follow a single client. When I started taking on others I generalised it: the domain and the brand signals no longer live inside the analysis logic, they are passed in from outside, client by client. It is the work that shows the least and matters the most, because it is what separates a tool that works once from one you can use again.

19,700lines of code
61internal routes
20screens
pythonflasksqlite (wal)javascript, no frameworksearch console apiga4 api