Skip to content

Architecture.nl

Doug Blank edited this page Oct 11, 2026 · 1 revision

🌐 English · Deutsch · Español · Français · 简体中文

Architectuur

Gramps Connect is een React-frontend (app/) die via de REST-API met een gramps-web-api-backend praat — het is geen fork of vervanging van gramps-web-api, maar een andere client voor dezelfde server. Twee mechanismen maken het mogelijk dat die frontend tegelijk snel en samenwerkend aanvoelt: een local-first cache, en een lichte laag voor live synchronisatie via polling bovenop een endpoint dat gramps-web-api al meelevert.

Local-first cache

Een WASM-build van SQLite draait in de browser, spiegelt servergegevens naar lokale tabellen en bewaart die in OPFS (het eigen privébestandssysteem van de browser), zodat een volgend bezoek het netwerk helemaal kan overslaan. Gegevens worden opgehaald via de snelle /api/<type>/query/-endpoints van gramps-web-api, waarbij het werk naar SQL wordt doorgeschoven — dezelfde endpoints waarnaar GOQL-voorwaarden en where=-clausules van Gramplets worden gecompileerd — in plaats van door volledige REST-antwoorden per object te bladeren.

De winst is wat het Overzicht beschrijft: zodra u een deel van uw stamboom hebt bekeken, voelen bladeren, sorteren en zoeken in dat deel daarna direct aan, zelfs bij stambomen met tienduizenden personen, waar dit soort zoekopdrachten tegen een gewone, niet-geïndexeerde REST-backend anders ruim een minuut kan duren.

Daarom kunnen de desktopversie met de vaste admin/admin en een echte serverinstallatie ook precies dezelfde frontendcode delen zonder speciale gevallen: de cache wil alleen weten dat hij met een /api/ in de vorm van gramps-web-api praat, niet wie die host.

Een valkuil om te kennen: de cache aan de browserzijde heeft een vaste bestandsnaam per weergave als sleutel, niet de backend-URL of het stamboom-id. Wisselen naar een andere backend, of een stamboom opnieuw importeren/aanmaken op dezelfde backend, kan ertoe leiden dat een browserprofiel verouderde rijen uit de cache serveert zonder automatische ongeldigverklaring — de enige controle die wordt uitgevoerd is schemacompatibiliteit, niet de identiteit van de gegevens. Als gegevens er na een wissel van backend ooit verouderd uitzien, wis ze dan handmatig: DevTools → Application → Storage → clear site data (of specifiek OPFS).

Live synchronisatie

De client pollt met een korte tussenpoos het bestaande endpoint GET /api/transactions/history/ van gramps-web-api (het audit-/undo-log van objectbewerkingen dat het al meelevert, niet iets wat hiervoor is toegevoegd). Voor elk object dat dat endpoint als gewijzigd meldt, haalt Gramps Connect alleen die ene rij opnieuw op en werkt die bij in de lokale cache.

Dit is bewust eenvoudig: er is geen blijvende verbinding in WebSocket-stijl en geen Postgres-specifieke change-data-capture nodig, alleen een gewone geauthenticeerde GET op een timer — dus het werkt met elke gramps-web-api-backend, niet alleen een met Postgres. Zo werkt "iemand anders corrigeert een datum en uw scherm werkt zichzelf bij" (zie Overzicht) echt, en zo kunnen de dev-fixtures synchronisatie oefenen zonder een echte Postgres-instantie — zelfs de gewone SQLite-fixtures ondersteunen het, omdat het gewoon een poll is.

Wat live synchronisatie nog niet doet: er is geen aanwezigheidslaag (wie op dit moment wat bekijkt of bewerkt) en geen geschiedenisbrowser voor gebruikers — zie Roadmap en bekende beperkingen.

