For the Dream OpsommingspuntInzichten

Waarom we onze €700/jaar projectmanagement tool weggooiden en zelf een betere bouwden

Een deep-dive in de techstack achter 'Dream Moments' (Next.js, Tauri, Rust & Supabase).

K

Kutlu Taskin Tuna

3 juni 2026 · 6 min leestijd

Waarom we onze €700/jaar projectmanagement tool weggooiden en zelf een betere bouwden
Moderne en robuuste cloud architectuur

In dit artikel bespreken we

De overstap van een externe tool naar een zelfgebouwde hybride applicatie.
Hoe we Zero Latency bereikten met Zustand, IndexedDB en Optimistic Updates.
De kracht van echte native OS integratie via Tauri en Rust.

Waarom we onze €700/jaar projectmanagement tool weggooiden en zelf een betere bouwden

Een deep-dive in de techstack achter "Dream Moments" (Next.js, Tauri, Rust & Supabase)

Als innovatief communicatiebureau dat expertise, skills en tijd verkoopt, liepen we bij For the Dream tegen een zeer herkenbaar probleem aan: het vinden van een eenvoudige tool om onze prestaties overzichtelijk te registreren en te declareren. Aan opties geen gebrek—denk aan ClickUp, Monday, Teamleader, et cetera—maar je wordt in dat soort applicaties vaak gedwongen om allerlei zware en onnodige extra pakketten af te nemen, puur om je basale urenregistratie-functie te behouden.

Zo gebruikten we zelf al drie jaar lang ClickUp, waarvoor we jaarlijks rond de €700 afrekenden. Het ironische van deze doorlopende kostenpost was dat we eigenlijk al intensief gebruikmaakten van Google Workspace. En laten we eerlijk zijn: met Google Workspace heb je in de basis al een extreem robuuste projectmanagement tool in handen. Tussen Docs, Google Tasks, Agenda en Mail heb je vrijwel alles wat je nodig hebt om een project succesvol van A tot Z te sturen. Zeker nu Google hun omgeving in rap tempo blijft doorontwikkelen, zoals met de recente Workspace drops en de krachtige integratie van AI in hun zakelijke tools.

Er miste binnen Google Workspace maar één cruciaal element voor ons bedrijfsmodel: een simpele, feilloze timetracker.

Waarom honderden euro's betalen voor de overtollige features van logge projectmanagement-platformen, als we uitsluitend een snelle urenregistratie-schakel nodig hadden ter aanvulling op Google Workspace? Als innovatief team doen we dan wat we het liefste doen: we bouwen die ontbrekende schakel zélf.

In deze blogpost neem ik je mee in de architectuur, de techstack en de development keuzes achter Dream Moments: onze eigen bliksemsnelle, hybride desktop- en web-applicatie die dit gat in onze workflow perfect (en zonder onnodige overhead) opvult.

Zelf de snelheid ervaren?

Benieuwd hoe zero latency urenregistratie voelt? We hebben Dream Moments opengesteld. Er is een gratis versie beschikbaar!

Start gratis met Dream Moments


De architectuur: een moderne, hybride stack

Moderne en robuuste cloud architectuur

We wilden geen simpele webapp bouwen die in een van je 50 open tabbladen verdwijnt. We wilden een tool die aanvoelt als een robuust verlengstuk van je besturingssysteem, maar met de ontwikkel-snelheid en flexibiliteit van het web.

Onze gekozen stack:

  • Frontend & App Framework: Next.js 16.2 (App Router) & React 19
  • State Management: Zustand v5 gecombineerd met IndexedDB (idb-keyval)
  • Styling & UI: Tailwind CSS v4, Framer Motion, met een custom design system (focus op glassmorfisme en animated mesh-backgrounds).
  • Desktop Wrapper: Tauri v2 (Rust) voor macOS en Windows native executables.
  • Backend & Database: Supabase (PostgreSQL) met Realtime CDC, aangestuurd via Next.js Serverless API routes.
  • Payments & Mails: Stripe & Resend.

Een beknopt overzicht van hoe deze lagen met elkaar praten:

  • Client-Side: De Next.js React frontend communiceert direct met de lokale Zustand store en IndexedDB. Op desktopniveau is er tweerichtingscommunicatie via Tauri IPC (Inter-Process Communication) voor native functionaliteiten.
  • Data & Services Layer: Supabase Realtime (WebSockets) pusht wijzigingen direct naar de client, terwijl veilige mutaties, betalingen (Stripe) en mails (Resend) via Next.js Serverless API Routes verlopen (welke de Supabase RLS tijdelijk bypassen met een service role wanneer dat strikt nodig is).

Waarom voelt de app zo ongelooflijk snel? (Zero latency architectuur)

De belangrijkste eis was snelheid. Een timer starten moet instant gebeuren, zonder te wachten op laadspinners. We bereikten deze ultieme UX door drie cruciale architecturale keuzes:

1. Single-query bootstrap & IndexedDB cache

Wanneer de app opstart, wachten we niet op een reeks losse API-calls (haal user, haal projecten, haal taken, etc.). We gebruiken een /api/v1/bootstrap route die in één geaggregeerde PostgreSQL-query alle benodigde data in één JSON-payload terugstuurt.

Nog belangrijker: de volledige Zustand store wordt lokaal gecached in IndexedDB. Bij het openen van de app laadt de UI direct de lokale state in. Je kunt direct aan de slag; het ophalen van nieuwe data vanaf de server gebeurt onzichtbaar op de achtergrond.

