Genealogy Prototype

So many projects I want to do (aka: so many shiny objects competing for my attention), never enough time in a day.

This first cut is focused on fleshing out the foundational architecture for producing family trees with the GraphViz plugin.

Take a peek at the TiddlyWiki instance.

5 Likes

The TiddlyWiki instance.

Figured out how to show informative tooltip when hovering over a “person node” in a GraphViz rendering. See calls to the “gvnote” macro (in the “macros” tiddler) in the “Footer” tiddler.

For example, “Prince Albert Victor”:
Screenshot 2025-10-02 3.19.34 PM

2 Likes

The TiddlyWiki instance.

Next TODO: Now that it looks like “forward-generating” of a family tree works, I want to setup “backward-generating” of a family tree.

For example, great to know the “forward-generation” of King Charles III family tree (I.e. descendants), I want the tree to show King Charles III’s ancestors (on both the father’s side and the mother’s side),

This first attempt (the goods are hiding in the “Footer” tiddler) gets the relationship that conceived King Charles III:

Now we can see all ancestors for an individual.

Next TODO: for an individual, show siblings, show aunts/uncles, show cousins, etc. etc.

To make sure that ancestors thingy is working okay, I added a little bit of info on Prince Phillips ancestry.

By focusing on the relationship between King Charles III and Diana Spencer, we get to see the genealogical tree of both Prince William and Prince Harry.

Cool.

1 Like

Ah good. “Kissing cousins” doesn’t break the graph:

The TiddlyWiki instance.

Total aside: digging into a family tree, one gets to discover some very interesting history.

Like how Queen Victoria got to be a monarch.

image

The TiddlyWiki instance.

Focused on King Charles III ancestry up to and including his great-great grandparents, I’m satisfied with the basic data entry and the family tree graphics, and also with TW navigation.

People and Marriages can be found (via simple filters) via the People and via the Marriages SideBar tabs. Filtering ought to be done with only 1 name/word, not to reduce the list down to one person/marriage, but rather to shorten the list enough to make a person/marriage easy to find.

image

image

Next TODO: setup a “reader” user interface as the default interface. The normal TW interface will be for editing content.

Whoa! That is a seriously powerful app. already … How it produces the “people maps”…like …

Kind of fun, eh?

I’m now using it to create my own family tree, and I’m making some tweaks to my personal TW instance and, as I truck along, copying those tweaks over to this public prototype.

The TiddlyWiki instance.

A relationship (marriage, affair, common law …) is between two people.

I’ve set things up so that a relationship involves at most 2 people. (Sometimes, it is possible to work far into the past, and not know the other person in a relationship that spawned children. So a relationship with just one person means we don’t know who the other person is.)

For the list of check boxes provided to tag the relationship with the people in the relationship:

  • check boxes for selected people will always be enabled
  • check boxes for non-selected people will only be enabled when there are fewer than 2 people selected.

Here’s a snippet of related code (from the “Relationship Editor” tiddler), followed by a screenshot (two people selected, all other check boxes become disabled):

<$checkbox
   tiddler={{!!title}}
   tag=<<p>>
   disabled={{{ [{!!title}tags[]match<p>then[no]] [{!!title}tags[]tag[p]count[]match[2]then[yes]] +[first[]] }}}>
         {{{ [<p>search-replace:g[\n],[ ]search-replace:g[_],[ ]] || txt }}}
</$checkbox>

2 Likes

Just some cosmetic touch-ups.

The “People” side bar tab shows birth dates (or range of life: birth and death) when avaiable:

And the “Relationships” side bar tab does the same thing:

I’ve also altered the shape of relationship nodes, switching from a triangle to an inverted house (eventually, I think I’ll be using icons to identify the kind of relationship between the couple and between the couple and children):

I’m in the midst of coding a change regarding the list of relationships in the sidebar tab.

In the “before” version, every relationship is retrieved once, and the link for each relationship shows the people in the relationship sorted by their names. This means searching via scanning the list means looking at names of both people in every relationship…

In the “after” version, every relationship is listed twice: once as “Person A” and “Person B”, and once as “Person B” and “Person A”. And then all of those relationships are sorted alphabetically. So if you are scanning for a particular person, you can just look at the first person in all relationships.

A picture being worth a thousand words, here is an example in which we would be scanning for a particular “Michel”…

Before:

After:

Related code, if you are interested in that …

Before:

\define extra() <br><div style="margin-left:20px;margin-top:-5px;font-size:0.75em;">{{{ [{!!title}get[dob]] [{!!title}get[dod]addprefix[  ➡  ]] +[join[]] +[addprefix[ (]] +[addsuffix[)]] || txt }}}</div>

<$button>
  <$action-createtiddler $basetitle={{{ [tag[m]nsort[]last[]add[1]else[1]] }}} tags="m">
  <$action-navigate $to=<<createTiddler-title>>/>
  </$action-createtiddler>
  âž• Add a Relationship
</$button>
<hr>
''Filter: '' <$edit-text tiddler="$:/temp/MarriagesFilter" tag="input" default=""/>
<hr>
<$let r={{{ [[(?i)]] [{$:/temp/MarriagesFilter!!text}] +[join[]]  }}}>
<$list filter="[tag[p]regexp<r>sort[]tagging[]tag[m]]">
<$link to={{!!title}}><$text text={{{ [{!!title}tags[]tag[p]search-replace:g[_],[ ]sort[]join[ 🧑‍🤝‍🧑 ]else[New marriage]] }}}/></$link><<extra>>
<hr style="margin:1px;border:1px dashed #d7d7d7">
</$list>
</$let>

After:

\define extra() <br><div style="margin-left:20px;margin-top:-5px;font-size:0.75em;">{{{ [<m>get[dob]] [{!!title}get[dod]addprefix[  ➡  ]] +[join[]] +[addprefix[ (]] +[addsuffix[)]] || txt }}}</div>

<$button>
  <$action-createtiddler $basetitle={{{ [tag[m]nsort[]last[]add[1]else[1]] }}} tags="m">
  <$action-navigate $to=<<createTiddler-title>>/>
  </$action-createtiddler>
  âž• Add a Relationship
</$button>
<hr>
''Filter: '' <$edit-text tiddler="$:/temp/MarriagesFilter" tag="input" default=""/>
<hr>
<$let r={{{ [[(?i)]] [{$:/temp/MarriagesFilter!!text}] +[join[]]  }}}>
<$list variable=p1 filter="[regexp<r>tag[p]sort[]]">
<$list variable=p2 filter="[<p1>tagging[tag[m]tags[]tag[p]!match<p1>sort[]]">
<$list variable=m filter="[tag<p1>tag[m]] :intersection[tag<p2>tag[m]]">
<$link to=<<m>>><$text text={{{ [<p1>search-replace:g[_],[ ]] [<p2>search-replace:g[_],[ ]addprefix[ 🧑‍🤝‍🧑 ]] +[join[]] }}}/></$link><<extra>>
<hr style="margin:1px;border:1px dashed #d7d7d7">
</$list>
</$list>
</$list>
</$let>
1 Like