modularsoftware/genealogy
A Laravel package for genealogy applications, with Eloquent models, migrations, and relationships for people, families, events, places, and sources. Build family trees, ancestry records, and research workflows with a clean, extensible API designed to fit into existing Laravel projects.
This repo is an application, not a drop-in Composer library. Treat it as a fork-and-own starter kit rather than something you composer require into an existing Laravel app. That single fact shapes everything below.
Minimum path to a running instance:
git clone https://github.com/modularsoftware/genealogy.git my-tree-app
cd my-tree-app
composer install
cp .env.example .env
php artisan key:generate
# configure DB_* in .env (MySQL or Postgres recommended)
php artisan migrate --seed
npm install && npm run build
php artisan serve
Where to look first, in order:
routes/ — understand the surface area before touching models. You need to know whether this is server-rendered, API-only, or mixed.app/Models/ — the domain is GEDCOM-shaped: expect records for individuals, families, events, sources/citations, media, and notes, with self-referential and pivot relations for parent/child/spouse links.database/migrations/ — the schema is the real spec. Read it before trusting model docblocks.First use case to validate: import a small GEDCOM file (3–4 generations, a handful of sources) and confirm you can (a) render a person with their events, (b) walk parents/children/spouses, and (c) export back to GEDCOM without data loss. If those three work, the skeleton is usable. If import is broken, stop — the rest is scaffolding you could rebuild faster than you could repair.
Model the domain as GEDCOM records, not as "users' family data." The records are Individuals, Families, Events, Sources, Citations, Media, Notes. Build your features against that vocabulary so import/export stays symmetric. Fight the urge to invent a parallel "Person" model alongside the existing one.
Import as a queued pipeline, not a request. Parse → normalize xrefs (@I123@ style pointers) → upsert records in batches inside transactions → link relations in a second pass. This gives you retries, progress tracking, and a clean failure boundary. If the repo already ships an importer, wrap it rather than rewriting it; if it doesn't, this is the first thing you build.
Relationship traversal is the performance hot spot. Parent/child/spouse links are recursive and will N+1 instantly on any tree view. Eager-load generously, and for deep ancestor/descendant queries prefer a recursive CTE (Postgres/MySQL 8) or a materialized path/closure table over repeated Eloquent traversal. Cache computed tree fragments by family ID and bust on write.
Extend via observers and custom importers, not by editing core models. Add your own fields in a new migration, attach behavior with model observers, and register custom GEDCOM tag handlers if the importer exposes a handler map. Keeps your fork mergeable if upstream ever moves (it won't, but future-you will thank you when upgrading Laravel).
Keep your API/resources in your own namespace. Add App\Http\Controllers\Api\... and App\Http\Resources\... alongside whatever ships, rather than editing shipped controllers. Same for policies — genealogy data is often sensitive (living individuals), so gate access at the tree/record level explicitly.
Test with tiny GEDCOM fixtures. Hand-write 20-line GEDCOM files covering the ugly cases (multiple marriages, unknown parents, source citations, ANSEL-encoded names) and assert round-trip import→export equality. This is the highest-value test suite you can write for this codebase.
composer audit, pin your lockfile, and budget a framework upgrade before you ship anything public-facing.max_execution_time and memory limits. Queue it, chunk it, and stream rather than loading the whole file into memory.storage:link is assumed. Media paths in GEDCOM exports are often relative and machine-specific — normalize them on import.failed_jobs plus storage/logs/laravel.log before touching the schema. php artisan tinker against the models is faster than clicking through the UI for relation checks.QUEUE_CONNECTION, the media disk, and database collation (utf8mb4) up front. Genealogy data is name-heavy and multilingual; a latin1 schema will silently mangle it.Bottom line: use this repo as a reference implementation of GEDCOM-shaped domain modeling and import/export logic, not as a dependency. Its schema and parser are the leverage; its framework version and maintenance status are the liability.
How can I help you explore Laravel packages today?