Usage Guide: Adding a New Subject¶
This is the repeatable process for turning a new biographical source (a
paper, an oral history, an archive) into a new subjects/<slug>/ folder.
Follow it in order — each step depends on the one before. The live
version of this checklist lives in extraction/EXTRACTION_GUIDE.md.
Read the data model first
Before extracting anything, read
Data model reference — in particular what counts as
an "event" and the fuzzy-date chronology mechanism. Extraction is only
consistent if it follows that model exactly: don't improvise a new
event type or relation type mid-extraction. If nothing in the
controlled vocabulary fits, use "other" for events, or see
Extending & Contributing for how to propose a new
vocabulary value.
0. Read the whole source once, straight through¶
Before extracting anything, read the paper end to end to get the arc of the story. Note in passing: who are the recurring people, places, organizations, and named things (inventions, patents, products, books)? This becomes the seed list for the next step.
1. Draft entities.json¶
One entry per distinct person, place, organization, or artifact that will be referenced by at least one event or relation. Don't create an entity for something mentioned exactly once with no dateable connection to anything else, unless it will anchor a relation or event.
{
"id": "v_b_aleskovskii",
"entity_type": "person",
"name": "Valentin Borisovich Aleskovskii",
"summary": "Soviet chemist who independently discovered molecular layering, the Soviet-side counterpart to Suntola's Atomic Layer Epitaxy.",
"subtype": "researcher"
}
id: snake_case, derived from the name (v_b_aleskovskii, notperson_1).summary: static facts only — no dates, no "in 1974...". If a sentence has a "when," it belongs in an event instead.- Watch for id collisions between a place and an organization that share
a name (e.g. a company town) — suffix one (
_city/_oy) if needed, the waysubjects/suntola/entities.jsondistinguisheslohja_city(place) fromlohja_oy(organization).
2. Draft sources.json¶
At minimum, one entry for the source paper itself:
{
"id": "malygin2015",
"title": "Aleskovskii and the molecular layering method",
"authors": ["A. A. Malygin"],
"year": 2015,
"publication": "Some Journal",
"file": "data/malygin2015.pdf"
}
Add more entries only if the paper itself cites another primary source you're drawing directly from (an autobiography, an interview transcript).
3. Draft events.json¶
Walk the source again, this time pulling out every dateable occurrence that meets the four requirements from Data model reference (a date, however fuzzy; a type; at least one participant; at least one source citation).
{
"id": "aleskovskii_molecular_layering",
"event_type": "invention",
"label": "Aleskovskii formulates molecular layering",
"description": "Aleskovskii and Kol'tsov proposed the molecular layering method for surface synthesis of solid compounds.",
"date": { "display": "1965", "precision": "year", "sort_start": "1965-01-01", "sort_end": "1965-12-31" },
"location": "leningrad",
"participants": [
{ "entity_id": "v_b_aleskovskii", "role": "inventor" },
{ "entity_id": "molecular_layering", "role": "invention" }
],
"sources": [
{ "source_id": "malygin2015", "page": 4, "quote": "the molecular layering method was first proposed in 1965" }
]
}
Practical rules:
- Every event date must trace to something the text actually says. If
the text says "in the early 1970s,"
date.displayis"early 1970s"withprecision: "decade"— not a guessed exact year. - Quote sparingly, but quote the load-bearing sentence for pivotal events (the invention moment, the first public disclosure) so a reader can verify the claim without re-opening the source.
- Page numbers are the PDF's printed page number, not the PDF viewer's page index, so citations match what a human reader sees.
- Don't split one sentence into five events. A paragraph describing one coherent episode is one event with a fuller description.
- Capture connective-tissue events too — an organization founded, sold, or renamed; a collaborator's milestone that later matters to the subject — not just the subject's own life events. These are what make the graph interesting to explore, and what a future cross-subject bridge connects to.
4. Draft relations.json¶
For each event that implies a durable fact about the connection between
two entities (an employment, an invention, a founding, a visit), add a
corresponding relation with event_id pointing back to it:
{
"id": "aleskovskii_invented_molecular_layering",
"source": "v_b_aleskovskii",
"type": "invented",
"target": "molecular_layering",
"event_id": "aleskovskii_molecular_layering",
"sources": [{ "source_id": "malygin2015", "page": 4 }]
}
Then add any relations the source states as a fact without a specific
dateable event behind it (e.g. "they remained close collaborators for the
rest of their lives") — these stand alone, with no event_id.
Keep relations directed per the vocabulary's defined reading direction —
e.g. worked_at always reads person → organization, never the reverse.
See Data model reference for the full list.
5. Write subject.json¶
{
"slug": "aleskovskii",
"name": "V. B. Aleskovskii",
"summary": "Discoverer of molecular layering — from Malygin (2015)"
}
6. Validate and build¶
The build validates every file against the schemas and checks
referential integrity before writing dist/aleskovskii.html. Fix every
reported error — see Usage Guide
for a worked example of diagnosing one.
7. Open the built page and sanity-check it¶
Click through a handful of entities and events. Things to look for: nodes
with no connections at all (probably a relation is missing), events
clustered at implausible dates (probably a sort_start/sort_end typo),
and any name that renders as undefined (a broken id reference).
8. Once both subjects exist: cross-subject bridges¶
Create subjects/_bridges/<a>-<b>.json — an array of relation objects
using the same shape as relation.schema.json, except source/target
are qualified as "<slug>:<entity_id>":
[
{
"id": "suntola_met_aleskovskii_leningrad",
"source": "suntola:tuomo_suntola",
"target": "aleskovskii:v_b_aleskovskii",
"type": "met",
"event_id": "suntola:suntola_visits_leningrad",
"sources": [{ "source_id": "suntola:puurunen2014", "page": 341 }]
}
]
This keeps each subject file self-contained while still letting a later
combined view draw the edges between them. The Puurunen paper already
documents one such link — Suntola's 1990 visit to Leningrad to meet
Aleskovskii (subjects/suntola/events.json#suntola_visits_leningrad) —
so aleskovskii-suntola.json is the first bridge file this project will
need once subjects/aleskovskii/ exists.