import React, { useState, useMemo } from "react"; const C = { ground: "#0C2942", panel: "#123A5C", raised: "#19486C", ink: "#EDE3CE", dim: "#9FB4C6", faint: "#6C889F", gold: "#D9A94B", verd: "#74B39B", cinn: "#C4472F", line: "rgba(237,227,206,0.18)", }; const STATUS = { resolved: { c: C.verd, label: "Resolved" }, partial: { c: C.gold, label: "Partly resolved" }, open: { c: C.cinn, label: "Still open" }, dissolved: { c: C.faint, label: "No longer arises" }, }; const LENSES = [ { id: "text", name: "As written", who: "No harmonisation applied", claim: "Read both lists flatly, with no reconciling assumption. This is the starting position, and every problem is live.", cost: "Two irreconcilable lists sit in the same New Testament. Something has to give.", status: { q1: "open", q2: "open", q3: "open", q4: "open", q5: "open", q6: "open" }, edges: {}, }, { id: "levirate", name: "Levirate marriage", who: "Julius Africanus, preserved in Eusebius", claim: "Where a man died childless, his brother raised offspring in his name (Deuteronomy 25:5-6). Such a son has two fathers on the record: one who begot him, one whose name he carries. Africanus reports that Estha bore Jacob to Matthan of Solomon's line and Heli to Melchi of Nathan's line; Heli died childless and Jacob raised offspring for him.", cost: "It needs the same rare arrangement to recur at Shealtiel and again at Joseph. Africanus writes in the third century and names no earlier source but family tradition.", status: { q1: "open", q2: "resolved", q3: "resolved", q4: "open", q5: "resolved", q6: "dissolved" }, edges: { shealtiel: { left: "Named father", right: "Begetter" }, joseph: { left: "Begetter", right: "Named father" }, }, }, { id: "mariam", name: "Luke traces Mariam", who: "A reading current since the late medieval period", claim: "Luke gives Mariam's descent, not Joseph's. Heli is her father, and Joseph enters the list as his son-in-law. The lists never converge at Joseph biologically because they were never both his.", cost: "Luke's Greek most naturally makes Joseph the son of Heli. No writer is known to have read it this way before roughly the fifteenth century, which is a long silence.", status: { q1: "open", q2: "resolved", q3: "open", q4: "open", q5: "resolved", q6: "resolved" }, edges: { joseph: { left: "Joseph's father", right: "Mariam's father" }, shealtiel: { left: "Royal house", right: "Another family" }, }, }, { id: "title", name: "Title and bloodline", who: "The position David Mitchell argues", claim: "Both lists are accurate and both are necessary. Solomon's line carries the legal claim to the throne but runs through Jeconiah, of whom Jeremiah 22:30 says no offspring will sit on David's throne. Nathan's line carries blood untouched by that judgement. Jesus receives the title through Joseph and the blood through Mariam, and so is not the natural offspring of the cursed generation.", cost: "It rests on a medieval Jewish manuscript the article does not name. Until that source is identified and dated, the reconstruction cannot be checked.", status: { q1: "partial", q2: "resolved", q3: "partial", q4: "partial", q5: "resolved", q6: "resolved" }, edges: { shealtiel: { left: "Legal line", right: "Blood line" }, joseph: { left: "Throne-right", right: "Blood" }, }, }, { id: "critical", name: "Theological construction", who: "Raymond Brown, David Flusser", claim: "The lists are not descent records. Each evangelist built a genealogy to make a claim about who Jesus is, and the two disagree because they were composed independently for different purposes.", cost: "The contradictions stop being a problem, but so does the evidence that Jesus descended from David at all. Both evangelists plainly meant these as descent.", status: { q1: "dissolved", q2: "dissolved", q3: "dissolved", q4: "dissolved", q5: "dissolved", q6: "dissolved" }, edges: {}, }, ]; const QUESTIONS = { q1: { n: 1, title: "Why does Matthew leave names out?", problem: "Matthew's list is shorter than the record it draws on. Between Joram and Uzziah he passes over three reigning kings, and between Josiah and Jeconiah he passes over Jehoiakim. He then states that there are three sets of fourteen generations, though the last set counts thirteen.", sources: [ { ref: "Matthew 1:8", text: "Joram is followed directly by Uzziah." }, { ref: "1 Chronicles 3:11-12", text: "Ahaziah, Joash and Amaziah reigned between them." }, { ref: "Matthew 1:11", text: "Josiah is followed directly by Jeconiah." }, { ref: "Matthew 1:17", text: "Three sets of fourteen generations are claimed." }, ], answers: [ "Semitic genealogies commonly skip generations. To beget can mean to be ancestor of, and a shortened list is not a false one.", "The omitted kings descend from Ahab through Athaliah, and may have been struck out as a judgement on that house.", "The fourteens are a mnemonic structure, possibly counting the Hebrew letters of David's name.", "The numbering slipped in transmission.", ], }, q2: { n: 2, title: "Was Shealtiel's father Jeconiah or Neri?", problem: "The two lines meet at Shealtiel, but they arrive with different fathers. Matthew brings him from the royal house through Jeconiah. Luke brings him from Nathan's line through Neri.", sources: [ { ref: "Matthew 1:12", text: "Jeconiah fathered Shealtiel." }, { ref: "1 Chronicles 3:17", text: "Shealtiel is listed among Jeconiah's sons." }, { ref: "Luke 3:27", text: "Shealtiel is called the son of Neri." }, ], answers: [ "One father begot him and the other gave him his name, under levirate custom or adoption.", "Two men of the same name in the same generation, which is common enough in these lists.", "The lines belong to two different families and only appear to meet.", ], }, q3: { n: 3, title: "Was Zerubbabel the son of Shealtiel or of Pedaiah?", problem: "Both gospels make Zerubbabel the son of Shealtiel, and Ezra and Haggai agree. Chronicles makes him the son of Pedaiah, Shealtiel's brother.", sources: [ { ref: "Matthew 1:12, Luke 3:27", text: "Zerubbabel son of Shealtiel." }, { ref: "Ezra 3:2, Haggai 1:1", text: "The same descent." }, { ref: "1 Chronicles 3:19", text: "Pedaiah's sons were Zerubbabel and Shimei." }, ], answers: [ "Shealtiel died childless and Pedaiah raised offspring in his name, so Zerubbabel is legally the one and naturally the other.", "Shealtiel adopted his brother's son.", "A Greek witness to Chronicles reads Shealtiel here, so the difference may be textual.", ], }, q4: { n: 4, title: "Which sons did Zerubbabel have?", problem: "The lines part again immediately after Zerubbabel, and neither continues through a son Chronicles names. Matthew goes on through Abiud, Luke through Rhesa, and Chronicles lists seven sons, none of them either.", sources: [ { ref: "Matthew 1:13", text: "Zerubbabel fathered Abiud." }, { ref: "Luke 3:27", text: "Rhesa follows Zerubbabel." }, { ref: "1 Chronicles 3:19-20", text: "Meshullam, Hananiah, Hashubah, Ohel, Berechiah, Hasadiah and Jushab-hesed.", }, ], answers: [ "The Chronicles list is partial, and a genealogy need not name every son.", "Abiud and Rhesa are second names, or stand further down the line than they appear.", "Rhesa may not be a name at all. The Aramaic word for prince is close to it, and if a title was read as a name Luke's line would run straight from Zerubbabel to Joanan.", ], }, q5: { n: 5, title: "Was Joseph's father Jacob or Heli?", problem: "The last convergence is the sharpest. Matthew ends with Jacob fathering Joseph. Luke begins with Joseph as the son of Heli.", sources: [ { ref: "Matthew 1:16", text: "Jacob fathered Joseph, the husband of Mariam." }, { ref: "Luke 3:23", text: "Joseph, as was supposed, of Heli." }, ], answers: [ "Jacob and Heli were half-brothers by the same mother. Heli died childless, Jacob raised offspring for him, and Joseph carries both names.", "Heli is Mariam's father and Joseph is entered as his son-in-law.", "One of the two names was supplied by the evangelist rather than drawn from a record.", ], }, q6: { n: 6, title: "Is Luke's list Mariam's descent?", problem: "If Luke traces Mariam rather than Joseph, several of these problems stop being problems. The question is whether the text will carry that reading.", sources: [ { ref: "Luke 3:23", text: "The phrase as was supposed brackets Joseph before the list begins." }, { ref: "Luke 1-2", text: "Luke's opening chapters are told largely from Mariam's side." }, { ref: "Talmud, Sanhedrin 106a", text: "Mariam is called a daughter of rulers and of a segan." }, ], answers: [ "Luke marks Joseph off as only supposed to be the father, then gives the line that actually carried the blood.", "A daughter's descent could be entered under her husband's name where there was no son.", "The Greek reads Joseph as the son of Heli, and Jewish genealogies traced through fathers. The Mariam reading appears late.", ], }, }; const solomonSeg = [ "Solomon", "Rehoboam", "Abijah", "Asa", "Jehoshaphat", "Joram", { n: "Ahaziah", cut: true }, { n: "Joash", cut: true }, { n: "Amaziah", cut: true }, "Uzziah", "Jotham", "Ahaz", "Hezekiah", "Manasseh", "Amon", "Josiah", { n: "Jehoiakim", cut: true }, "Jeconiah", ]; const nathanSeg = [ "Nathan", "Mattatha", "Menna", "Melea", "Eliakim", "Jonam", "Joseph", "Judah", "Simeon", "Levi", "Matthat", "Jorim", "Eliezer", "Joshua", "Er", "Elmadam", "Cosam", "Addi", "Melchi", "Neri", ]; const abiudSeg = ["Abiud", "Eliakim", "Azor", "Zadok", "Achim", "Eliud", "Eleazar", "Matthan", "Jacob"]; const rhesaSeg = [ "Rhesa", "Joanan", "Joda", "Josech", "Semein", "Mattathias", "Maath", "Naggai", "Esli", "Nahum", "Amos", "Mattathias", "Joseph", "Jannai", "Melchi", "Levi", "Matthat", "Heli", ]; const nameOf = (x) => (typeof x === "string" ? x : x.n); const isCut = (x) => typeof x !== "string" && x.cut; const W = 480; const LX = 130, RX = 350, MX = 240; const RAIL_W = 160, SHARED_W = 240; const NODE_H = 46, TALL_H = 66, GAP = 28, ROW_H = 24; function buildLayout(expanded, edges) { const blocks = [ { kind: "shared", id: "david", label: "David", sub: "2 Samuel 7" }, { kind: "split", id: "seg1", left: solomonSeg, right: nathanSeg, q: "q1", leftHead: "Solomon's line", rightHead: "Nathan's line" }, { kind: "shared", id: "shealtiel", label: "Shealtiel", q: "q2" }, { kind: "shared", id: "zerubbabel", label: "Zerubbabel", q: "q3" }, { kind: "split", id: "seg2", left: abiudSeg, right: rhesaSeg, q: "q4", leftHead: "Through Abiud", rightHead: "Through Rhesa" }, { kind: "shared", id: "joseph", label: "Joseph of Nazareth", q: "q5" }, { kind: "shared", id: "jesus", label: "Jesus", sub: "Called Messiah" }, ]; let y = 24; const out = blocks.map((b) => { const open = expanded.has(b.id); const h = b.kind === "shared" ? (edges[b.id] ? TALL_H : NODE_H) : open ? Math.max(b.left.length, b.right.length) * ROW_H + 34 : 62; const placed = { ...b, y, h, open }; y += h + GAP; return placed; }); return { blocks: out, height: y + 8 }; } function Rail({ x, w, y, h, color, dashed, children }) { return ( {children} ); } export default function GenealogyModule() { const [lensIdx, setLensIdx] = useState(0); const [openQ, setOpenQ] = useState(null); const [expanded, setExpanded] = useState(new Set()); const lens = LENSES[lensIdx]; const { blocks, height } = useMemo( () => buildLayout(expanded, lens.edges), [expanded, lens]); const toggle = (id) => setExpanded((prev) => { const next = new Set(prev); next.has(id) ? next.delete(id) : next.add(id); return next; }); const Badge = ({ q, x, y }) => { const st = STATUS[lens.status[q]]; const active = openQ === q; return ( setOpenQ(q)}> {QUESTIONS[q].n} ); }; const conn = (x1, y1, x2, y2) => `M ${x1} ${y1} C ${x1} ${y1 + 14}, ${x2} ${y2 - 14}, ${x2} ${y2}`; return (
The genealogies of Jesus

Matthew and Luke both trace Jesus to David, and they disagree. The two lines part, meet, part and meet again. Open a junction to see what each source says, then choose a reading below and watch which problems it settles and which it leaves standing.

Reading {LENSES.map((l, i) => ( ))}
{blocks.map((b, i) => { const prev = blocks[i - 1]; const lines = []; if (prev) { const py = prev.y + prev.h; if (prev.kind === "shared" && b.kind === "shared") lines.push(conn(MX, py, MX, b.y)); if (prev.kind === "shared" && b.kind === "split") { lines.push(conn(MX - 40, py, LX, b.y)); lines.push(conn(MX + 40, py, RX, b.y)); } if (prev.kind === "split" && b.kind === "shared") { lines.push(conn(LX, py, MX - 40, b.y)); lines.push(conn(RX, py, MX + 40, b.y)); } } return lines.map((d, k) => ( )); })} {blocks.map((b) => { if (b.kind === "shared") { const edge = lens.edges[b.id]; return ( {b.label} {b.sub && ( {b.sub} )} {edge && ( <> {edge.left} {edge.right} )} {b.q && } ); } const sides = [ { x: LX, arr: b.left, head: b.leftHead, color: C.gold }, { x: RX, arr: b.right, head: b.rightHead, color: C.verd }, ]; return ( {sides.map((s) => ( {s.head} {b.open ? s.arr.map((nm, i) => ( {nameOf(nm)} )) : ( {s.arr.filter((n) => !isCut(n)).length} generations )} ))} toggle(b.id)}> {b.open ? "Collapse" : "Expand"} {b.q && } ); })}
Prototype for a teaching module. Scripture references are given so you can read them in your own Bible. The fuller argument for the fourth reading is set out in chapter 5 of Jesus: The Incarnation of the Word.
); } function Marker({ status }) { const st = STATUS[status]; return ( {st.label} ); } function LensPanel({ lens, onOpen }) { return (
{lens.name}
{lens.who}

{lens.claim}

What this reading does to the six problems
{Object.entries(QUESTIONS).map(([k, q]) => { const st = STATUS[lens.status[k]]; return ( ); })}
What it costs you

{lens.cost}

); } function QuestionPanel({ q, lens, status, onBack }) { return (
{q.n} {q.title}

{q.problem}

What the sources say
{q.sources.map((s, i) => (
{s.ref}
{s.text}
))}
Answers that have been offered
    {q.answers.map((a, i) => (
  • {a}
  • ))}
Under {lens.name.toLowerCase()}

{lens.claim}

); }