Gå til teknologiindholdet
Tilbage til forsiden

Teknologistak

HansaChat er en europæisk virksomhedschat med et driftslag til teams i marken, designet, bygget og drevet af én person. Denne side viser, hvad hver del er bygget med, og hvorfor valget faldt på netop det.

Versioner og antal gennemgået i oktober 2026.

Optalt i repositorierne

ConnectRPC-tjenester med 179 RPC’er, alle defineret i Protobuf
18
Go-binærfiler fra én kodebase: API, worker, outbox-relay, administration
4
platforme fra én klient: web, macOS, Windows, Linux, iOS, Android
6
sprog på det offentlige websted
22
grænsefladesprog i appen
23
Playwright-end-to-end-specs på en isoleret stak
70

Sådan hænger delene sammen

Tre applikationer deler én edge og én klynge. Webstedet ejer fakturering og registret over arbejdsområder, Go-backenden ejer alt inde i et arbejdsområde, og webappen taler med backenden gennem genererede ConnectRPC-klienter.

Klienter

Browser

Websted og webapp

Tauri

Desktop- og mobilskaller

hansa CLI

Scripts og agenter

Edge

Bunny.net CDN

TLS, caching, DDoS-beskyttelse

IONOS Managed Kubernetes, Tyskland

Traefik

Ingress til hver applikation

Webapp Vue + Vite

Statisk Vue-build

Chat-API

Go med ConnectRPC

  • Worker
  • Outbox-relay

Websted Laravel + FrankenPHP

Fakturering, register, provisionering

NATS JetStream

Holdbare kommandoer og hændelser

Centrifugo

WebSocket-distribution

Valkey Sentinel + HAProxy

Cache, tilstedeværelse, sessioner

LiveKit

Opkaldsmedier

Administrerede data hos IONOS

MariaDB

Én database pr. arbejdsområde plus et centralt register

Object Storage S3

Filer og avatarer

Eksterne tjenester

ElevenLabs · LLM · Clef

Transskription, oversættelse, triage

Creem · EmailLabs

Betalinger og e-mail

Uden for klyngen

Cloudflare Workers D1

Eksterne statustjek

Bunny Storage restic

Krypterede backups i Frankfurt og Stockholm

Vejen for én besked

  1. Klienten kalder beskedtjenesten via ConnectRPC.
  2. API’et accepterer først anmodningen, når NATS JetStream har gemt kommandoen holdbart.
  3. En worker skriver beskeden og en outbox-hændelse til arbejdsområdets database i én transaktion.
  4. Outbox-relayet publicerer den committede hændelse til NATS og Centrifugo.
  5. Alle åbne klienter modtager den via WebSocket; efter et afbrud genindlæser klienterne den autoritative tilstand fra API’et.

Chat-backend

Alt, hvad der sker inde i et arbejdsområde, kører i Go: beskeder, kanaler, filer, opkald, realtid, importer og driftspakken til rengøringsbranchen. Webstedet rører aldrig data i arbejdsområderne.

Go 1.26

Fire binærfiler fra én modulær kodebase: API’et, besked-workeren, outbox-relayet og en sikret administrationskommando. De leveres som statiske binærfiler i ét lille image.

Hvorfor

Et stærkt standardbibliotek, forudsigelig ydeevne og enkel samtidighed passer til en backend bestående af langtkørende workers. Ét sprog for hele arbejdsområdekernen gør den vedligeholdelig for én person.

ConnectRPC + Protobuf connect-go 1.20 · buf 1.71

18 tjenester og 179 RPC’er er defineret i Protobuf. buf genererer Go-serveren og TypeScript-klienterne med lokale plugins, så intet skema forlader maskinen.

Hvorfor

Én kontrakt betjener web-, desktop-, mobil- og kommandolinjeklienterne. Der er ingen håndskrevne HTTP-stier eller manuel parsing af svar, og en kontraktændring viser sig som en kompileringsfejl i stedet for en fejl under kørsel.

Én database pr. arbejdsområde MariaDB · sqlc

Hvert arbejdsområde får sin egen fysiske MariaDB-database. API’et finder arbejdsområdet ud fra dets domæne og åbner den tilhørende pool; workers finder det selv igen og stoler aldrig på et databasenavn fra en købesked. Forespørgsler er almindelig SQL, som sqlc kompilerer til typet Go.

Hvorfor

Isolationen er strukturel i stedet for et filter på hver forespørgsel. Eksport, import, gendannelse og sletning fungerer pr. virksomhed.

NATS JetStream 2.10

