← cd ../work
Architect and sole engineer · 2025–2026

Ligneous

A genealogy platform that parses GEDCOM family trees in Go and serves them as a living family-history site.

GoPythonFlaskNext.jsTypeScriptPostgreSQLPrismaPodman
A descendancy chart laid out by the visualization engine
Charts: laid out by the headless visualization engine

$ cat architecture.svgAt a glance

Editoruploads a .ged fileAdmin appNext.jsGEDCOM APIGo HTTP serviceGEDCOM library (Go)parse, validate, enrichPostgresgedcom_* tablesPublic siteNext.js@ligneous packagescharts, stories, albumsResearch APIPython, FlaskEnrichedDocumentapply in one transactionstatistics, search

$ cat the-problem.mdThe problem

Family trees arrive as GEDCOM files: an old, loosely followed format full of fuzzy dates, duplicate people and broken links. The family wanted a site where relatives can browse people, explore charts, read and write stories, and ask questions in plain language, with editors able to import new files safely.

$ cat architecture.mdArchitecture

  1. Import. An editor uploads a GEDCOM file. A Go service parses and validates it into a typed intermediate representation: flat, deduplicated tables of people, families, parsed dates, places, events and parent/child edges that line up with the Postgres tables.
  2. Review. Before anything is written, the admin app shows the validator’s findings and a merge plan against the existing tree: who is already there, who is new, and what conflicts.
  3. Apply. Approved changes go into Postgres in one transaction.
  4. Read. The public Next.js site reads Postgres for people, charts, timelines and stories, and calls a Python research API for statistics, relationship paths and plain-language questions.

$ cat engineering-highlights.mdEngineering highlights

$ cat security-boundaries.mdSecurity boundaries

The public site and the admin app are separate applications with different access to data. In production every service runs as a rootless Podman container under systemd, behind nginx, and the Go and Python services listen only on the server itself.

$ cat testing-and-deployment.mdTesting and deployment

102 tests for the Go library plus benchmarks, 135 pytest cases for the research API and 127 Vitest cases for the story editor. Each repository documents its limitations and known bugs openly.

$ cat whats-next.mdWhat’s next

Fix the relationship-label bug the Python tests expose, and keep moving shared packages into public repositories.

$ ls screenshots/On screen

From the test and demo servers, so the people and data shown are made up or public samples.

A five-generation fan chart of ancestors
Fan chart: five generations
GEDCOM import summary showing parsed, validated and enriched records
Import: parsed, validated and enriched before anything is written
Story editor with text linked to people in the family tree
Story editor: text linked to people in the tree
A plain-language question answered from the family tree
Plain-language search: questions mapped to allowlisted SQL