Data Modeling and Visualization for a 16th-Century French Royal Engraving Collection
This article shows how a historical catalogue of French monarchs, based on engravings associated with Nicolas de Larmessin, can be converted into a structured dataset for querying, verification, and extension. It covers entity modeling for persons, reigns, dynasties, kingdoms, portraits, and evidence; techniques for handling reign intervals, overlapping rulers, conflicting dates, uncertain chronology, and data quality; API design, analytical queries, visualization patterns, and a phased delivery plan. It is intended for developers and data engineers working on historical, genealogical, or cultural-heritage data projects.
1. Source Characteristics and Requirements
The engraving set is based on engravings by the French engraver Nicolas de Larmessin. The portraits run from Faramund, the legendary first king of the Franks, to Louis XIV of the Bourbon dynasty, covering most French monarchs in between as well as several royal family members. The original catalogue lists figures by lineage and uses ordinal numbers and short annotations to connect the Merovingian, Carolingian, and Capetian dynasties across several centuries.
For readers, this list has an obvious limitation: it does not provide consistent answers to questions such as “How many years did a particular king reign?”, “Which monarchs were ruling at the same time?”, or “Who was whose father?”
This article does not focus on art history. Instead, it is aimed at developers and data engineering practitioners. Using this engraving set as a prototype, it explains how a historical list of persons can be transformed into a structured dataset. The article covers:
- designing a data model based on the characteristics of the source material;
- handling reign intervals, multi-source conflicts, and date annotation;
- designing query APIs and visualization options;
- establishing data-quality rules and a delivery path.
The goal is to turn “portraits plus annotations” into a queryable, verifiable, and extensible knowledge asset. The SQL and JSON examples in this article are illustrative, and fields can be adapted to the needs of a specific project.
1.1 Three characteristics of the source material
The engraving collection can be abstracted as a composite data source consisting of “persons + relationships + images”:
- The person list is semi-structured. Ordinal numbers imply an ordering, while annotations mix historical facts, evaluations, and speculation.
- The relationship network is dense. Father-son relations, sibling relations, partition, reunification, deposition, and marriage alliances are intertwined across several centuries.
- Images are unique and carry date information. Each engraving corresponds to one person, and the production date of the engraving itself is also important metadata.
If the list is simply imported into a database, the result is little more than a searchable name list, with limited query capability and limited knowledge value. The requirements should therefore be refined into five categories:
- Retrieval by dimension: dynasty, period, identity status, and reign duration.
- Interval-based questions: which monarchs had overlapping reigns; when the Frankish kingdom was unified and when it split again.
- Kinship and succession reconstruction: whether succession chains are continuous; how many sons a particular monarch had.
- Traceable evidence: every conclusion should be traceable to a specific engraving or historical source.
- Extensibility: royal family members, queens, regents, and capital cities can later be added without restructuring existing tables.
1.2 Five modeling challenges
First, ordinal position does not equal chronology. In the list, Childeric I appears before the Merovingian dynasty heading. He was the father of Clovis I and an ancestor of the Merovingian family that later founded the dynasty, so the catalogue effectively treats him as a “pre-dynastic figure.” However, what most people refer to as the “Merovingian dynasty” often includes Childeric I. The Carolingian section is more complicated: Charles the Fat was originally king of East Francia, while Eudes and Raoul were not Carolingian by blood. Dynasty classification therefore directly affects results such as “count monarchs by dynasty.” Classification rules should be defined separately and stored as metadata.
Second, one name may correspond to multiple identities. Both Louis I and Charles II appear in the Carolingian section, but they are not simply two “Louis” or two “Charles” entries within the same dynasty. Louis I is Louis the Pious, counted as the first Louis in the traditional French sequence. Charles II is Charles the Bald; he is Charles II in the West Frankish sequence, but he is often counted as Charles I when all Carolingian rulers are considered together. Charlemagne is also sometimes referred to as Charles I in certain numbering systems. If a localized name is treated as the primary key, gaps or conflicts may appear between entries such as Louis I and Louis V. Any name with an ordinal should therefore be split into two fields: a base name and an ordinal. A numbering-convention note should also be attached.
Third, a reign interval is itself a modeling object. The source contains at least four forms of reign interval:
- Chlothar I “reunited the kingdom” in 558 and, after his death in 561, the kingdom was divided again;
- Chlothar II was initially limited to Neustria and only unified all of Francia in 613;
- Louis III and Carloman II appear together as co-rulers;
- Charles the Fat ruled across East Francia and West Francia, representing succession across kingdoms.
There are also cases involving temporal adjacency, such as Clovis II preceding Chlothar III; confusable same names, such as Chlothar I, II, and III; and periods with excluded rulers, such as the predecessor of Dagobert III. These cannot be fully represented by a single “start year/end year” field.
Fourth, “unification” and “division” are computable states. Terms such as “unified,” “divided,” and “inherited a kingdom” are essentially changes in the overall state of the Frankish kingdom over time. Once each person’s reign interval is stored accurately, periods of unification and division can be derived through interval-coverage calculations rather than maintained manually.
Fifth, information quality varies. The source explicitly notes that Faramund is “very likely a fictional figure” and that records about Clodion are “still sparse.” The entry for Childeric I contains only one father-son relationship, and after Dagobert I many entries contain only names. The model must therefore allow “identity without dates” and use a confidence field to distinguish historical fact, inference, and legend.
2. Data Model Design
2.1 Core entities and relationships
A hybrid approach is recommended: a relational database as the core, with a graph query layer, such as a property graph, for relationship exploration.
- Entities: Person, Reign, Dynasty, Kingdom, Portrait, Source.
- Relationships: reign, father/son, brother, succession, marriage, evidence.
Making Reign a separate entity is the most important modeling decision. The reasons are:
- the same person may reign multiple times in different kingdoms or under different titles;
- multiple rulers may reign concurrently during the same period;
- each reign can have its own evidence and confidence metadata.
erDiagramPERSON ||--o{ REIGN : "holds"DYNASTY ||--o{ PERSON : "member_of"REIGN }o--|| KINGDOM : "rules"REIGN }o--o{ EVIDENCE : "supported_by"PORTRAIT ||--|| EVIDENCE : "visual_source"SOURCE ||--o{ EVIDENCE : "text_source"PERSON {string person_id PKstring base_name "Base name, e.g. Chlothar"int ordinal "Ordinal, e.g. 1"string identity_status "attested / thin / legendary"float confidence "0 to 1"}REIGN {int reign_id PKstring person_id FKstring kingdom_code FKint start_date "YYYYMMDD"int end_date "YYYYMMDD"string span_type "sole / co_ruler / sub_king"string source_note "Original annotation"}KINGDOM {string kingdom_code PKstring display_name "e.g. Soissons"string full_name "e.g. West Francia"}
2.2 Person table: identity status and name decomposition
-- identity_status: attested (supported by sources) / thin (sparse records) / legendary (legendary or fictional)CREATE TABLE person (person_id VARCHAR(32) PRIMARY KEY,base_name VARCHAR(64) NOT NULL, -- Base name, e.g. Chlotharordinal SMALLINT, -- 1/2/3; leave NULL for figures such as Faramunddisplay_name VARCHAR(96) NOT NULL, -- e.g. Chlothar Iname_variants JSONB, -- Variants: {"la":"Chlothar I","en":"Chlothar I","alias":["Chlothar I"]}dynasty_code VARCHAR(32) NOT NULL, -- Classification rules are defined separatelyidentity_status VARCHAR(16) NOT NULL CHECK (identity_status IN ('attested','thin','legendary')),confidence NUMERIC(3,2) NOT NULL DEFAULT 0.80,portrait_id VARCHAR(32), -- Linked entry in the portrait catalogueCONSTRAINT uq_person_name UNIQUE (base_name, ordinal));
Two design points are important:
base_nameandordinalare jointly unique, which fundamentally prevents duplicate entries such as “two Clovis I.”name_variantsstores alternate names in JSON, including Latin, English, and localized variants. Different translations may not be consistent, so a variant dictionary is also useful for synonym search.
2.3 Reign table: one model for multiple interval types
CREATE TABLE kingdom (kingdom_code VARCHAR(32) PRIMARY KEY, -- FRANCIA / PARIS / SOISSON / NEUST / AUST / WEST_FRANCIA / EAST_FRANCIAdisplay_name VARCHAR(32) NOT NULL,full_name VARCHAR(64) NOT NULL, -- e.g. West Franciasort_order SMALLINT NOT NULL);CREATE TABLE reign (reign_id SERIAL PRIMARY KEY,person_id VARCHAR(32) NOT NULL REFERENCES person(person_id),kingdom_code VARCHAR(32) NOT NULL REFERENCES kingdom(kingdom_code),span_type VARCHAR(16) NOT NULL CHECK (span_type IN ('sole','co_ruler','sub_king')),-- Dates are stored as YYYYMMDD integers. Missing parts are padded with 0, e.g. 0558 or 0481 when only the year is known.start_date INT NOT NULL,end_date INT NOT NULL,seq_in_kingdom SMALLINT, -- Sequence within the same kingdomnotes TEXT, -- Original annotations, preserved as-issource_ref VARCHAR(64), -- Evidence reference, linked to the evidence tableCONSTRAINT ck_reign_range CHECK (start_date <= end_date));CREATE INDEX idx_reign_kingdom_range ON reign (kingdom_code, start_date, end_date);CREATE INDEX idx_reign_person ON reign (person_id);
The original entries can be mapped as follows:
| Source entry | Person record | Reign record |
|---|---|---|
| Clovis I (reigned from 481, died in 511, kingdom divided among four sons) | Clovis/1 | FRANCIA, sole, 0481–0511 |
| Childebert I, inherited the Kingdom of Paris | Childebert/1 | PARIS, sub_king, 0511–0558 |
| Chlothar I, inherited the Kingdom of Soissons; reunited Francia in 558 | Chlothar/1 | SOISSON, sub_king, 0511–0558; FRANCIA, sole, 0558–0561 |
| Charles the Fat, briefly unified Francia | Charles/3 under Carolingian numbering | EAST_FRANCIA, sole, 0881–0887; FRANCIA, sole, 0884–0887 |
| Louis III and Carloman II | Louis/3, Carloman/2 | WEST_FRANCIA, co_ruler, 0879–0882; 0879–0884 |
The dates in this table are approximate values added for illustration. Details such as the exact month in which Charles the Fat took control of West Francia, and the death year of Louis III, differ across sources. When building a production dataset, these should be checked item by item and their sources preserved.
Two modeling decisions deserve explanation:
- Charles the Fat has multiple relevant status points. He was king of East Francia, was crowned emperor in 881, and succeeded to the West Frankish throne in 884. He should not be recorded only as “King of West Francia.”
- Entries without an explicit kingdom are not necessarily kingdom-agnostic. For example, Chlothar II was only king in Neustria before 613 and became sole king of all Francia only after 613. This information must be filled in during modeling; otherwise, overlap calculations may produce incorrect unified periods.
2.4 Dual timeline: historical validity and record validity
Historical data will continue to be corrected. A bitemporal modeling approach is useful:
- Valid time: the historical period itself, represented by
start_dateandend_date. - Transaction time: the time when the record was written, revised, or retired in the database, represented by audit fields such as
created_at,valid_from, andvalid_to.
With this approach, any query can be interpreted in two ways: “according to current understanding” or “according to the understanding at a particular point in time.” Revisions are not lost, and traceability and audit requirements can be satisfied.
2.5 Kinship and unified periods
Kinship should be stored in a separate table to avoid duplicating father-son and brother relations inside the person table.
CREATE TABLE kinship (from_person VARCHAR(32) REFERENCES person(person_id),to_person VARCHAR(32) REFERENCES person(person_id),relation VARCHAR(16) NOT NULL CHECK (relation IN ('father','mother','son','brother')),PRIMARY KEY (from_person, to_person, relation));
“Unified periods” do not need to be maintained manually. They can be derived from reign intervals using SQL. The algorithm is based on a classic sweep-line approach: each reign interval is split into two events, “start +1” and “end -1.” After sorting events by date and accumulating them, the number of concurrent rulers at any point can be obtained. Continuous intervals where the count is exactly 1 correspond to periods with a single ruler.
The following example treats end_date as an open interval. Each end event is shifted by adding 0101 to avoid incorrectly marking the death day itself as “already departed.”
WITH events AS (SELECT start_date AS d, 1 AS delta, reign_id FROM reignWHERE kingdom_code = 'FRANCIA'UNION ALLSELECT end_date + 101, -1, reign_id FROM reignWHERE kingdom_code = 'FRANCIA'),scan AS (SELECTd,SUM(delta) OVER (ORDER BY d, deltaROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS concurrent_kings,SUM(CASE WHEN delta = 1 THEN 1 ELSE 0 END) OVER (ORDER BY d, deltaROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS opensFROM events)SELECTd - 1 AS seg_start, -- Segment start: the day before the current eventLEAD(d) OVER (ORDER BY d) - 1 AS seg_end, -- Segment end: the day before the next eventconcurrent_kings,opens -- 1 means a new ruler begins in this segmentFROM scanWHERE concurrent_kings = 1; -- One ruler corresponds to a unified period
The scan output can then be aggregated into continuous unified periods with Python:
def merge_unified_periods(segments):"""Merge single-point segments into continuous unified periods.segments: [(seg_start, seg_end, concurrent_kings, opens), ...]"""periods, current = [], Nonefor start, end, concurrent, opens in segments:if concurrent != 1:current = Nonecontinue# opens == 1 means a new ruler acceded, so this is treated as a new unified segment even if it touches the previous one.if current and not opens and current[1] + 1 == start:current = (current[0], end)else:if current:periods.append(current)current = (start, end)if current:periods.append(current)return periods
In this illustrative dataset, the timeline can be bounded by the accession of Clovis I and the death of Louis V. The approximate unified periods are as follows:
| Unified period | Approximate interval | Sole ruler(s) | Reason for ending |
|---|---|---|---|
| 1 | 481–511 | Clovis I | Died; kingdom divided among four sons |
| 2 | 558–561 | Chlothar I | Died; kingdom divided among sons |
| 3 | 613–639 | Chlothar II, then Dagobert I | Dagobert I died |
| 4 | 639–657 | Clovis II | Died |
| 5 | 673–691 | Theuderic III | Died |
| 6 | 691–714 | Clovis IV, Childebert III, Dagobert III | Dagobert III died; period of civil conflict followed |
| 7 | 721–737 | Theuderic IV | Died; vacancy followed |
| 8 | 743–751 | Childeric III | Deposed |
| 9 | 751–768 | Pepin | Died; Francia divided between two sons |
| 10 | 771–840 | Charlemagne, Louis I | Louis I died |
| 11 | 843–855 | Charles the Bald in West Francia | Associated with the death of Lothair I |
| 12 | 861–863 | Charles the Bald in West Francia | Louis II moved south |
| 13 | 866–875 | Charles the Bald in West Francia | Louis II died |
| 14 | 884–887 | Charles the Fat | Deposed |
Minor timing details, such as the early death of Carloman II and the elevation of Robertian claimants, are not included here. In production data, they should be verified one by one.
Unified periods can directly validate claims in the original catalogue because the scan logic itself provides evidence:
- Periods 4 through 8 provide a precise definition of “reunification.” Chlothar II became sole king of all Francia in 613, and later periods of unity are continuations of that state.
- The claim that Charles the Fat’s unification was brief is supported. He held both East Francia and West Francia only during 884–887.
- Between periods 3 and 8, there were also short non-unified intervals. For example, during the long span of 640–673, Neustria, Austrasia, and Burgundy were often ruled by different royal branches. This helps explain the later decline of central kingship, often associated with the so-called “do-nothing kings.”
On the other hand, if only the FRANCIA line is considered, the scan may show “count greater than 1” continuously after 884–887, which would miss an important historical fact. After Charles the Fat was deposed, East Francia passed to his nephew Arnulf, while West Francia was contested by Odo and later by Charles the Simple from a Carolingian branch. Until 987, there was no universally recognized sole ruler of all Francia. The kingdom dimension should therefore be split at least into WEST_FRANCIA and EAST_FRANCIA, and the unified-period rule should be adjusted accordingly.
3. Multi-Source Conflicts and Confidence
The same historical figure may appear differently in engravings, chronicles, and later history books. Evidence should therefore be modeled explicitly.
CREATE TABLE evidence (evidence_id SERIAL PRIMARY KEY,evidence_type VARCHAR(16) NOT NULL CHECK (evidence_type IN ('portrait','chronicle','modern_work')),title VARCHAR(128) NOT NULL,author VARCHAR(64),produced_year INT,supports JSONB NOT NULL, -- Claims: [{"entity":"person:fr-006","field":"start_date","value":481,"stance":"support"}]reliability NUMERIC(3,2) NOT NULL);CREATE TABLE person_conflict (conflict_id SERIAL PRIMARY KEY,person_id VARCHAR(32) REFERENCES person(person_id),field_name VARCHAR(32) NOT NULL,value_a TEXT, value_b TEXT,stance_a VARCHAR(16), stance_b VARCHAR(16),resolution VARCHAR(16) NOT NULL, -- pending / adopt_a / adopt_b / keep_bothresolved_by VARCHAR(64), resolved_at TIMESTAMP);
Several principles should be applied:
- Evidence grading. Contemporary or near-contemporary chronicles are generally more reliable than later retellings. Engravings are useful visual evidence for identity and inscriptions, but they should not be used as the sole basis for dates.
- Preserve conflicts. When contradictory information is found, it should not be silently overwritten. It should be recorded in
person_conflictand adjudicated by an editor. - Confidence can be calculated. A person’s confidence can initially be initialized as a weighted average of evidence reliability and then overwritten after manual review.
- Legendary figures should be separated. Figures such as Faramund should have a person record but no real reign, or they can be represented by a placeholder interval of type
legacyand excluded from statistics.
For boundary questions such as “Who was the first king?”, the model does not need to decide which answer is “correct.” It should record different criteria. For example, Merovech appears in sixth-century sources, but contemporary records about him are largely lost, and it is uncertain whether he held the formal title of “king.” Whether he should be counted as the “first monarch supported by historical evidence” can be marked with a criteria_version field. The same dataset can then support multiple counting conventions.
4. Image Assets and Dating Risks
4.1 Portrait asset model
Each engraving should be treated as an independent asset. A high-resolution digital file, a consistent naming convention, and complete provenance and rights information are all necessary.
{"portrait_id": "fr-portrait-0006","person_id": "fr-006","inscription": "Chlodoveus Rex Francorum","medium": "engraving","object_uri": "oss://historical-portraits/fr/0006.tif","sha256": "9f2c...","width": 1240, "height": 1860,"plate_no": 6,"catalogue_note": "Plate 6 in the catalogue; inscription corresponds to Clovis I","rights": "public-domain-scan","checksum_verified_at": "2025-01-01T00:00:00Z"}
Large engraving collections may require substantial image storage and distribution. Common cloud capabilities can be used:
- object storage for master files and derived images;
- a content delivery network to accelerate access;
- prefix-triggered functions to generate thumbnails and progressive image formats automatically;
- logging and monitoring services to track access anomalies and storage capacity.
These capabilities should be evaluated as candidates, and the final design should be tested and costed.
4.2 Required dating-risk annotations
The original catalogue dates the engravings to the “16th century” but also states that the collection includes Louis XIV. Louis XIV acceded in 1643 and died in 1715, so no 16th-century engraver could have depicted him. The most reasonable explanation is that information comes from different editions or sources, such as a later re-engraving of an older edition or a later addition. The data model should preserve this contradiction rather than choose one side arbitrarily.
{"catalogue_id": "fr-engraving-set","dating": {"value": 1600,"precision": "century","confidence": 0.45,"constraints": [{"type": "terminus_post_quem", "year": 1643, "reason": "Includes a portrait of Louis XIV"},{"type": "terminus_ante_quem", "year": 1715, "reason": "Year of death of Louis XIV"}],"status": "conflict_pending","note": "The 16th-century dating conflicts with part of the content. It may be a mixture of different editions and needs verification against the source copy."},"attribution": {"creator": "Nicolas de Larmessin","confidence": 0.7,"note": "Several members of the Larmessin engraving family share this name; the exact author requires further research."}}
This leads to a general approach for date annotation:
- record both precision and confidence for time values;
- support two constraint types: “not earlier than a certain year” (
terminus post quem) and “not later than a certain year” (terminus ante quem); - use a status field to indicate whether a conflict exists.
This method applies equally to uncertain dates such as birth and death years, or reign start and end dates.
5. API Design and Analysis Scenarios
5.1 Read APIs
GET /api/v1/persons?dynasty=merovingian&identity_status=attested&page=1&size=20GET /api/v1/persons/{person_id} # Person details: dates, reigns, kinship, portraits, evidenceGET /api/v1/reigns?kingdom=FRANCIA&overlap_with=0558-0561GET /api/v1/unified-periods?kingdom=FRANCIAGET /api/v1/lineage?from=fr-006&depth=3 # Kinship and succession subgraph
All time parameters should use numeric formats such as YYYY or YYYYMMDD to make parsing, sorting, and validation easier.
5.2 Typical analyses
- Reign duration ranking: actual duration can be calculated as the difference between start and end dates plus one day, with excluded co-ruling periods removed. Results can retain both days and years.
- Division and reunification: expressions such as “the kingdom was divided among sons” and “the kingdom was reunited” can be mapped to splits and merges of unified periods.
- Father-son succession chains: recursive queries can traverse the
kinshiptable and mark points where the succession chain breaks. - Homonym disambiguation: grouping by
base_namecan reveal where additional aliases or descriptive terms are needed.
Example queries are shown below.
-- 1) Calculate actual reign days in FRANCIA after clipping overlapping intervalsWITH merged AS (SELECT person_id,start_date,LEAST(end_date, COALESCE(LEAD(start_date) OVER (PARTITION BY person_id ORDER BY start_date), end_date)) AS clipped_endFROM reignWHERE kingdom_code = 'FRANCIA')SELECT person_id,SUM(to_date(clipped_end::text, 'YYYYMMDD')- to_date(start_date::text, 'YYYYMMDD') + 1) AS actual_daysFROM mergedGROUP BY person_idORDER BY actual_days DESCLIMIT 10;-- 2) Father-son succession: check whether a son acceded in or before the father's death yearSELECT c.display_name AS son, p.display_name AS fatherFROM kinship kJOIN person c ON c.person_id = k.to_personJOIN person p ON p.person_id = k.from_personWHERE k.relation = 'father'AND EXISTS (SELECT 1 FROM reign rcJOIN reign rp ON rp.person_id = p.person_id AND rp.kingdom_code = 'FRANCIA'WHERE rc.person_id = c.person_idAND rc.kingdom_code = 'FRANCIA'AND rc.start_date <= rp.end_date + 101);
6. Data Quality Rules and Validation
Data quality should be treated as a first-class engineering concern. Every rule should be expressed as an executable check.
| ID | Rule | Severity | Description |
|---|---|---|---|
| Q1 | Ordinal uniqueness | Error | (base_name, ordinal) must not be duplicated |
| Q2 | Date validity | Error | Start and end years must be positive integers not later than 1715, and start_date <= end_date |
| Q3 | Identity consistency | Error | A person with identity_status = legendary must not have a real reign |
| Q4 | Lifespan contains reign | Warning | A reign interval must fall within the person’s lifespan, allowing ±1 year of error |
| Q5 | Reign overlap | Warning | Overlapping reigns for the same monarch, kingdom, and period require manual confirmation |
| Q6 | Orphan kinship | Warning | Both ends of a kinship relation must reference valid persons |
| Q7 | Portrait binding | Warning | Each monarch should be associated with at least one portrait, and the inscription should match the base name plus ordinal |
| Q8 | Dating conflict | Warning | Catalogue dating must satisfy all constraints; otherwise, the item should enter a manual verification queue |
Validation should be implemented as repeatable jobs, such as scheduled daily tasks, with results written to a data-quality dashboard. Error-level issues should block publication, while warning-level issues should enter a manual review queue.
7. Visualization Design
- Timeline swimlane view: This is the core visualization. The horizontal axis represents years, and each lane represents one monarch. Color blocks distinguish reign type, such as sole rule, co-rule, or sub-king status. Division periods and unified periods can be distinguished with background colors. Chlothar I’s two reign intervals can appear as two blocks in the same lane, while Charles the Fat can span both East Francia and West Francia lanes. It becomes immediately visible who ruled at the same time as whom.
- Genealogy tree: Father-son relations form the main structure, while sibling and marriage relations are shown with connecting lines. Legendary figures can be distinguished with dashed borders.
- Relationship graph: Persons are nodes, relationships are edges, and node size can be tied to reign duration or evidence count. This is useful for exploring influence and succession networks.
- Large image browsing: When the number of engravings is large, tile-based slicing and progressive loading can avoid loading all original images at once.
Accessibility should also be considered:
- color should not be the only information carrier; textures or patterns should also distinguish reign types;
- every color block should provide readable labels and tooltips;
- chart data should also be available in table form for users of assistive technologies or text-based environments.
8. Delivery Path
| Phase | Goal | Key deliverables | Acceptance criteria |
|---|---|---|---|
| Phase 1 | Ingestible and searchable | Person, reign, and kingdom core tables; import scripts | All 35 source entries are imported with no orphan records |
| Phase 2 | Analyzable | Unified-period scan, reign-duration calculation, kinship query APIs | Scan results match source annotations, and differences are documented |
| Phase 3 | Traceable | Evidence table, conflict table, date-annotation specification | Every conclusion can be traced to an engraving or source |
| Phase 4 | Extensible | Queens, regents, capitals, and map layers | New entities can be added without changing existing table structures |
| Phase 5 | Presentable | Timeline, genealogy tree, relationship graph, and accessibility support | Usable in major browsers and with screen readers |
Two additional points should be considered during import:
- Not every monarch in the source has an ordinal number. For example, the entry before Hugh Capet lacks an ordinal. Both the original ordinal and a computed ordinal should be preserved.
- Layout information such as “left/right” should be recorded as spatial properties of catalogue entries, not mixed into person identity fields.
Conclusion
The value of this French monarch engraving collection is not limited to the images themselves. Once the fiction around Faramund, the sparse records of Clodion, the two reunifications associated with Chlothar I, and the brief unification of Charles the Fat are transformed into structured data, many previously ambiguous questions can be answered through queries: who ruled at the same time, when the kingdom divided, and where a genealogical chain breaks.
This approach can be reused for any historical material that consists of “person lists + time intervals + relationship networks”: decompose lists into entities and relationships, treat intervals as first-class objects, model uncertainty explicitly, and automate quality rules. The value of the data asset comes precisely from these seemingly small modeling decisions.
