TRAUTOK STATION: the personal dashboard running on Python stdlib and SQLite
There's one screen I keep open more than any other. It isn't a product, it has no users, and it doesn't need to please anyone but me. It's the cockpit I use to look at my day — and like every tool I actually rely on, I built it to last: two files, no dependency I can't lose without sinking. The construct calls it a station. I call it the place where I figure out where I stand.
What a personal "command deck" is
TRAUTOK STATION is a personal dashboard: a single page where everything that would otherwise end up scattered across ten different apps comes together — a quote to get started, things to do, my finances, the week, the journal, the map of the people who matter. I didn't build it to sell it. I built it because I needed one place to look at, and because I wanted that place to be mine in the most literal sense — code I understand, data sitting in a file I can open with my own hands.
It's a Zone 1 project in its most honest form: a tool born from a real problem, mine first of all. This is the build log of what's inside.
How it's built: two files and nothing else
The whole dashboard lives in two pieces, and the split is clean:
- ONE UI FILE —
trautok-dashboard.html: the structure, all the CSS and all the JavaScript live inline in that single file. The only external resource is Google Fonts (Orbitron, Share Tech Mono, Special Elite). No bundler, no framework, no build pipeline to memorize. - ONE STDLIB SERVER —
launcher.py: an HTTP server written with nothing but Python's standard library[1] (http.server+sqlite3). It serves the page and exposes a small REST API backed by a local SQLite database indata/trautok.db. You start it withpython3 launcher.pyonlocalhost:8765, and it creates the DB on first run if it doesn't exist. - ONE EXCEPTION, OPTIONAL — the Google Calendar integration. The Google libraries are imported lazily, only when a calendar endpoint is hit: if they aren't installed, the server starts anyway and every other panel works. The heavy dependency is fenced in where it's needed, and it can be amputated without killing the rest.
- NO BUILD, NO TEST SUITE, NO LINTER — you edit the two files and that's it. It's a choice, not laziness: the fewer layers between me and the program, the longer the program survives me forgetting about it for six months.
The seven panels
The interface is a CSS grid of seven panels, each one self-contained:
- MOTIVATION — a "quote of the moment" from a static array, typed out on screen with a typewriter effect. It starts immediately, without waiting for the server.
- TASKS — things to do with deadlines and priorities, checkable.
- FINANCES — not a fixed snapshot, but a list of goals (project, family, savings, taxes), each with its own income and expense entries. At the top, three semicircle gauges drawn in SVG — autonomy, business share, margin — and a mini-chart projecting net income over the next six months.
- WEEKLY PLANNING — the grid of the current week, with today highlighted, with Google Calendar events overlaid on top.
- JOURNAL — dated, independent notes with autosave.
- FAMILY — the relationship map, which I'll get to in a moment.
- CALENDAR — the agenda of upcoming commitments, separate from the week view, with event adding and deletion.
The relationship map
The panel I'm proudest of is Family, and it's a real node map. In the center sits the ME node; the people are arranged on a circle around it, connected by lines. The lines aren't decoration: the line style encodes the type of bond — solid for blood, dashed for in-laws, dotted for everyone else. On top of these there are free-form links from person to person, each with its own style.
- CLICKABLE SVG EDGES — every connection is an SVG line with a wider transparent stroke on top that acts as the click target. Clicking an edge opens the checklist of activities with that person; each activity can be sent as an event to Google Calendar (
"<activity> · with <person>"). - ZOOM AND FOCUS — double-click a node and the view centers on it with a CSS
transform; non-neighbors fade out. There's also an "only people connected to X" filter to thin things out as the nodes multiply. - PER-NODE NOTES — every person (and the ME node) has their own free-text notes, with a small badge when they're not empty.
The data flow (offline-first)
This is the part that really matters. The source of truth is SQLite[2], not the browser. The page's JavaScript never writes directly to localStorage: there's a single write point, persist(store, value), which first saves a lossless local backup and then, if the server is online, sends a PUT /api/<store>. Every save function goes through it.
On load, a GET /api/all fills all the stores (tasks, budget, journal, family) in one shot. If that call fails — say I opened the file via file://, with no server — the dashboard slides into offline mode: it shows a banner, lights up the DB offline badge and reads from the local backup. localStorage isn't the archive: it's the lifeboat. And if the DB is empty but a backup exists, the page re-imports it on its own, once.
> ui: 1 html file (css + js inline) · only external dep: google fonts
> server: python http.server + sqlite3 (stdlib) · localhost:8765
> truth: sqlite → data/trautok.db · localStorage = offline backup only
> api: GET /api/all · PUT /api/<store> (atomic replace)
> calendar: google, lazy import · missing → the rest lives
Why stdlib and no framework
The obvious question: why hurt yourself with http.server when there are frameworks that give you everything in three lines? The answer is the same one that runs through everything I publish here. A personal tool I use every day has to pass one precise test: if the third-party service vanished, does the project live? With two files of pure standard library and one SQLite file, the answer is yes. Google Calendar can drop off tomorrow and I lose a panel, not the station.
It's the principle behind the return to self-hosting applied on a small scale, and the same pact I made with myself when I started writing code with an agent: use the tools of the present, but stay able to survive their absence. A dashboard that depends on half the Internet is a cockpit someone else can switch off.
Frequently asked questions
What stack does this dashboard use?
Two files: a trautok-dashboard.html with inline CSS and JavaScript (the only external dependency is Google Fonts) and a launcher.py, an HTTP server built purely on Python's standard library (http.server + sqlite3). No framework, no bundler, no build step.
Where is the data stored?
In a local SQLite database, the file data/trautok.db. The browser's localStorage is used only as an emergency backup when the server can't be reached, not as the main archive.
Does it work without a connection?
Yes, in two senses. Everything runs locally, so you don't need the Internet to use it. And if I open the page without the server running, it goes into offline mode: warning banner, "DB offline" badge, and reading from the local backup. The only piece that needs the network is the optional Google Calendar integration.
I close the laptop and the station stays right there, in its file of a few megabytes. No cloud to thank, no subscription to expire. May your cockpit outlive the apocalypse — and above all, outlive you forgetting about it.
Notes
- stdlib (standard library) — the set of modules that ship with Python without installing anything. Here the two pillars are
http.server(a basic HTTP server) andsqlite3(the interface to the SQLite database). Fewer external dependencies = fewer things that break over time. ↑ back to text - SQLite — a relational database that lives in a single file on disk, with no separate server. The server opens one connection per request in WAL mode, which is compatible with the multi-threaded server. ↑ back to text
SURVIVAL APPS