Internal tools2026

Replacing Notion with a tool built for one business

The dashboard I run LzCtrl from: projects, releases, tasks, content, and analytics, on real-time Firestore with a drag-and-drop board and an editor that round-trips markdown.

Built forLzCtrl
RoleDesigner and engineer
Internal Admin dashboard
What Notion could not do

Everything was in Notion, spread across databases that never quite matched how the work actually ran. Releases lived apart from the projects they belonged to, tasks lived apart from both, and keeping them related was manual effort that quietly stopped happening.

The parts that mattered most were the ones a generic tool could not do: drafting a newsletter in the format it actually sends in, and seeing growth numbers that Meta deletes after thirty days.

How I modelled it

I modelled the business rather than the tool. Projects own releases, releases own tasks, and content is a first-class thing with its own drafting surface, so nothing has to be cross-referenced by hand.

The whole app runs on real-time listeners instead of per-view queries. The dashboard is three subscriptions rather than a read per card, which is what makes it feel instant and keeps the bill near zero.

What it runs
  • Projects, releases, tasks, and groups as one connected model
  • A drag-and-drop task board
  • A rich-text editor that round-trips markdown, for blog and newsletter drafting
  • An Instagram growth dashboard with derived metrics and pace tracking
  • A triage dashboard with quick capture
  • Google sign-in gated on an allowlist enforced in the database rules
Architecture

Choices behind it

01

Counters that trade tidiness for speed

Counters are denormalised so the dashboard reads three listeners instead of a query per card. Every write that affects a counter goes through a batch, and a rename fans out across related documents. There is also a manual recalculate, because denormalised data eventually drifts and it is better to have the button than to pretend otherwise.

FirestoreArchitecture
02

Auth that costs nothing to check

Access is a literal allowlist in the security rules rather than a lookup in an admins collection. A lookup would bill a read on every rule evaluation, and this is a single-owner tool, so adding a person is one line and a deploy.

Firebase AuthSecurity
03

An editor that speaks the output format

Drafting happens in rich text but round-trips cleanly to markdown, so what gets written is what gets published, and the same content feeds both the blog pipeline and the newsletter renderer without a conversion step in between.

TipTapContent
04

Analytics that outlive the source

Meta drops follower history after thirty days. The growth tables keep it, so the dashboard can show pace against a goal over months rather than only showing the last few weeks.

AnalyticsData retention
What it gives me

I run the whole business from it: what is shipping, what is blocked, what is drafted, and how the audience is growing, in one place that matches how the work actually happens.

It is the clearest example of what I build when a company asks for an internal tool, because I had exactly one user to satisfy and no excuse for it being awkward.

Built with
Frontend
ReactJSTypeScriptViteTailwindReactJS Router
Infrastructure
Firebase FirestoreFirebase Auth
Services
TipTapdnd-kit