Mennova
Alle cases

MijnDakje

SaaS & automatisering

In deze case laat ik zien hoe ik MijnDakje heb gebouwd: een huurwoning-zoekplatform met automatisch reageren.

Het platform houdt bijna dertig verhuursites in de gaten, vergelijkt nieuwe woningen met het zoekprofiel van de gebruiker en kan voor Pro-gebruikers direct op een woning reageren.

Beeld van MijnDakje
Type
SaaSWebapplicatieBackend-APIAutomatiseringAdmin-dashboard
Mijn rol
Software-architectFull-stack developerProduct ownerIntegraties
Tijdlijn
2025 - heden
Opdrachtgever
Eigen product

Uitdagingen en doelen

Wie in Nederland een huurwoning zoekt, moet tientallen sites tegelijk in de gaten houden. Elke makelaar heeft een eigen website, eigen filters en een eigen reactieformulier, en in een krappe huurmarkt heeft wie als eerste reageert de beste kans. Ik heb daarom gekozen voor één zoekprofiel dat automatisch met alle bronnen wordt vergeleken, met meldingen per e-mail en push en automatisch reageren als betaalde functie.

Het doel: een huurwoning-zoekplatform met automatisch reageren, zodat woningzoekers geen nieuwe woning meer missen en altijd bij de eersten zijn.

Browser met alle gevonden huurwoningen en filters op prijs en oppervlakte, en een telefoon met sollicitaties bij verschillende makelaars.
Woningen van alle bronnen staan op één plek, en de gebruiker ziet per makelaar waar al op is gereageerd.

Architectuur

De architectuur is opgebouwd rond een aantal uitgangspunten:

  • 01Éen strategie per makelaar
  • 02Web en Jobs gescheiden
  • 03Heldere lagen
  • 04Gevoelige data versleuteld

De Next.js-webapp praat met een ASP.NET Core API, terwijl een aparte Jobs-host met Hangfire op de achtergrond scrapet, matcht en reageert. Beide delen één MariaDB-database.

Het diagram toont de onderdelen en de externe diensten waarmee ze werken.

Diagram met de webapp en het beheerdashboard links, de API, de Jobs-host en MariaDB in het midden en verhuursites, Stripe, Nominatim, e-mail en push en OpenAI rechts.
De API bedient de gebruikers; de Jobs-host doet het zware werk met de verhuursites op de achtergrond.

Technieken

De backend is gebouwd in .NET met ASP.NET Core, Entity Framework Core en MariaDB, opgedeeld in domein-, applicatie- en infrastructuurlagen.

Hangfire draait scrapen, matchen en automatisch reageren als geplande jobs; elke makelaar wordt apart afgehandeld, zodat een storing bij één site de rest niet raakt en na herhaalde fouten een melding volgt.

Een optionele controle met OpenAI vergelijkt prijs en oppervlakte met de letterlijke tekst op de advertentie, zodat foutieve gegevens niet bij de gebruiker belanden.

De webapp is gemaakt met Next.js, React, TypeScript en Tailwind CSS, in het Nederlands en Engels en met een donkere modus. Zoekgebieden kies je op een kaart met Leaflet en OpenStreetMap, en abonnementen lopen via Stripe. Alles draait in Docker-containers achter Traefik.

  • .NET
  • ASP.NET Core
  • MariaDB
  • Hangfire
  • Playwright
  • Next.js
  • React
  • TypeScript
  • Tailwind CSS
  • Stripe
  • OpenAI
  • Leaflet
  • OpenStreetMap
  • Docker
  • Traefik
  • OpenTelemetry

Agile / Scrum

Ontwikkelproces

Ik bouw MijnDakje alleen, feature voor feature vanuit een genummerde takenlijst. Elke taak krijgt een plan, tests vooraf en een eigen commit, en AI-codeeragents helpen mij bij onderzoek, review en testwerk.

Daarnaast wordt er continue getest met daadwerkelijke gebruikers die woningzoekende zijn, hierdoor ontvang ik feedback en verwerk ik deze in de applicatie.

Sprint01en weer opnieuw ↻
  1. Planning
  2. Analyseren
  3. Ontwerpen
  4. Implementeren
  5. Testen
  6. Onderhouden

Implementatie

Elke makelaar heeft een eigen strategie voor de lijstpagina, de detailpagina en het reactieformulier, en een resolver kiest de juiste.

Een nieuwe verhuursite toevoegen raakt daardoor de rest van het systeem niet. Zo groeide het platform stap voor stap van vier naar +50 bronnen.

Code-editor met C#-code die de woningkaarten van de NMGWonen-website uitleest en omzet naar woningobjecten.
Elke makelaar heeft een eigen, kleine strategieklasse; de gedeelde basisklasse regelt het laden van de pagina.
Terminalvenster met een geslaagde dotnet test-run van 104 tests voor matching, makelaarsformulieren en Stripe.
Tests voor de matchingscore, de formulieren per makelaar en de abonnementen draaien in minder dan een seconde.

Testen

De backend heeft ruim zeshonderd unit- en integratietests met xUnit en Moq, onder meer voor de matchingscore, de formulieren per makelaar en de Stripe-abonnementen. De frontend wordt getest met Vitest en Testing Library, en bijna honderd end-to-end tests met Playwright doorlopen de belangrijkste flows, van registreren tot betalen.

Zo valt een wijziging die een bestaande flow breekt op voordat hij live gaat.

Continuous development & integration

Lokaal start .NET Aspire de hele omgeving met één commando: database, geocoder, testmailserver, API, jobs en webapp. Zo test ik elke wijziging in een opstelling die dicht bij productie ligt. Voor een release draaien de backend-, frontend- en end-to-end tests lokaal.

API, Jobs-host en webapp worden als Docker-containers gebouwd en draaien achter Traefik, dat HTTPS afhandelt. Database-migraties worden bij het opstarten automatisch toegepast. Het Hangfire-dashboard en een geplande gezondheidscheck per makelaar laten zien of scrapers en jobs goed draaien.

Stroomschema van een wijziging via lokale tests met xUnit, Vitest en Playwright naar een Docker-build, uitrol, migraties en een controle van de health-endpoints.
Releases gaan met Docker Compose; gaat er iets mis, dan zet ik de vorige build terug.

01 / 03

Screenshots

Het zoekgebied kies je door op de kaart te klikken en de straal te verschuiven.

mijndakje.mennova.nl

Verder kijken

Meer case studies

Bekijk alle cases

Een goed begin

Heb jij een digitaal vraagstuk dat verder mag?

Vertel me waar je aan werkt. Dan verken ik samen met jou wat er technisch nodig is om vooruit te komen.

Plan een kennismaking
vraag.tsroute.tscontact.ts

// Van vraag naar richtingconst route = { inzicht: true, richting: true, volgendeStap: 'helder',}plan(route)[klaar] tijd voor een kennismaking.