Huble
Time tracking and invoicing for teams. I lead development across the whole product, rebuilt the desktop tracker in Rust (130 MB down to 30 MB, with offline sync), and built its Paddle billing, real-time backend, and security-first infrastructure.
Visit gethuble.com ↗
Overview
Huble is time tracking and invoicing for teams. Start a timer, and Huble turns it into a timesheet, an invoice, and a clear picture of where the team’s time goes. It’s used across the organization and offered to other teams as a product.
I lead its development, and I’ve worked on every part of it: the backend, the web app, the infrastructure, the desktop tracker, and the website. It all lives in one Turborepo monorepo.
Desktop tracker
The desktop tracker is where the timer lives: one-click tracking, idle detection, and every session tied to a project and task. Tracking works offline too: sessions are stored locally in SQLite and sync to the backend as soon as the machine is back online, so no hours are lost to a dropped connection. Sign-in happens in the browser using OAuth with PKCE, so the tracker never handles anyone’s password.
I built the original cross-platform tracker in Electron, then led its full migration to Tauri with Rust:
- Installer size dropped from 130 MB to 30 MB, 77% smaller
- OS integration moved from C++ to Rust. The Electron app relied on separate C++ scripts to talk to the operating system; that code now runs natively in Rust, inside the app
- Better performance, lower memory use, and stronger security, which matters for an app that runs all day on people’s machines
Backend
The backend is built with NestJS on PostgreSQL. It runs in Docker on Hetzner machines, behind an Nginx reverse proxy. Underneath, everything sits on one record: log an hour, and the project, the timesheet, and the invoice all reflect it. The backend is what keeps those connected.
- Queues: background work runs through BullMQ, backed by Redis so it scales with load
- Real time: the web and desktop apps talk to the server over both HTTP and Socket.IO, so things like who’s tracking right now update live
- Billing: I built the Paddle subscription integration. Its webhooks handle trial-to-paid upgrades and cancellations, keeping each team’s plan in sync
Web app
The web app is built with Next.js and deployed on Vercel. The UI uses shadcn/ui components, customised with Tailwind CSS so they look like Huble rather than a component library.
Security-first infrastructure
PostgreSQL and Redis run on a private machine with no public IP. The backend reaches them only through a NAT gateway, so neither is ever exposed to the internet.
I also set up self-hosted Linux runners for CI/CD, which reduced pipeline costs while keeping builds fast and reliable.
Website
I also worked on gethuble.com, the website where teams find Huble and start a trial.
Analytics and consent
I recently added product analytics to Huble, with consent built in from the start:
- CookieYes handles cookie consent, so visitors choose what gets tracked
- Google Analytics 4, deployed through Google Tag Manager, tracks the key moments in the funnel, like signing up and starting a trial
The goal is the gap between those events and a paid plan. When someone signs up but doesn’t upgrade, the team can follow up by email, either to help them get value from Huble or to learn why they stopped using it.
Dayonai →
Secure virtual workstations on AWS, fully defined in Terraform. Adding someone to Google Workspace gives them a locked-down machine and the right AWS permissions for their role, automatically, all inside a private VPC with keyless OIDC deployments.