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

$ cat architecture.svgAt a glance
$ 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
- 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.
- 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.
- Apply. Approved changes go into Postgres in one transaction.
- 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
- Parser: line-based, with errors that carry line numbers and a lossless tree that can be written back out unchanged. A 1.1 MB file parses in about 38 ms.
- Validation: 37 stable finding codes such as
DEATH_BEFORE_BIRTH, at three severities. - Reconciliation: a merge plan without writing anything, with optional fuzzy matching solved as a min-cost assignment inside blocking buckets.
- Plain-language questions without free-form SQL: each question maps to one of 34 intents that run fixed, allowlisted queries, so the model never writes SQL.
- A headless chart engine: descendancy, pedigree and fan-chart layouts as pure functions returning positions and SVG paths.
$ 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.



