Contacts to organization-chart converter
A python script, that converts your address-book into an organigram. (offline - no internet connection needed.)
As a result, you can find out, how you know whom. This is based on the idea of "six degrees of separation". https://en.wikipedia.org/wiki/Six_degrees_of_separation
Your buddy Frank (6) is married to Eve (5). She is a colleague of David (4), who plays football with Charlie (3). He is the neighbor of Bob (2), who is the brother to your wife Alice (1).
To run, type vcf2chart.py FILENAME.VCF or vcf2chart.py "../another-folder/FILENAME.VCF" depending on where the file is located.
It creates a file index_contacts.html and should start your browser.
- 🗀 / 🗁 : Show / Hide the (number of) contact-levels under this item.
Example:Wendy Doe-SmithopensMegan SmithandFred Smith. - ▿ / ◃ : Show / Hide the contact-details
- ☋ / ⎌ : Show / Hide the (number of) connections for this contact.
-
Your address-book exported as a vCard VCF-file. Please refer to your email / contact / messenger-application. You can look at the short example of a VCF-file.
-
Some hashtags in the NOTE of your contacts
- Three hashes for your own contact details.
Example:###this_is_meor###abcdefor simply### - Two hashes for your "categories". These are the parent-elements.
Example:##wendy, ##sports, ##football
OR use (sub)-categories for your contacts.
Example:My Family / Family abroad / Family in Europe
OR combine the two possibilities. - One hash for the child-elements.
Example:
#wendy, #sports, #football - A child can also be parent to other children.
Example: parent A:##sports-> has child B: with#sports. But B is also labeled parent for##footballto -> child C:#football - A child overrules the category.
Example:Friends + #sports-> The contact will be shown under##sportsbut notFriends.
- Three hashes for your own contact details.
-
Optionally: a hashtag
#noin the NOTE for contacts you want to hide from the chart.
Example: The contactCharlotte Whitein the VCF-file. -
Optionally: Normal categories and subcategories (sometimes called "label") on your contacts.
Example: The contactsWendy Doe-Smith, Scott Doe, Diane DoewithMy Familyin the VCF-file. -
Optionally: A connection to a parent-item in your contact. Connections are identified by a pipe symbol "|"
Example:Thomashas a connection called|wendyand draws a line to##wendy
This can be useful for relations spanning over different categories.
Example:Thomasis a child of##workbut he has also a connection to##wendy. -
Python in version 3.x or higher
Within the script , find the list_of_vcf_property_types in the first lines. You always need the first four properties!
list_of_vcf_property_types = ["FN", "NOTE", " ", "CATEGORIES"]
But you can add more if you like.
list_of_vcf_property_types = ["FN", "NOTE", " ", "CATEGORIES", "ADR", "TEL", "EMAIL", "BDAY", "URL", "PHOTO"]
A list of properties can be found on Wikipedia https://en.wikipedia.org/wiki/VCard#Properties
The HTML file shows only the first three levels by default. (1: You, 2:Categories / first parents, 3:First children)
Within the assets/treeData.js find the function toggle_levels(3) and change it to another number.
Example: toggle_levels(5)
Within the stylesheets in àssets/css_org_chart.css find the :root-part. It defines the background-colors for up to ten contact-levels.
The text-color (black / white) is calculated automatically based on the background using the CSS contrast-color.
Multiple #children or categories within one contact are not possible.
- Example 1: "Damian" (multiple categories) ->
CATEGORIES:Friends,Work/Company C-> only one is taken - Example 2: "Linda" (multiple children)" ->
NOTE:#wendy #brat_doe-> only one is taken
A contact without category but with a ##parent-tag will not show up.
- Example:
Emma Richardshas no category but the tag##emma. She and her kidEvelin Richards (#emma)won't show up. - Workaround 1: Put the contact into a category (like
Friends), so it has its own parent. - Workaround 2: Give the ##parent an extra #child (like
##emma #sports). The unknown child#sportswill create a new parent/category##sports.
Extra labels aren't filtered.
- Example 1:
Thomasfrom company A (with extra labels)
TEL;TYPE=WORK:(846)-62 70 96 75
TEL;TYPE=HOME:(846)-62 70 77 48 283
results into:
TYPE=WORK:(846)-62 70 96 75 TYPE=HOME:(846)-62 70 77 48 283
- Example 2:
Wendy(without extra labels)TEL:(936)-39 03 63 76 484
results into:(936)-39 03 63 76 484
Hashtags should have a space character in front of them. If not, they can cause a mismatch in combination with long texts before the hash tag in the NOTE-part.
Example: In the contact-note you have two lines:
A very long note on a person and a hash tag that follows.
#child
This could look in the VCF file like this:
NOTE:A very long note on a person and a hash tag that follows.
` #child
Which then is processed by the script into:
A very long note on a person and a hash tag that follows.#child
So it would be better to write a contact-note like this:
A very long note on a person and a hash tag that follows.
#child
There are different ways to specify a photo. The browser needs a string like
data:image/png;base64,[base64-data] to show the data.
But the vCard contains a string like:
PHOTO:TYPE=PNG;ENCODING=b:[base64-data] or
PHOTO:ENCODING=BASE64;TYPE=PNG:[base64-data] or
PHOTO;MEDIATYPE=image/png:http://example.com/logo.png
So far, not all possible scenarios are covered.
The CSS property contrast-color was introduced in late 2025 / beginning of 2026 into browsers. https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/contrast-color If you're using an older browser, it might not work, yet.
There is probably space for many improvements. :) Feel free to open an issue, write to me at mathias . steudtner (a) mailbox . org or use it for your own projects.
The scripts (python, HTML, CSS, JavaScript) are licensed under MIT license.
https://choosealicense.com/licenses/mit/
Images and texts can be used under Creative Commons Attribution Share Alike 4.0 International (CC BY SA 4.0)
https://choosealicense.com/licenses/cc-by-sa-4.0/
- initial version.
- reads VCF file
- creates an organizational chart
- shows names, details (notes, telephone, URL, etc.) and photos
- can show / hide sub-levels ("children")
- hides empty categories ("parents") from search
- hides contacts with keyword
#no
- removed some unused data
- children and parents are not case-sensitive anymore
before:#sport != #SpOrTAfter:#work == #SpOrT - added a function to create connections (lines, SVG-paths) between contacts
- show number of connections on a button
- show number of children (levels) on a button
- buttons are better aligned using a table
- added a footer to the HTML-file
- added timestamps to the log-messages in the terminal
- corrected some typos
- added a search
- parents as categories are now capitalized
Example: parent##sportdoesn't get the name##sportanymore butSport - changed the hover effect (red, 50% opacity) to start on the second level and not at the main person (1st level)
- added function to read out subcategories
Example: CategoryMy Family-> subcategoryMy Family / Family abroad-> sub-subcategoryMy Family / Family abroad / Family in Europe - minor bugfix on vCard-lines that start with a space character
- Added a new VCF-example file.
- Updated comments (documentation) in the script
- Minor changes on font-styles
- Dark mode for HTML-file (CSS)
- bug-fixes