2. Optimistic updates over de hele linie

Als een gebruiker een taak aanmaakt of een timer start, wachten we de database niet af. Zustand updatet de lokale interface onmiddellijk met tijdelijke ID's (bijv. temp-task-uuid). Op de achtergrond vuurt het HTTP-verzoek af.

  • Succes? Zustand vervangt geruisloos de tijdelijke ID voor de echte database-ID.
  • Faalt het (bijv. offline)? Dan rollen we de lokale state onzichtbaar terug. Het resultaat is een interface die geen milliseconde hapert.

3. Supabase realtime (PostgreSQL CDC)

We maken gebruik van Supabase's Change Data Capture via WebSockets. Verandert een collega de omschrijving van een taak of de status van een project? Dan wordt die mutatie direct vanuit de PostgreSQL database naar de aangesloten clients gepusht. Geen polling of page refreshes nodig.


De magie van Tauri: echte native OS integratie

Abstracte weergave van schone code en technologische integratie

Waar reguliere web-apps vaak tekortschieten, is in de naadloze integratie met het besturingssysteem. Door Tauri v2 (met Rust als backend) in te zetten om onze Next.js app te wrappen, kregen we toegang tot low-level OS features, resulterend in een echte native feel:

  • De Menubalk (Tray) Integratie: Onze React TimerContext tikt elke seconde en roept via de IPC-bridge een custom Rust command aan (update_tray_title). Rust past direct de menubalk aan. Zo zie je altijd 00:04:12 in je macOS menubalk staan, en kun je de timer direct vanuit de tray bedienen.
  • Window Close Hijacking: Klik je op de rode sluitknop van het venster? In plaats van de app te killen, onderschept de Rust backend dit event (WindowEvent::CloseRequested), voorkomt dat het proces sluit (api.prevent_close()), en verbergt simpelweg het venster. De timer blijft veilig doortikken op de achtergrond.
  • De Zwevende Picture-in-Picture Widget: We bouwden een specifieke /widget route. In Tauri is dit geconfigureerd als een transparant, randloos venster met alwaysOnTop: true. Omdat dit kleine venster dezelfde Zustand (IndexedDB) store deelt als de hoofdapp, lopen timer en acties overal perfect synchroon.

Robuuste backend: security, fallbacks & impersonation

Snelheid en UX zijn prachtig, maar zonder data-integriteit heb je niets aan een timetracker.

Slimme fallbacks voor tijdsregistraties

Een klassiek probleem met timetrackers: je start in een haast een timer, stopt hem later, maar je was vergeten een project of merk te selecteren. Vaak gaat die data verloren door een database-error. Wij losten dit op de backend op: ontvangt de API een payload zónder geselecteerd merk of project? Dan crasht hij niet. Er wordt volautomatisch een 'Persoonlijk merk' en een 'Individueel project' aangemaakt, gebaseerd op je gebruikersnaam. Zo gaat er nooit één gewerkte seconde verloren.

Row level security (RLS)

Security wordt niet overgelaten aan de grillen van API-code, maar wordt afgedwongen direct op databaseniveau. Onze multi-tenant architectuur maakt gebruik van Supabase RLS (Row Level Security). Via SQL-policies wordt ervoor gezorgd dat gebruikers fysiek nooit records kunnen inzien of wijzigen die niet bij hun brands of projects horen, zelfs niet als iemand via de commandline de database probeert te bevragen.

Clean impersonation architectuur

Als admin wil je gebruikers soms direct kunnen helpen door mee te kijken in hun omgeving. In plaats van in elke API-route een "if admin then..." check in te bouwen, hebben we dit gecentraliseerd met een interceptor: Zodra een admin een gebruiker wil impersoneren, overschrijft de globale AuthProvider de window.fetch. Elk uitgaand verzoek krijgt automatisch de header x-impersonate-user: <id>. Onze Next.js middleware vangt dit op, controleert of de verzoeker daadwerkelijk admin-rechten heeft, en voert de database-query's uit onder de gemaskeerde identiteit. Transparant en extreem veilig.


Conclusie

Is het verstandig om zélf een tool te bouwen ter vervanging van een SaaS-abonnement van €700 per jaar? Voor de meeste bedrijven is off-the-shelf software de beste keuze.

Maar als development agency gaf het ons de kans om een tool te ontwikkelen die 100% is afgestemd op onze processen, zonder enige compromis op het gebied van UX of performance. De combinatie van Next.js voor razendsnelle UI-ontwikkeling, Tauri & Rust voor native performance en Supabase voor realtime cloud sync bewijst wat ons betreft de gouden standaard voor moderne app development anno 2026.

We hebben eindelijk de timetracker die we altijd al wilden hebben.

Klaar om je logge tool te vervangen?

Probeer de gratis versie van Dream Moments en ervaar zelf de snelheid van native integratie en bliksemsnelle timetracking.

Probeer Dream Moments Gratis

Zelf de switch gemaakt van een betaalde SaaS naar een in-house oplossing? Ik hoor graag jullie ervaringen in de reacties!

Klaar om je legacy te bouwen?

Ontvang elke week scherpe strategieën, praktijkvoorbeelden en nieuwe denkkaders. Direct in je inbox.

Geen spam. Uitschrijven kan altijd.