Holdbare streams til kommandoer, jobs og hændelser samt en dead-letter-stream. Skrivninger af beskeder kører i 64 ordnede partitioner.

Hvorfor

En besked accepteres først efter en holdbar bekræftelse. Beskeder i samme kanal bevarer deres rækkefølge, mens uafhængige kanaler behandles parallelt.

Transaktionel outbox

Domænerækker og den udgående hændelse committes i samme transaktion. Et relay publicerer committede hændelser til NATS og Centrifugo, deduplikeret efter hændelses-id, og registrerer fejl til et nyt forsøg.

Hvorfor

Ingen tabte hændelser eller fantomhændelser, når en proces stopper mellem databaseskrivningen og publiceringen.

Centrifugo v5

WebSocket-levering af beskeder, tilstedeværelse, skriveindikatorer og opkaldsstatus. Klienter abonnerer med kortlivede tokens pr. kanal, som API’et først udsteder efter at have kontrolleret medlemskabet af arbejdsområdet.

Hvorfor

En dedikeret realtidsserver holder langlivede forbindelser ude af API-processen, og hvert token angiver både arbejdsområde og bruger, så identiteter fra separate databaser ikke kan kollidere.

S3-kompatibel objektlagring aws-sdk-go-v2

Filer og avatarer gemmes i IONOS Object Storage i EU og udleveres via kortlivede signerede links.

Hvorfor

Fillagringen skalerer uafhængigt af databaserne og er krypteret i hvile på serversiden.

LiveKit 1.9

En selvhostet WebRTC-medieserver til opkald i direkte beskeder og lydbaserede kanalopkald med kamera og skærmdeling.

Hvorfor

Open source og selvhostbar, så opkaldsmedier kører på infrastruktur, som HansaChat selv driver.

ElevenLabs Scribe

Tale til tekst for talebeskeder. Transskriptionen knyttes til beskeden og kan søges i og oversættes som al anden tekst.

Hvorfor

Medarbejdere i marken taler mere, end de skriver.

LLM-oversættelse

Oversættelse pr. læser via et OpenAI-kompatibelt API. Hver besked oversættes efter behov, caches én gang pr. målsprog og springes over, når læseren allerede taler sproget.

Hvorfor

Et flersproget hold arbejder i én samtale, mens hvert medlem læser på sit eget sprog. Udbyderen kan fortsat udskiftes bag én grænseflade.

Cloudflare Clef

En beslutningsmodel klassificerer driftsbeskeder efter kategori, hastegrad og konfidens. Den returnerer sandsynligheder for faste spørgsmål, ikke genereret tekst. I øjeblikket i pilotdrift.

Hvorfor

Der er intet fritekstoutput at parse. Arbejdsledere ser, hvad der kræver opmærksomhed; at handle på det forbliver altid en menneskelig beslutning.

go-pdf 0.9

A4-timesedler og servicerapporter genereres på serveren.

Hvorfor

Et rent Go-bibliotek holder backend-imaget lille og fri for en headless browser.

Sentry + slog

Fejl og traces sendes til Sentry, logs er struktureret JSON fra standardbiblioteket, og workers eksponerer metrikker i Prometheus-tekstformatet.

Hvorfor

Få bevægelige dele at drive, og hver fejl ankommer med sin kontekst.

Apps og CLI

Én Vue-klient betjener webben og pakkes af Tauri til desktop og mobil. Kommandolinjeklienten bruger det samme offentlige API som apperne.

Vue 3 + TypeScript Vue 3.5 · TS 5.9 · Pinia 3

Én klient med 118 single-file-komponenter, Pinia-stores, vue-router og vue-i18n på 23 grænsefladesprog, testet med Vitest.

Hvorfor

En moden, læsbar komponentmodel og streng TypeScript gør en stor klient håndterbar for et meget lille team.

Vite + Tailwind CSS Vite 8 · Tailwind 4

Byggeværktøjet og stylinglaget: Tailwind CSS 4 med et lyst og et mørkt tema.

Hvorfor

Hurtige builds og designtokens, der følger samme dokumenterede palet som webstedet.

Tauri 2.10

Pakker den samme webklient til macOS, Windows, Linux, iOS og Android med native notifikationer, deep links og signerede desktopopdateringer.

Hvorfor

Én grænseflade overalt, der bruger systemets webview i stedet for at bundte en browsermotor i hver app.

Genererede Connect-klienter connect-web 2.1 · protobuf-es 2

TypeScript-klienter, der genereres fra backendens Protobuf og kopieres ind i webappen. De redigeres aldrig i hånden.

Hvorfor

En kontraktændring bliver til en typefejl i klienten i stedet for en overraskelse i produktion.

