Every so often a user asks what actually happens after they connect their Notion workspace. Fair question: you are trusting an app with your habit data, so you deserve to know what runs on the other side. I'm Lucas, the solo developer behind Notion Habit Heroes. This is an honest tour of the stack as it runs in August 2026, written for curious users rather than recruiters.

Three parts, one product

The product is three pieces. A backend does the real work: syncing journals, calculating streaks, scoring competitions. A static website serves the page you are reading right now. A widget written in plain JavaScript lives inside your Notion pages. Each piece is shaped by where it runs, which is most of what this post is about.

A boring backend, on purpose

The core is a Spring Boot application on Java 17 with PostgreSQL, hosted on AWS in Frankfurt. That is about as boring as stacks get in 2026, which is exactly the point. A habit tracker has one job above all others: your streak must be correct every single morning. So the innovation budget goes into reliability, not novelty.

Every night the backend creates tomorrow's journal row in your Notion database, then syncs your checkboxes at your local midnight rather than mine. Timezones are the hardest part of the whole system. Every user gets their own scheduled task in their own timezone; tasks are persisted, so a restart or a deploy cannot lose them. A few hours later a self-healing job walks through every user's sync from that night, finds anything that failed or got stuck, then quietly re-runs it. Most incidents fix themselves before I wake up.

Talking to Notion politely

The code that talks to Notion is not written by hand. I maintain a formal description of the endpoints the app uses; a generator turns it into client code at build time. When Notion ships a new API version I update the description, regenerate, then let the compiler point at everything that changed. The app used to speak two Notion API versions at once: the older 2022 endpoints for journal syncing, plus the 2026 data-source API behind the habit schedule mirror. The last of those old calls has since moved across, so every request now goes out on the single 2026 version. Every request passes through a rate limiter capped at three requests per second per user. Notion asks integrations to stay under that limit; being a polite API citizen beats being throttled.

Seventeen thousand lines, zero frameworks

The widget you embed in a Notion page is plain JavaScript. No framework, no bundler, no build step. That choice surprises developers, but it comes straight from where the widget lives: inside an iframe in Notion, frequently on a phone, sometimes on hotel wifi. A small hand-written bundle loads faster than any framework I tried, plus there is nothing between the file I write and the file your browser runs. It even watches for new versions on its own: when I deploy while your Notion page is open, the widget reloads itself.

A website with no server

The site is built with Angular 18, yet no server renders it. Every page, including this article, is prerendered to plain HTML at build time, then served from a CDN. There is no application server to slow down, break, or get attacked. The moment you log in, your browser talks to the backend API directly; until then, you are reading static files.

Analytics without cookies

Since August 2026 analytics run on a self-hosted Umami instance on the same Frankfurt infrastructure. It is cookieless, so there is no consent banner because there is nothing to consent to. It records page views plus a handful of anonymous events. No ad networks, no fingerprinting. The hosted analytics provider I used before was perfectly fine; self-hosting simply makes the promise structural: your usage data never leaves the product's own infrastructure.

Assume nothing works, then check

The hardest operational lesson of this project, told in full in the story behind Notion Habit Heroes, was that "no errors" is not the same as "working". After an email outage I did not notice for three months, monitoring became its own feature area. A daily job compares every email the app believes it sent against what the mail provider actually delivered. A nightly job verifies that each user's sync really happened. An hourly scan clusters new production errors straight into my todo list.

The same distrust applies to my own dependencies. Updates arrive as merge requests from a bot: small patches merge automatically once the test suite passes, bigger upgrades wait for a human. Before each release, about fifty end-to-end tests drive a real browser through the real app, with Notion's API replaced by a local mock so no test ever touches real user data.

Why tell you this

Partly because I enjoy it. Mostly because trust is the actual product here. You connect a workspace that may hold your journal, your projects, your whole life admin; the least I can do is show you the machinery. The app only ever sees the pages you explicitly share with it during the Notion connect step, which in practice is one habit database.

If your habits already live in Notion, here is how it works. Everything, including competitions with friends, is on the free plan, so create an account and let the nightly sync surprise you tomorrow morning.