Technologiestack
HansaChat is een Europese bedrijfschat met een operationele laag voor buitendienstteams, ontworpen, gebouwd en beheerd door één persoon. Deze pagina laat zien waarmee elk onderdeel is gebouwd en waarom daarvoor is gekozen.
Versies en aantallen gecontroleerd in oktober 2026.
Geteld in de repositories
- ConnectRPC-services met 179 RPC’s, allemaal gedefinieerd in Protobuf
- 18
- Go-binaries uit één codebase: API, worker, outbox-relay, beheer
- 4
- platforms vanuit één client: web, macOS, Windows, Linux, iOS, Android
- 6
- talen op de openbare website
- 22
- interfacetalen in de app
- 23
- Playwright-end-to-end-specs op een geïsoleerde stack
- 70
Hoe de onderdelen samenhangen
Drie applicaties delen één edge en één cluster. De website is eigenaar van facturering en het werkruimteregister, de Go-backend van alles binnen een werkruimte, en de web-app praat met de backend via gegenereerde ConnectRPC-clients.
Clients
Browser
Website en web-app
Tauri
Desktop- en mobiele shells
hansa CLI
Scripts en agents
Edge
Bunny.net CDN
TLS, caching, DDoS-bescherming
IONOS Managed Kubernetes, Duitsland
Traefik
Ingress voor elke applicatie
Web-app Vue + Vite
Statische Vue-build
Chat-API
Go met ConnectRPC
- Worker
- Outbox-relay
Website Laravel + FrankenPHP
Facturering, register, provisioning
NATS JetStream
Duurzame commando’s en events
Centrifugo
WebSocket-distributie
Valkey Sentinel + HAProxy
Cache, aanwezigheid, sessies
LiveKit
Media voor gesprekken
Beheerde data bij IONOS
MariaDB
Eén database per werkruimte plus een centraal register
Object Storage S3
Bestanden en avatars
Externe diensten
ElevenLabs · LLM · Clef
Transcriptie, vertaling, triage
Creem · EmailLabs
Betalingen en e-mail
Buiten het cluster
Cloudflare Workers D1
Externe statuscontroles
Bunny Storage restic
Versleutelde back-ups in Frankfurt en Stockholm
De route van één bericht
- De client roept de berichtendienst aan via ConnectRPC.
- De API accepteert het verzoek pas nadat NATS JetStream het commando duurzaam heeft opgeslagen.
- Een worker schrijft het bericht en een outbox-event in één transactie naar de database van de werkruimte.
- De outbox-relay publiceert het vastgelegde event naar NATS en Centrifugo.
- Elke geopende client ontvangt het via WebSocket; na een onderbreking laden clients de gezaghebbende status opnieuw vanuit de API.
Chatbackend
Alles wat binnen een werkruimte gebeurt, draait in Go: berichten, kanalen, bestanden, gesprekken, realtime, imports en het operationele pakket voor de schoonmaakbranche. De website komt nooit aan werkruimtegegevens.
- Go 1.26
-
Vier binaries uit één modulaire codebase: de API, de berichtenworker, de outbox-relay en een afgeschermd beheercommando. Ze worden geleverd als statische binaries in één kleine image.
Waarom
Een sterke standaardbibliotheek, voorspelbare prestaties en eenvoudige concurrency passen bij een backend die bestaat uit langlopende workers. Eén taal voor de hele werkruimtekern houdt die onderhoudbaar voor één persoon.
- ConnectRPC + Protobuf connect-go 1.20 · buf 1.71
-
18 services en 179 RPC’s zijn gedefinieerd in Protobuf. buf genereert de Go-server en de TypeScript-clients met lokale plug-ins, zodat geen enkel schema de machine verlaat.
Waarom
Eén contract bedient de web-, desktop-, mobiele en opdrachtregelclients. Er zijn geen handgeschreven HTTP-paden of handmatig geparste responses, en een contractwijziging verschijnt als compileerfout in plaats van als runtimefout.
- Eén database per werkruimte MariaDB · sqlc
-
Elke werkruimte krijgt een eigen fysieke MariaDB-database. De API bepaalt de werkruimte aan de hand van het domein en opent de bijbehorende pool; workers bepalen die zelf opnieuw en vertrouwen nooit een databasenaam uit een wachtrijbericht. Query’s zijn gewone SQL, die sqlc compileert naar getypeerde Go-code.
Waarom
Isolatie is structureel in plaats van een filter op elke query. Export, import, herstel en verwijdering werken per bedrijf.
- NATS JetStream 2.10
-
Duurzame streams voor commando’s, jobs en events, plus een dead-letter-stream. Schrijfacties voor berichten lopen in 64 geordende partities.
Waarom
Een bericht wordt pas geaccepteerd na een duurzame bevestiging. Berichten in één kanaal blijven op volgorde, terwijl onafhankelijke kanalen parallel worden verwerkt.
- Transactionele outbox
-
Domeinrecords en het uitgaande event worden in dezelfde transactie vastgelegd. Een relay publiceert vastgelegde events naar NATS en Centrifugo, ontdubbeld op event-ID, en registreert fouten om ze opnieuw te proberen.
Waarom
Geen verloren of spookevents wanneer een proces stopt tussen het schrijven naar de database en het publiceren.
- Centrifugo v5
-
WebSocket-levering van berichten, aanwezigheid, typindicatoren en gespreksstatus. Clients abonneren zich met kortlevende tokens per kanaal, die de API pas uitgeeft na controle van het lidmaatschap van de werkruimte.
Waarom
Een aparte realtimeserver houdt langlevende verbindingen buiten het API-proces, en elk token noemt zowel werkruimte als gebruiker, zodat identiteiten uit afzonderlijke databases niet kunnen botsen.
- S3-compatibele objectopslag aws-sdk-go-v2
-
Bestanden en avatars worden opgeslagen in IONOS Object Storage in de EU en verstrekt via kortlevende ondertekende links.
Waarom
Bestandsopslag schaalt onafhankelijk van de databases en is aan de serverzijde versleuteld in rust.
- LiveKit 1.9
-
Een zelf gehoste WebRTC-mediaserver voor gesprekken in directe berichten en audiogerichte kanaalgesprekken met camera en scherm delen.
Waarom
Open source en zelf te hosten, zodat de media van gesprekken draaien op infrastructuur die HansaChat zelf beheert.
- ElevenLabs Scribe
-
Spraak-naar-tekst voor spraakberichten. Het transcript wordt aan het bericht gekoppeld en is doorzoekbaar en vertaalbaar zoals elke andere tekst.
Waarom
Buitendienstploegen praten meer dan ze typen.
- LLM-vertaling
-
Vertaling per lezer via een OpenAI-compatibele API. Elk bericht wordt op verzoek vertaald, één keer per doeltaal gecachet en overgeslagen als de lezer de taal al spreekt.
Waarom
Een meertalige ploeg werkt in één gesprek terwijl elk lid in de eigen taal leest. De provider blijft vervangbaar achter één interface.
- Cloudflare Clef
-
Een beslismodel classificeert operationele berichten op categorie, urgentie en betrouwbaarheid. Het geeft kansen terug voor vaste vragen, geen gegenereerde tekst. Momenteel in een pilotfase.
Waarom
Er is geen vrije tekst om te parsen. Leidinggevenden zien wat aandacht nodig heeft; ernaar handelen blijft altijd een menselijke beslissing.
- go-pdf 0.9
-
A4-urenstaten en servicerapporten worden op de server gegenereerd.
Waarom
Een pure Go-bibliotheek houdt de backend-image klein en vrij van een headless browser.
- Sentry + slog
-
Fouten en traces gaan naar Sentry, logs zijn gestructureerde JSON uit de standaardbibliotheek en workers stellen metrics beschikbaar in het Prometheus-tekstformaat.
Waarom
Weinig bewegende delen om te beheren, en elke fout komt binnen met de bijbehorende context.
Apps en CLI
Eén Vue-client bedient het web en wordt door Tauri verpakt voor desktop en mobiel. De opdrachtregelclient gebruikt dezelfde openbare API als de apps.
- Vue 3 + TypeScript Vue 3.5 · TS 5.9 · Pinia 3
-
Eén client met 118 single-file components, Pinia-stores, vue-router en vue-i18n in 23 interfacetalen, getest met Vitest.
Waarom
Een volwassen, leesbaar componentmodel en strikte TypeScript maken een grote client beheersbaar voor een heel klein team.
- Vite + Tailwind CSS Vite 8 · Tailwind 4
-
De buildtool en de stylinglaag: Tailwind CSS 4 met een licht en een donker thema.
Waarom
Snelle builds en designtokens die hetzelfde gedocumenteerde palet volgen als de website.
- Tauri 2.10
-
Verpakt dezelfde webclient voor macOS, Windows, Linux, iOS en Android, met systeemeigen meldingen, deeplinks en ondertekende desktopupdates.
Waarom
Eén interface overal, met de webview van het systeem in plaats van een browser-engine die in elke app wordt meegeleverd.
- Gegenereerde Connect-clients connect-web 2.1 · protobuf-es 2
-
TypeScript-clients die worden gegenereerd uit de Protobuf van de backend en naar de web-app worden gekopieerd. Ze worden nooit met de hand bewerkt.
Waarom
Een contractwijziging wordt een typefout in de client in plaats van een verrassing in productie.
- centrifuge-js + livekit-client 5.7 · 2.20
-
De clientbibliotheken voor Centrifugo-realtime en LiveKit-gesprekken.
Waarom
Herverbinden, herstel en mediaverwerking komen van de projecten die ook de servers bouwen.
- TipTap 3.22
-
De berichteneditor, met vermeldingen, links en codeblokken met syntaxiskleuring.
Waarom
Een gestructureerde editor in plaats van foutgevoelige stringverwerking.
- hansa CLI Go 1.26 · Cobra
-
Een stateless opdrachtregelclient voor mensen, scripts en LLM-agents. Standaard JSON-uitvoer, inloggegevens in de sleutelhanger van het besturingssysteem en releasechecksums ondertekend met Minisign.
Waarom
Hij gebruikt dezelfde openbare API als de apps. De Protobuf-contracten worden gekopieerd uit de backend en vastgezet met SHA-256-hashes, zodat afwijkingen in CI worden gedetecteerd.
Website, facturering en register
Laravel draait de openbare website, de klantdocumentatie, de checkout, abonnementen en het centrale register van werkruimten. Het maakt een werkruimte aan door de Go-backend aan te roepen via geauthenticeerde HTTP, zonder gedeelde code en zonder gedeelde wachtrijen.
- Laravel + PHP Laravel 12 · PHP 8.5
-
De openbare website, klantdocumentatie, checkout, abonnementen, kortingscodes, levenscyclusmeldingen en het centrale register van werkruimten en domeinen.
Waarom
Facturering, e-mail, planning, wachtrijen en formulieren zijn waar Laravel het sterkst is. De chat blijft in Go, en de grens daartussen is één geauthenticeerde HTTP-interface.
- FrankenPHP 1.13
-
De PHP-applicatieserver in de containerimage, gebouwd op een gedeelde basisimage die PHP, de extensies en tooling vastpint op digest.
Waarom
Eén proces bedient de applicatie, en het opnieuw bouwen van dezelfde commit levert dezelfde runtime op.
- Blade + Alpine.js + Tailwind CSS Alpine 3.15 · Tailwind 3.4 · Vite 7
-
Server-side gerenderde pagina’s met kleine Alpine.js-componenten, gestyled met Tailwind CSS en gebundeld door Vite.
Waarom
Contentpagina’s laden snel zonder een single-page-app-framework mee te leveren.
- 22 talen
-
Elke openbare pagina bestaat in 22 EU-talen, met taalvoorvoegsels in de URL’s, hreflang-links en een gelokaliseerde sitemap. Een test faalt als een taal een sleutel mist of Engelse tekst bevat.
Waarom
Een Europees product hoort vanaf de eerste pagina leesbaar te zijn in de taal van de koper.
- Creem
-
Checkout, belasting, facturen en abonnementen, gesynchroniseerd via ondertekende webhooks.
Waarom
Betaling, belasting en facturatie liggen bij een gespecialiseerde provider, terwijl de website een afgestemde kopie van elk abonnement bijhoudt.
- EmailLabs
-
Transactionele en service-e-mails zoals uitnodigingen, wachtwoordlinks en meldingen.
Waarom
Een EU-e-mailprovider voor een EU-product.
- Pest 4.4
-
Meer dan 130 testbestanden dekken routes, facturering, provisioning, vertalingen en SEO, inclusief browsertests.
Waarom
Snelle, leesbare tests die bij elke wijziging draaien.
Platform en beheer
Productie en preview draaien bij IONOS in Duitsland. Elke applicatie wordt geleverd als containerimage met een eigen Helm-chart en wordt uitgerold via een handmatig gestarte GitLab-job.
- IONOS Managed Kubernetes
-
Productie- en previewclusters, beheerde MariaDB en S3-compatibele Object Storage, allemaal beheerd door een Duitse provider in Duitsland.
Waarom
Een Europese provider onder EU-jurisdictie, niet de EU-regio van een niet-Europese cloud.
- Helm + Traefik
-
Elke applicatie levert een eigen chart. Traefik routeert verkeer binnen het cluster, en migraties van werkruimtedatabases draaien als hook vóór elke uitrol van de backend.
Waarom
Elke uitrol is geversioneerd, herhaalbaar en eenvoudig terug te draaien.
- Bunny.net
-
CDN, DNS en DDoS-bescherming vóór het cluster, en de opslag voor versleutelde back-ups.
Waarom
Een Europees bedrijf beheert de edge en bewaart de back-upkopieën, zodat geen van beide afhankelijk is van een niet-Europese cloud.
- Valkey + Sentinel + HAProxy Valkey 9.1
-
Drie replica’s met Sentinel-failover en een HAProxy-proxy die altijd naar de huidige primary wijst. Het ondersteunt caching, sessies, aanwezigheid en de realtimebroker.
Waarom
Een failover vereist geen wijziging in de applicatie, omdat elke dienst met hetzelfde adres blijft praten.
- restic 0.18
-
Versleutelde databaseback-ups elke 6 uur naar twee EU-locaties, met wekelijkse integriteitscontroles en een geautomatiseerde maandelijkse hersteloefening.
Waarom
Een back-up telt pas als een herstel bewezen is.
- GitLab CI
-
Tests, imagebuilds en controles van Helm-charts draaien in CI. Uitrol naar preview en productie gebeurt via aparte, handmatig gestarte jobs.
Waarom
Automatisering doet het repetitieve werk; een mens beslist wanneer iets bij klanten terechtkomt.
Rond het product
De tools die een eenmansbedrijf observeerbaar, bereikbaar en uitlegbaar houden.
- Cloudflare Workers + D1
-
Een externe statuspagina die de app en de website elke vijf minuten controleert en incidenten vastlegt.
Waarom
Beschikbaarheid wordt gemeten van buiten de infrastructuur die ze beschrijft.
- Umami 3.2
-
Zelf gehoste webanalyse die pas draait nadat een bezoeker een toestemmingskeuze heeft gemaakt.
Waarom
Bezoekersgegevens blijven op de infrastructuur van HansaChat in plaats van een advertentienetwerk te voeden.
- Remotion 4.0
-
De productvideo’s worden door de end-to-end-testrunner opgenomen in de echte applicatie en in code samengesteld met een AI-voice-over.
Waarom
Als de interface verandert, wordt de video opnieuw gerenderd in plaats van opnieuw gefilmd.
- TwentyCRM + WireGuard
-
Een zelf gehost CRM dat alleen bereikbaar is via een privé-VPN.
Waarom
Verkoopgegevens zijn helemaal niet blootgesteld aan het openbare internet.
Ontwikkelpraktijken
De gewoonten waarmee één persoon een multi-tenantproduct levert zonder apart QA- of beheerteam.
Contracten worden gegenereerd, nooit met de hand geschreven
Protobuf is de enige bron voor de Go-server, de TypeScript-clients en de CLI. Generators zijn vastgepind op exacte versies, en de CLI legt de hash vast van elk contractbestand dat hij gebruikt.
Migraties houden een logboek bij
Elke werkruimtedatabase registreert welke migraties zijn toegepast. Een deployment-hook past alleen de ontbrekende toe en controleert na de uitrol opnieuw. De website behoudt haar oorspronkelijke basismigraties, zodat bestaande databases ze nooit twee keer uitvoeren.
End-to-end-tests op een geïsoleerde stack
Eén commando start de databases, NATS, Valkey, Centrifugo en objectopslag op vrije poorten, bouwt de Go-binaries, start de web-app en draait 70 Playwright-specs met een verse werkruimte voor elke test.
Tests op elke laag
478 Go-testfuncties, waaronder isolatietests met twee werkruimten, 109 Vitest-bestanden in de client en meer dan 130 Pest-bestanden op de website.
Vangrails in CI
Opmaakcontroles, een limiet van 1.000 regels per Go-bestand en tests van Helm-charts draaien in CI naast de testsuites.
Uitrol alleen na handmatige vrijgave
CI bouwt en test automatisch, maar uitrol naar preview en productie gebeurt via aparte handmatige jobs. Productie rolt een releasetag uit die pas wordt aangemaakt nadat de wijziging is gemerged.
Back-ups bewezen door herstel
Elke back-uprun wordt gemonitord, en een geautomatiseerde oefening herstelt de databases elke maand en valideert tabellen en aantallen rijen.
Eén designsysteem
De website en de app delen één gedocumenteerd palet, typografische schaal en componentregels, met een licht en een donker thema in de app.
AI-ondersteund, door mensen goedgekeurd
AI-codeeragents werken vanuit een instructiebestand in elke repository dat verwijst naar één centrale repository met ontwikkeldocumentatie. Herhaalbare workflows zoals de end-to-end-run zijn verpakt als agent-skills. Elke wijziging moet nog steeds dezelfde tests doorstaan, en uitrol blijft handmatig.
Informatiebeveiligingsbeheer in voorbereiding
HansaChat bereidt zich voor op ISO/IEC 27001-certificering met een risicoregister, een bewijsregister en een besluitenlog. HansaChat is vandaag niet gecertificeerd.
Wat deze pagina beweert en wat niet
Alles hierboven beschrijft wat vandaag is geïmplementeerd en is geteld in de bronrepositories. HansaChat claimt geen beveiligingscertificering. Berichttriage zit in een pilotfase, en pushmeldingen voor gesloten apps zijn nog niet live.
Vragen over de architectuur?
Engineers die HansaChat evalueren, krijgen direct antwoord van de persoon die het heeft gebouwd.