centrifuge-js + livekit-client 5.7 · 2.20

Klientbibliotekerne til Centrifugo-realtid og LiveKit-opkald.

Hvorfor

Genforbindelse, gendannelse og mediehåndtering kommer fra de projekter, der bygger serverne.

TipTap 3.22

Beskededitoren med omtaler, links og kodeblokke med syntaksfremhævning.

Hvorfor

En struktureret editor i stedet for skrøbelig strenghåndtering.

hansa CLI Go 1.26 · Cobra

En tilstandsløs kommandolinjeklient til mennesker, scripts og LLM-agenter. JSON-output som standard, legitimationsoplysninger i operativsystemets nøglering og release-checksummer signeret med Minisign.

Hvorfor

Den bruger det samme offentlige API som apperne. Dens Protobuf-kontrakter kopieres fra backenden og låses med SHA-256-hashes, så afvigelser opdages i CI.

Websted, fakturering og register

Laravel driver det offentlige websted, kundedokumentationen, checkout, abonnementer og det centrale register over arbejdsområder. Det opretter et arbejdsområde ved at kalde Go-backenden over godkendt HTTP, uden delt kode og uden delte køer.

Laravel + PHP Laravel 12 · PHP 8.5

Det offentlige websted, kundedokumentationen, checkout, abonnementer, rabatkoder, livscyklusmeddelelser og det centrale register over arbejdsområder og domæner.

Hvorfor

Fakturering, e-mail, planlægning, køer og formularer er Laravels stærkeste sider. Chatten bliver i Go, og grænsen mellem dem er én godkendt HTTP-grænseflade.

FrankenPHP 1.13

PHP-applikationsserveren i container-imaget, bygget på et fælles base-image, der fastlåser PHP, dets udvidelser og værktøjer via digest.

Hvorfor

Én proces betjener applikationen, og et nyt build af samme commit giver det samme runtime-miljø.

Blade + Alpine.js + Tailwind CSS Alpine 3.15 · Tailwind 3.4 · Vite 7

Serverrenderede sider med små Alpine.js-komponenter, stylet med Tailwind CSS og bundtet af Vite.

Hvorfor

Indholdssider indlæses hurtigt uden at levere et single-page-app-framework.

22 sprog

Hver offentlig side findes på 22 EU-sprog med sprogpræfiks i URL’erne, hreflang-links og et lokaliseret sitemap. En test fejler, hvis et sprog mangler en nøgle eller leverer engelsk tekst.

Hvorfor

Et europæisk produkt bør kunne læses på købers eget sprog fra første side.

Creem

Checkout, moms, fakturaer og abonnementer, holdt synkroniseret via signerede webhooks.

Hvorfor

Betaling, moms og fakturering ligger hos en specialiseret udbyder, mens webstedet fører en afstemt kopi af hvert abonnement.

EmailLabs

Transaktions- og service-e-mails som invitationer, adgangskodelinks og meddelelser.

Hvorfor

En EU-e-mailudbyder til et EU-produkt.

Pest 4.4

Mere end 130 testfiler dækker ruter, fakturering, provisionering, oversættelser og SEO, inklusive browsertests.

Hvorfor

Hurtige, læsbare tests, der kører ved hver ændring.

Platform og drift

Produktion og preview kører hos IONOS i Tyskland. Hver applikation leveres som et container-image med sit eget Helm-chart og udrulles af et manuelt udløst GitLab-job.

IONOS Managed Kubernetes

Produktions- og preview-klynger, administreret MariaDB og S3-kompatibel Object Storage, alt sammen drevet af en tysk udbyder i Tyskland.

Hvorfor

En europæisk udbyder under EU-jurisdiktion, ikke EU-regionen hos en ikke-europæisk cloud.

Helm + Traefik

Hver applikation leverer sit eget chart. Traefik router trafikken inde i klyngen, og migreringer af arbejdsområdedatabaser kører som en hook før hver udrulning af backenden.

Hvorfor

Hver udrulning er versioneret, gentagelig og nem at rulle tilbage.

Bunny.net

CDN, DNS og DDoS-beskyttelse foran klyngen samt lageret til krypterede backups.

Hvorfor

En europæisk virksomhed driver edgen og opbevarer backup-kopierne, så ingen af dem afhænger af en ikke-europæisk cloud.

Valkey + Sentinel + HAProxy Valkey 9.1

Tre replikaer med Sentinel-failover og en HAProxy-proxy, der altid peger på den aktuelle primære node. Den understøtter caching, sessioner, tilstedeværelse og realtidsbrokeren.

Hvorfor