Indeling van de repository

  • app/ — de React-client voor productie: alle tien weergaven per objecttype (persoon, gezin, gebeurtenis, plaats, bibliotheek, bron, citaat, media, notitie, label — zie Datamodel en bewerken), filteren met where_expr/GOQL, een WASM-SQLite-cache die in OPFS wordt bewaard, en live synchronisatie, achter een storelaag op basis van useSyncExternalStore (app/src/store/) met @tanstack/react-virtual voor het scrollen.
  • dev-fixtures/ — echte gramps-web-api-backends om app/ lokaal tegen te draaien; geen onderdeel van het uitgeleverde product, alleen wat lokale ontwikkeling mogelijk maakt zonder handmatig een server te configureren. Zie Ontwikkeling voor de drie varianten (layer2-local-cache/api-fixture, api-fixture-example en layer3-sync/api-fixture) en waarvoor elk dient.
  • packages/gramps-date/ — een TypeScript-port van het eigen Date-model van Gramps, de kalenderconversie en de taalafhankelijke datumweergave, gebruikt door app/ zodat het een Gramps-Date-structuur kan weergeven, ontleden of opbouwen zonder voor elke rij in een tabel een trage rondreis per object via de eigen Python-datumweergave van Gramps. Het dekt alle tien kalenders van Gramps (inclusief de Chinese, Koreaanse en Vietnamese maankalenders van Gramps 6.2), gestructureerde datuminvoer en -validatie, en de datumweergave en -herkenning van Gramps in alle 43 datumtalen van Gramps (Engels ingebouwd, de rest op verzoek geladen), waarvan de teksten door zijn scripts/generate_gramps_locales.py uit een draaiende Gramps worden gegenereerd. Het is een vertaling van de eigen gramps/gen/lib/date.py/gcalendar.py/_datedisplay.py/ _dateparser.py uit de kern van Gramps, van Python naar TypeScript, in zijn testsuite gecontroleerd tegen de eigen uitvoer van Gramps en de datumsets uit de unittests van Gramps; Gramps-bugs die het repareert in plaats van overneemt, staan in zijn GRAMPS_BUGS.md. Zie zijn eigen README voor het volledige verhaal over herkomst en licentie (het is GPL-2.0-or-later-code die in dit AGPL-3.0-or-later-project is opgenomen, op dezelfde manier als de eigen gcalendar.js-port van gramps-web al doet).
  • standalone/ — de op PyInstaller gebaseerde build van gramps-connect-desktop: een Python-launcher (launcher.py) die de gebouwde frontend van app/ samen met gramps-web-api en SQLite bundelt tot één app met een eigen venster (of met de browser als terugvaloptie). Zie Installeren.
  • deploy/ — de gecontaineriseerde installatie voor meerdere gebruikers (app/ + gramps-web-api + Postgres + Caddy + Redis/Celery). Zie Implementeren.
  • gramplet_examples/ en gramplet-store/ — voorbeeld-Gramplets en de broninhoud voor de catalogus van de Gramplet-winkel in de app. Zie Gramplets.

Een npm-workspace op het hoogste niveau (packages/*, app) verbindt app/ en packages/gramps-date als echte workspace-afhankelijkheden. De snelle /query/-endpoints waarvan app/ afhankelijk is, staan in gramps-web-api zelf (een aparte repository, ter plaatse uitgebreid, achterwaarts compatibel) via gramps-object-query-language, de eigen implementatie van GOQL — niet in deze repository.

Add-ons draaien Python in de browser

Gramplets — de add-ons van de app — draaien onder Pyodide (naar WebAssembly gecompileerde CPython) rechtstreeks in het browsertabblad, met lokaal gebouwde wheels van gramps.gen.lib (het eigen datamodel van Gramps, zodat de Python-code van een Gramplet echte Person/Family/...-objecten ziet, geen herimplementatie). Er wordt niets op een server uitgevoerd en niets op uw computer geïnstalleerd — zie Ontwikkeling voor hoe die wheels worden gebouwd, en Gramplets voor hoe de afgeschermde API (people(), filter(), db, row(), html(), ...) in elkaar zit.

Clone this wiki locally