Task Manager
One codebase, two applications: desktop and PWA.
- Year
- 2026
- Status
- In production
- Stack
- TypeScriptTauri 2PWASupabasePostgreSQLpnpm workspacesCaddy
The problem
I wanted my tasks on my PC and on my phone, in sync, without handing their contents to a third-party service. And without writing the same business logic twice.
The architecture
A monorepo where the domain logic and the API client live in shared packages. The applications are just interfaces on top: they differ in navigation and feel, not in rules.
The decisions that matter
- 01
Dropping the Android app for a PWA
The Android app worked, but every fix meant rebuilding an APK and reinstalling it by hand. A PWA installed to the home screen covers both Android and iOS, updates itself, and removes an entire build chain. The Android code still exists — it just isn't used any more.
- 02
Deleting the API server
There was a custom backend with its own database at first. All it did was relay requests and enforce permissions — two things Postgres can do on its own. Replacing it with direct Supabase access, with the security rules written into the database, removed a whole service to maintain and monitor.
- 03
Permissions in the database, not in the code
Every row carries its own access rules at the Postgres level. A badly written client, or one modified by its user, still can't read someone else's tasks: the barrier isn't in the application, it's underneath it.
- 04
A deployment that's just a file copy
The web side is nothing but a folder of static files served by Caddy. Shipping a version means copying that folder — no container restart, no downtime for users.