En failover kræver ingen ændring i applikationen, fordi hver tjeneste bliver ved med at tale med den samme adresse.

restic 0.18

Krypterede databasebackups hver 6. time til to placeringer i EU med ugentlige integritetstjek og en automatiseret månedlig gendannelsesøvelse.

Hvorfor

En backup tæller først, når en gendannelse er bevist.

GitLab CI

Tests, image-builds og tjek af Helm-charts kører i CI. Udrulninger til preview og produktion er separate, manuelt udløste jobs.

Hvorfor

Automatiseringen klarer det gentagne arbejde; et menneske beslutter, hvornår noget når kunderne.

Omkring produktet

De værktøjer, der holder en enkeltmandsvirksomhed observerbar, tilgængelig og forklarlig.

Cloudflare Workers + D1

En ekstern statusside, der tjekker appen og webstedet hvert femte minut og registrerer hændelser.

Hvorfor

Tilgængelighed måles uden for den infrastruktur, den beskriver.

Umami 3.2

Selvhostet webanalyse, der først kører, når en besøgende har truffet et samtykkevalg.

Hvorfor

Besøgsdata forbliver på HansaChats infrastruktur i stedet for at fodre et annoncenetværk.

Remotion 4.0

Produktvideoerne optages fra den rigtige applikation af end-to-end-testkøreren og sammensættes i kode med en AI-genereret speak.

Hvorfor

Når grænsefladen ændres, renderes videoen igen i stedet for at blive filmet forfra.

TwentyCRM + WireGuard

Et selvhostet CRM, der kun kan nås via et privat VPN.

Hvorfor

Salgsdata er slet ikke eksponeret mod det offentlige internet.

Udviklingspraksis

De vaner, der gør det muligt for én person at levere et multi-tenant-produkt uden et separat QA- eller driftsteam.

Kontrakter genereres og skrives aldrig i hånden

Protobuf er den eneste kilde for Go-serveren, TypeScript-klienterne og CLI’en. Generatorerne er fastlåst til præcise versioner, og CLI’en registrerer hashen af hver kontraktfil, den bruger.

Migreringer fører regnskab

Hver arbejdsområdedatabase registrerer, hvilke migreringer den har anvendt. En udrulningshook anvender kun de manglende og tjekker igen efter udrulningen. Webstedet beholder sine oprindelige baseline-migreringer, så eksisterende databaser aldrig kører dem to gange.

End-to-end-tests på en isoleret stak

Én kommando starter databaserne, NATS, Valkey, Centrifugo og objektlagring på ledige porte, bygger Go-binærfilerne, starter webappen og kører 70 Playwright-specs med et nyt arbejdsområde til hver test.

Tests på hvert lag

478 Go-testfunktioner, herunder isolationstests med to arbejdsområder, 109 Vitest-filer i klienten og mere end 130 Pest-filer på webstedet.

Værn i CI

Formateringstjek, en grænse på 1.000 linjer pr. Go-fil og tests af Helm-charts kører i CI ved siden af testsuiterne.

Manuel godkendelse før udrulning

CI bygger og tester automatisk, men udrulninger til preview og produktion er separate manuelle jobs. Produktion udruller et release-tag, der først oprettes, efter at ændringen er merget.

Backups bevist ved gendannelser

Hver backupkørsel overvåges, og en automatiseret øvelse gendanner databaserne hver måned og validerer tabeller og rækkeantal.

Ét designsystem

Webstedet og appen deler én dokumenteret palet, typeskala og komponentregler med et lyst og et mørkt tema i appen.

AI-assisteret, godkendt af mennesker

AI-kodeagenter arbejder ud fra en instruktionsfil i hvert repository, der peger på ét centralt repository med udviklingsdokumentation. Gentagelige arbejdsgange som end-to-end-kørslen er pakket som agent-skills. Hver ændring skal stadig bestå de samme tests, og udrulninger forbliver manuelle.

Sikkerhedsstyring under forberedelse

HansaChat forbereder sig på ISO/IEC 27001-certificering med et risikoregister, et evidensregister og en beslutningslog. HansaChat er ikke certificeret i dag.

Hvad denne side påstår – og hvad den ikke påstår

Alt ovenfor beskriver, hvad der er implementeret i dag, og er optalt i kilderepositorierne. HansaChat gør ikke krav på en sikkerhedscertificering. Beskedtriage er i pilotdrift, og push-notifikationer for lukkede apps er endnu ikke live.

Spørgsmål om arkitekturen?

Udviklere, der evaluerer HansaChat, får direkte svar fra den person, der har bygget det.

Send en e-mail til udvikleren