From 658d95fa24d988f61b9829a6a0aa0135a3c06672 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:46:10 -0400 Subject: [PATCH 01/37] TKW: give events `aliases` and `mentions` - `EventSchema` gains `aliases` and `mentions`, both defaulting to `[]` - `lib/content-integrity.ts` validates `events.mentions` like `battles.mentions` - `lib/timeline.test.ts` event fixture carries the two new fields --- lib/content-integrity.test.ts | 24 ++++++++++++++++++++++++ lib/content-integrity.ts | 5 ++++- lib/schemas.test.ts | 30 ++++++++++++++++++++++++++++++ lib/schemas.ts | 2 ++ lib/timeline.test.ts | 2 ++ 5 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/content-integrity.test.ts b/lib/content-integrity.test.ts index a50384d6..caf9d41a 100644 --- a/lib/content-integrity.test.ts +++ b/lib/content-integrity.test.ts @@ -313,3 +313,27 @@ describe("content integrity", () => { expect(errors).toEqual([]); }); }); + +describe("event mentions", () => { + it("validates event mentions the same way as battle mentions", () => { + const errors = contentIntegrityErrors({ + ...emptyCollections(), + events: [ + { + body: "", + slug: "e", + frontmatter: EventSchema.parse({ + slug: "e", + name: "E", + type: "wedding", + date: LEGEND_DATE, + location: "nowhere", + landmass: "westeros", + mentions: ["no-such-entry"], + }), + }, + ], + }); + expect(errors).toEqual(["events/e.mentions: missing no-such-entry"]); + }); +}); diff --git a/lib/content-integrity.ts b/lib/content-integrity.ts index 745b4bb8..c3fd580f 100644 --- a/lib/content-integrity.ts +++ b/lib/content-integrity.ts @@ -224,7 +224,10 @@ function referenceErrors(collections: Collections): string[] { name: "events", entries: collections.events, targets, - rules: [{ to: "houses", read: participantHouses }], + rules: [ + { to: "houses", read: participantHouses }, + { to: "all", read: (fm) => ref("mentions", fm.mentions) }, + ], }), } satisfies Record; diff --git a/lib/schemas.test.ts b/lib/schemas.test.ts index d68da74c..7bbcdbea 100644 --- a/lib/schemas.test.ts +++ b/lib/schemas.test.ts @@ -366,3 +366,33 @@ describe("DragonSchema", () => { expect(() => DragonSchema.parse(input)).toThrow(); }); }); + +describe("EventSchema prose-link fields", () => { + it("defaults aliases and mentions to empty arrays", () => { + const parsed = EventSchema.parse({ + slug: "doom-of-valyria", + name: "The Doom of Valyria", + type: "disaster", + date: { year: 102, era: "BC", precision: "year" }, + location: "Valyria", + landmass: "essos", + }); + expect(parsed.aliases).toEqual([]); + expect(parsed.mentions).toEqual([]); + }); + + it("keeps the aliases and mentions it is given", () => { + const parsed = EventSchema.parse({ + slug: "doom-of-valyria", + name: "The Doom of Valyria", + type: "disaster", + date: { year: 102, era: "BC", precision: "year" }, + location: "Valyria", + landmass: "essos", + aliases: ["Doom"], + mentions: ["targaryen"], + }); + expect(parsed.aliases).toEqual(["Doom"]); + expect(parsed.mentions).toEqual(["targaryen"]); + }); +}); diff --git a/lib/schemas.ts b/lib/schemas.ts index ad3eaa52..5bf4e0eb 100644 --- a/lib/schemas.ts +++ b/lib/schemas.ts @@ -217,6 +217,8 @@ export const EventSchema = z.object({ participants: z.array(ParticipantSchema).default([]), outcome: z.string().optional(), casualties: z.array(z.string()).default([]), + aliases: z.array(z.string()).default([]), + mentions: z.array(z.string()).default([]), sources: z.array(SourceSchema).default([]), draft: z.boolean().default(false), }); diff --git a/lib/timeline.test.ts b/lib/timeline.test.ts index 379c72e3..e372e20e 100644 --- a/lib/timeline.test.ts +++ b/lib/timeline.test.ts @@ -65,6 +65,8 @@ const makeEvent = ({ landmass, participants: [], casualties: [], + aliases: [], + mentions: [], sources: [], draft: false, }); From 627a575aec2f77a47e29af9434ed1300783553ef Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:46:20 -0400 Subject: [PATCH 02/37] TKW: link castles, battles, and events from prose bodies - `buildProseLinkIndex` takes `allCastles`, `allBattles`, `allEvents` and emits `castle`, `battle`, `event` targets - a name starting with "The" also matches without the article, so "the Twins" and "the Red Wedding" link - self-suppression and once-per-page dedupe keyed by kind plus slug via `targetKey` - `ProseLinkIndex.selfSlug` becomes `self: { kind, slug }` - castles sharing a house's short name (Darry, Rosby, the Hightower) never auto-link; `mentions` cannot tell them apart - `targetsOf` replaces the four per-kind `flatMap` blocks --- lib/content.test.ts | 2 +- lib/prose-links.test.ts | 281 +++++++++++++++++++++++++++++++++++++++- lib/prose-links.ts | 222 ++++++++++++++++++++----------- 3 files changed, 426 insertions(+), 79 deletions(-) diff --git a/lib/content.test.ts b/lib/content.test.ts index 1533c84d..ef83ec87 100644 --- a/lib/content.test.ts +++ b/lib/content.test.ts @@ -65,7 +65,7 @@ describe("renderMarkdown", () => { surfaceForms: ["Catelyn Tully"], }, ], - selfSlug: null, + self: null, }, }); expect(html).toContain( diff --git a/lib/prose-links.test.ts b/lib/prose-links.test.ts index 9a0d51fc..9ddc7f0a 100644 --- a/lib/prose-links.test.ts +++ b/lib/prose-links.test.ts @@ -1,12 +1,30 @@ import { describe, it, expect } from "bun:test"; -import { buildProseLinkIndex, type ProseLinkIndex } from "@/lib/prose-links"; +import { + buildProseLinkIndex, + type ProseLinkIndex, + type ProseLinkKind, +} from "@/lib/prose-links"; import { renderMarkdown } from "@/lib/content"; -import type { Character, House, Weapon, Dragon } from "@/lib/schemas"; +import { + BattleSchema, + CastleSchema, + EventSchema, + type Battle, + type Castle, + type Character, + type Dragon, + type Event, + type House, + type Weapon, +} from "@/lib/schemas"; type CharacterFixture = { slug: string; frontmatter: Character }; type HouseFixture = { slug: string; frontmatter: House }; type WeaponFixture = { slug: string; frontmatter: Weapon }; type DragonFixture = { slug: string; frontmatter: Dragon }; +type CastleFixture = { slug: string; frontmatter: Castle }; +type BattleFixture = { slug: string; frontmatter: Battle }; +type EventFixture = { slug: string; frontmatter: Event }; function character( partial: Partial & Pick, @@ -83,9 +101,81 @@ const AERYS_II = character({ const STARK = house({ slug: "stark", name: "House Stark" }); const TARGARYEN = house({ slug: "targaryen", name: "House Targaryen" }); +const DATE = { year: 299, era: "AC", precision: "year" } as const; + +function castle(partial: { + slug: string; + name: string; + draft?: boolean; +}): CastleFixture { + const fm = CastleSchema.parse({ + slug: partial.slug, + name: partial.name, + type: "castle", + coords: { x: 100, y: 100 }, + draft: partial.draft ?? false, + }); + return { slug: fm.slug, frontmatter: fm }; +} + +function battle(partial: { + slug: string; + name: string; + aliases?: string[]; + draft?: boolean; +}): BattleFixture { + const fm = BattleSchema.parse({ + slug: partial.slug, + name: partial.name, + type: "battle", + start: DATE, + end: DATE, + aliases: partial.aliases ?? [], + draft: partial.draft ?? false, + }); + return { slug: fm.slug, frontmatter: fm }; +} + +function event(partial: { + slug: string; + name: string; + aliases?: string[]; + draft?: boolean; +}): EventFixture { + const fm = EventSchema.parse({ + slug: partial.slug, + name: partial.name, + type: "other", + date: DATE, + location: "Westeros", + landmass: "westeros", + aliases: partial.aliases ?? [], + draft: partial.draft ?? false, + }); + return { slug: fm.slug, frontmatter: fm }; +} + +const HARRENHAL = castle({ slug: "harrenhal", name: "Harrenhal" }); +const TWINS = castle({ slug: "the-twins", name: "The Twins" }); +const ASHFORD = castle({ slug: "ashford", name: "Ashford" }); +const PYKE = castle({ slug: "pyke", name: "Pyke" }); +const DARRY_CASTLE = castle({ slug: "darry", name: "Darry" }); +const DARRY_HOUSE = house({ slug: "darry", name: "House Darry" }); +const RED_WEDDING = battle({ slug: "red-wedding", name: "The Red Wedding" }); +const BATTLE_OF_ASHFORD = battle({ + slug: "battle-of-ashford", + name: "The Battle of Ashford", +}); +const STORMING_OF_PYKE = battle({ slug: "pyke", name: "The Storming of Pyke" }); +const DOOM = event({ + slug: "doom-of-valyria", + name: "The Doom of Valyria", + aliases: ["Doom"], +}); + function indexFor(args: { current: { - kind: "character" | "house" | "weapon" | "dragon"; + kind: ProseLinkKind; slug: string; mentions?: readonly string[]; }; @@ -93,6 +183,9 @@ function indexFor(args: { houses?: HouseFixture[]; weapons?: WeaponFixture[]; dragons?: DragonFixture[]; + castles?: CastleFixture[]; + battles?: BattleFixture[]; + events?: EventFixture[]; }): ProseLinkIndex { return buildProseLinkIndex({ allCharacters: args.characters ?? [ @@ -106,6 +199,9 @@ function indexFor(args: { allHouses: args.houses ?? [STARK, TARGARYEN], allWeapons: args.weapons ?? [], allDragons: args.dragons ?? [], + allCastles: args.castles ?? [], + allBattles: args.battles ?? [], + allEvents: args.events ?? [], current: { ...args.current, mentions: args.current.mentions ?? [] }, }); } @@ -342,6 +438,9 @@ describe("buildProseLinkIndex", () => { allHouses: [], allWeapons: [], allDragons: [], + allCastles: [], + allBattles: [], + allEvents: [], current: { kind: "character", slug: "self", mentions: ["rickard-stark"] }, }); const rickard = out.targets.find((t) => t.slug === "rickard-stark"); @@ -358,6 +457,9 @@ describe("buildProseLinkIndex", () => { allHouses: [STARK, TARGARYEN], allWeapons: [], allDragons: [], + allCastles: [], + allBattles: [], + allEvents: [], current: { kind: "house", slug: "self", mentions: ["stark"] }, }); const stark = out.targets.find((t) => t.slug === "stark"); @@ -405,6 +507,9 @@ describe("buildProseLinkIndex (weapons and dragons)", () => { allHouses: [], allWeapons: [{ slug: "blackfyre", frontmatter: weaponBase }], allDragons: [], + allCastles: [], + allBattles: [], + allEvents: [], current: { kind: "house", slug: "targaryen", mentions: [] }, }); const target = out.targets.find((t) => t.slug === "blackfyre"); @@ -418,6 +523,9 @@ describe("buildProseLinkIndex (weapons and dragons)", () => { allHouses: [], allWeapons: [], allDragons: [{ slug: "vhagar", frontmatter: dragonBase }], + allCastles: [], + allBattles: [], + allEvents: [], current: { kind: "house", slug: "targaryen", mentions: [] }, }); const target = out.targets.find((t) => t.slug === "vhagar"); @@ -431,8 +539,173 @@ describe("buildProseLinkIndex (weapons and dragons)", () => { allHouses: [], allWeapons: [{ slug: "blackfyre", frontmatter: weaponBase }], allDragons: [], + allCastles: [], + allBattles: [], + allEvents: [], current: { kind: "weapon", slug: "blackfyre", mentions: [] }, }); - expect(out.selfSlug).toBe("blackfyre"); + expect(out.self).toEqual({ kind: "weapon", slug: "blackfyre" }); + }); +}); + +describe("prose-links: castles, battles, and events", () => { + it("links a castle by name", async () => { + const index = indexFor({ + current: { kind: "battle", slug: "burning-of-harrenhal" }, + castles: [HARRENHAL], + }); + const html = await renderWith( + "Harren's host sheltered inside Harrenhal.", + index, + ); + expect(html).toContain('Harrenhal'); + }); + + it("links a castle written with a lowercase article", async () => { + const index = indexFor({ + current: { kind: "event", slug: "the-purple-wedding" }, + castles: [TWINS], + }); + const html = await renderWith("Robb Stark rode for the Twins.", index); + expect(html).toContain('the Twins'); + }); + + it("never links a castle whose name is also a house's short name", async () => { + const index = indexFor({ + current: { kind: "battle", slug: "sack-of-darry", mentions: ["darry"] }, + houses: [DARRY_HOUSE], + castles: [DARRY_CASTLE], + }); + const html = await renderWith( + "Lord Darry held the castle of Darry.", + index, + ); + expect(html).toContain('Darry'); + expect(html).not.toContain('href="/castles/darry/"'); + }); + + it("links a battle by its article-stripped name", async () => { + const index = indexFor({ + current: { kind: "character", slug: "robb-stark" }, + battles: [RED_WEDDING], + }); + const html = await renderWith("He was slain at the Red Wedding.", index); + expect(html).toContain( + 'the Red Wedding', + ); + }); + + it("links an event by name", async () => { + const index = indexFor({ + current: { kind: "house", slug: "targaryen" }, + events: [DOOM], + }); + const html = await renderWith( + "They fled before the Doom of Valyria.", + index, + ); + expect(html).toContain( + 'the Doom of Valyria', + ); + }); + + it("links an event by alias", async () => { + const index = indexFor({ + current: { kind: "house", slug: "targaryen" }, + events: [DOOM], + }); + const html = await renderWith( + "After the Doom, Dragonstone stood alone.", + index, + ); + expect(html).toContain('the Doom'); + }); + + it("prefers the battle over the castle inside the battle's own name", async () => { + const index = indexFor({ + current: { kind: "character", slug: "baelor-hightower" }, + castles: [ASHFORD], + battles: [BATTLE_OF_ASHFORD], + }); + const html = await renderWith("He fell at the Battle of Ashford.", index); + expect(html).toContain( + 'Battle of Ashford', + ); + expect(html).not.toContain('href="/castles/ashford/"'); + }); + + it("suppresses a battle page's link to itself", async () => { + const index = indexFor({ + current: { kind: "battle", slug: "red-wedding" }, + battles: [RED_WEDDING], + }); + const html = await renderWith("The Red Wedding was a massacre.", index); + expect(html).not.toContain('href="/battles/red-wedding/"'); + }); + + it("keys self-suppression by kind, so a castle sharing the page's slug still links", async () => { + const index = indexFor({ + current: { kind: "battle", slug: "pyke" }, + castles: [PYKE], + battles: [STORMING_OF_PYKE], + }); + const html = await renderWith("The walls of Pyke were breached.", index); + expect(html).toContain('Pyke'); + }); + + it("links a castle and a battle that share a slug once each", async () => { + const index = indexFor({ + current: { kind: "character", slug: "robert-baratheon" }, + castles: [PYKE], + battles: [STORMING_OF_PYKE], + }); + const html = await renderWith( + "The Storming of Pyke ended the rebellion, and Pyke was left in ruins.", + index, + ); + expect(html).toContain('The Storming of Pyke'); + expect(html).toContain('Pyke'); + }); + + it("skips draft castles, battles, and events", async () => { + const index = indexFor({ + current: { kind: "character", slug: "nobody" }, + castles: [ + castle({ slug: "ghost-keep", name: "Ghost Keep", draft: true }), + ], + battles: [ + battle({ slug: "ghost-fight", name: "The Ghost Fight", draft: true }), + ], + events: [ + event({ slug: "ghost-feast", name: "The Ghost Feast", draft: true }), + ], + }); + const html = await renderWith( + "Ghost Keep, the Ghost Fight, and the Ghost Feast.", + index, + ); + expect(html).not.toContain("href="); + }); + + it("emits article-stripped forms for castles, battles, and events", () => { + const out = buildProseLinkIndex({ + allCharacters: [], + allHouses: [], + allWeapons: [], + allDragons: [], + allCastles: [TWINS], + allBattles: [RED_WEDDING], + allEvents: [DOOM], + current: { kind: "battle", slug: "nobody", mentions: [] }, + }); + expect(out.targets.map((t) => [t.kind, t.href, t.surfaceForms])).toEqual([ + ["castle", "/castles/the-twins/", ["The Twins", "Twins"]], + ["battle", "/battles/red-wedding/", ["The Red Wedding", "Red Wedding"]], + [ + "event", + "/events/doom-of-valyria/", + ["The Doom of Valyria", "Doom", "Doom of Valyria"], + ], + ]); }); }); diff --git a/lib/prose-links.ts b/lib/prose-links.ts index ac5fb294..3a1c5d6f 100644 --- a/lib/prose-links.ts +++ b/lib/prose-links.ts @@ -1,21 +1,49 @@ import type { Plugin } from "unified"; import type { Root, Text, Link, Parent } from "mdast"; import { visitParents, SKIP } from "unist-util-visit-parents"; -import type { Character, House, Weapon, Dragon } from "@/lib/schemas"; +import type { + Battle, + Castle, + Character, + Dragon, + Event, + House, + Weapon, +} from "@/lib/schemas"; + +export type ProseLinkKind = + | "character" + | "house" + | "weapon" + | "dragon" + | "castle" + | "battle" + | "event"; export type ProseLinkTarget = { slug: string; - kind: "character" | "house" | "weapon" | "dragon"; + kind: ProseLinkKind; href: string; surfaceForms: string[]; }; export type ProseLinkIndex = { targets: ProseLinkTarget[]; - selfSlug: string | null; + self: { kind: ProseLinkKind; slug: string } | null; }; +const KIND_PATH = { + character: "characters", + house: "houses", + weapon: "weapons", + dragon: "dragons", + castle: "castles", + battle: "battles", + event: "events", +} as const satisfies Record; + const HOUSE_PREFIX = /^House\s+/i; +const ARTICLE_PREFIX = /^The\s+/; const SKIP_ANCESTOR_TYPES = new Set([ "link", "linkReference", @@ -34,6 +62,12 @@ function shortHouseName(name: string): string { return name.replace(HOUSE_PREFIX, ""); } +// The match is case-sensitive and prose writes "the Twins", so a name that +// carries its own article also needs the bare form. +function stripArticle(name: string): string { + return name.replace(ARTICLE_PREFIX, ""); +} + function uniqueOrdered(forms: string[]): string[] { const seen = new Set(); return forms.reduce((acc, f) => { @@ -44,85 +78,122 @@ function uniqueOrdered(forms: string[]): string[] { }, []); } +function targetKey(target: { kind: ProseLinkKind; slug: string }): string { + return `${target.kind}/${target.slug}`; +} + +function targetsOf({ + kind, + entries, + forms, +}: { + kind: ProseLinkKind; + entries: ReadonlyArray<{ frontmatter: T }>; + forms: (frontmatter: T) => string[]; +}): ProseLinkTarget[] { + return entries.flatMap(({ frontmatter: fm }) => { + if (fm.draft) return []; + const surfaceForms = uniqueOrdered(forms(fm)); + if (surfaceForms.length === 0) return []; + return [ + { + slug: fm.slug, + kind, + href: `/${KIND_PATH[kind]}/${fm.slug}/`, + surfaceForms, + }, + ]; + }); +} + export function buildProseLinkIndex(args: { allCharacters: ReadonlyArray<{ slug: string; frontmatter: Character }>; allHouses: ReadonlyArray<{ slug: string; frontmatter: House }>; allWeapons: ReadonlyArray<{ slug: string; frontmatter: Weapon }>; allDragons: ReadonlyArray<{ slug: string; frontmatter: Dragon }>; + allCastles: ReadonlyArray<{ slug: string; frontmatter: Castle }>; + allBattles: ReadonlyArray<{ slug: string; frontmatter: Battle }>; + allEvents: ReadonlyArray<{ slug: string; frontmatter: Event }>; current: { - kind: "character" | "house" | "weapon" | "dragon"; + kind: ProseLinkKind; slug: string; mentions: readonly string[]; }; }): ProseLinkIndex { - const { allCharacters, allHouses, allWeapons, allDragons, current } = args; + const { + allCharacters, + allHouses, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + current, + } = args; const mentioned = new Set(current.mentions); - const characterTargets = allCharacters.flatMap((c) => { - const fm = c.frontmatter; - if (fm.placeholder || fm.draft) return []; - const forms = [fm.name, ...fm.aliases]; - if (mentioned.has(fm.slug)) forms.push(firstNameToken(fm.name)); - const surfaceForms = uniqueOrdered(forms); - if (surfaceForms.length === 0) return []; - return [ - { - slug: fm.slug, - kind: "character", - href: `/characters/${fm.slug}/`, - surfaceForms, - }, - ]; + const characterTargets = targetsOf({ + kind: "character", + entries: allCharacters, + forms: (fm) => { + if (fm.placeholder) return []; + const forms = [fm.name, ...fm.aliases]; + if (mentioned.has(fm.slug)) forms.push(firstNameToken(fm.name)); + return forms; + }, }); - const houseTargets = allHouses.flatMap((h) => { - const fm = h.frontmatter; - if (fm.draft) return []; - const forms = [fm.name]; - if (mentioned.has(fm.slug)) { - const short = shortHouseName(fm.name); - if (short && short !== fm.name) forms.push(short); - } - const surfaceForms = uniqueOrdered(forms); - if (surfaceForms.length === 0) return []; - return [ - { - slug: fm.slug, - kind: "house", - href: `/houses/${fm.slug}/`, - surfaceForms, - }, - ]; + const houseTargets = targetsOf({ + kind: "house", + entries: allHouses, + forms: (fm) => { + const forms = [fm.name]; + if (mentioned.has(fm.slug)) { + const short = shortHouseName(fm.name); + if (short && short !== fm.name) forms.push(short); + } + return forms; + }, }); - const weaponTargets = allWeapons.flatMap((w) => { - const fm = w.frontmatter; - if (fm.draft) return []; - const surfaceForms = uniqueOrdered([fm.name, ...fm.aliases]); - if (surfaceForms.length === 0) return []; - return [ - { - slug: fm.slug, - kind: "weapon", - href: `/weapons/${fm.slug}/`, - surfaceForms, - }, - ]; + const weaponTargets = targetsOf({ + kind: "weapon", + entries: allWeapons, + forms: (fm) => [fm.name, ...fm.aliases], }); - const dragonTargets = allDragons.flatMap((d) => { - const fm = d.frontmatter; - if (fm.draft) return []; - const surfaceForms = uniqueOrdered([fm.name, ...fm.aliases]); - if (surfaceForms.length === 0) return []; - return [ - { - slug: fm.slug, - kind: "dragon", - href: `/dragons/${fm.slug}/`, - surfaceForms, - }, - ]; + const dragonTargets = targetsOf({ + kind: "dragon", + entries: allDragons, + forms: (fm) => [fm.name, ...fm.aliases], + }); + + // A castle that shares its name with a house (Darry, Rosby, the Hightower) + // reads as the house or its lord in most sentences, and `mentions` cannot + // separate the two because both carry the same slug. Such castles never + // auto-link; an explicit markdown link in the body still does. + const houseShortNames = new Set( + allHouses.map((h) => shortHouseName(h.frontmatter.name)), + ); + const castleTargets = targetsOf({ + kind: "castle", + entries: allCastles, + forms: (fm) => { + const forms = [fm.name, stripArticle(fm.name)]; + return forms.some((f) => houseShortNames.has(f)) ? [] : forms; + }, + }); + + const battleTargets = targetsOf({ + kind: "battle", + entries: allBattles, + forms: (fm) => [fm.name, ...fm.aliases, stripArticle(fm.name)], + }); + + const eventTargets = targetsOf({ + kind: "event", + entries: allEvents, + forms: (fm) => [fm.name, ...fm.aliases, stripArticle(fm.name)], }); return { @@ -131,8 +202,11 @@ export function buildProseLinkIndex(args: { ...houseTargets, ...weaponTargets, ...dragonTargets, + ...castleTargets, + ...battleTargets, + ...eventTargets, ], - selfSlug: current.slug, + self: { kind: current.kind, slug: current.slug }, }; } @@ -143,13 +217,13 @@ function escapeRegex(s: string): string { type CompiledIndex = { pattern: RegExp; formToTarget: Map; - selfSlug: string | null; }; function compileIndex(index: ProseLinkIndex): CompiledIndex | null { + const selfKey = index.self ? targetKey(index.self) : null; const formToTarget = new Map(); const allForms = index.targets - .filter((t) => t.slug !== index.selfSlug) + .filter((t) => targetKey(t) !== selfKey) .reduce((acc, t) => { t.surfaceForms.forEach((f) => { if (formToTarget.has(f)) return; @@ -164,7 +238,7 @@ function compileIndex(index: ProseLinkIndex): CompiledIndex | null { "\\b(" + allForms.map(escapeRegex).join("|") + ")\\b", "g", ); - return { pattern, formToTarget, selfSlug: index.selfSlug }; + return { pattern, formToTarget }; } export function remarkProseLinks(index: ProseLinkIndex): Plugin<[], Root> { @@ -172,13 +246,13 @@ export function remarkProseLinks(index: ProseLinkIndex): Plugin<[], Root> { const compiled = compileIndex(index); return function transformer(tree: Root) { if (!compiled) return; - const usedSlugs = new Set(); + const usedKeys = new Set(); visitParents(tree, "text", (node: Text, ancestors: Parent[]) => { if (ancestors.some((a) => SKIP_ANCESTOR_TYPES.has(a.type))) return SKIP; const parent = ancestors[ancestors.length - 1]; if (!parent) return; - const replacements = scanText(node, compiled, usedSlugs); + const replacements = scanText(node, compiled, usedKeys); if (replacements === null) return; const idx = parent.children.indexOf(node as never); if (idx === -1) return; @@ -192,7 +266,7 @@ export function remarkProseLinks(index: ProseLinkIndex): Plugin<[], Root> { function scanText( node: Text, compiled: CompiledIndex, - usedSlugs: Set, + usedKeys: Set, ): (Text | Link)[] | null { const value = node.value; if (!value) return null; @@ -205,8 +279,8 @@ function scanText( const matched = match[1]; const target = compiled.formToTarget.get(matched); if (!target) continue; - if (target.slug === compiled.selfSlug) continue; - if (usedSlugs.has(target.slug)) continue; + const key = targetKey(target); + if (usedKeys.has(key)) continue; const start = match.index; const end = start + matched.length; if (start > lastIndex) { @@ -218,7 +292,7 @@ function scanText( title: null, children: [{ type: "text", value: matched }], }); - usedSlugs.add(target.slug); + usedKeys.add(key); lastIndex = end; produced = true; } From f4709d5c793391b47a062f04f30d6a9f57fd8a70 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:46:29 -0400 Subject: [PATCH 03/37] TKW: render prose links on battle and event pages - `app/battles/[slug]` and `app/events/[slug]` build a link index and pass `proseLinks` to `renderMarkdown` - character, house, weapon, and dragon pages pass castles, battles, and events into the index --- app/battles/[slug]/page.tsx | 36 ++++++++++++++++++++++++-- app/characters/[slug]/page.tsx | 33 ++++++++++++++++++------ app/dragons/[slug]/page.tsx | 33 ++++++++++++++++++------ app/events/[slug]/page.tsx | 47 +++++++++++++++++++++++++++++++--- app/houses/[slug]/page.tsx | 33 +++++++++++++++++------- app/weapons/[slug]/page.tsx | 36 +++++++++++++++++++------- 6 files changed, 179 insertions(+), 39 deletions(-) diff --git a/app/battles/[slug]/page.tsx b/app/battles/[slug]/page.tsx index f7b9232b..f8b51f85 100644 --- a/app/battles/[slug]/page.tsx +++ b/app/battles/[slug]/page.tsx @@ -6,8 +6,13 @@ import { loadAllBattles, loadAllHouses, loadAllCharacters, + loadAllWeapons, + loadAllDragons, + loadAllCastles, + loadAllEvents, renderMarkdown, } from "@/lib/content"; +import { buildProseLinkIndex } from "@/lib/prose-links"; import { PlateLayout } from "@/components/PlateLayout"; import { Sources } from "@/components/Sources"; import { BattleInfobox } from "@/components/BattleInfobox"; @@ -42,10 +47,25 @@ export default async function BattlePage({ params: Promise<{ slug: string }>; }) { const { slug } = await params; - const [battle, allHouses, allCharacters, image] = await Promise.all([ + const [ + battle, + allHouses, + allCharacters, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + image, + ] = await Promise.all([ loadBattle(slug).catch(() => null), loadAllHouses(), loadAllCharacters(), + loadAllWeapons(), + loadAllDragons(), + loadAllCastles(), + loadAllBattles(), + loadAllEvents(), findBattleImage(slug), ]); if (!battle) notFound(); @@ -54,7 +74,19 @@ export default async function BattlePage({ const charactersBySlug = bySlug(allCharacters); const fm = battle.frontmatter; - const html = battle.body.trim() ? await renderMarkdown(battle.body) : ""; + const proseLinks = buildProseLinkIndex({ + allCharacters, + allHouses, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + current: { kind: "battle", slug, mentions: fm.mentions }, + }); + const html = battle.body.trim() + ? await renderMarkdown(battle.body, { proseLinks }) + : ""; const subtitle = [formatBattleWhen(fm.start, fm.end), fm.war] .filter(Boolean) .join(" ยท "); diff --git a/app/characters/[slug]/page.tsx b/app/characters/[slug]/page.tsx index 5bd5e515..9769cd7e 100644 --- a/app/characters/[slug]/page.tsx +++ b/app/characters/[slug]/page.tsx @@ -5,6 +5,9 @@ import { loadAllHouses, loadAllWeapons, loadAllDragons, + loadAllCastles, + loadAllBattles, + loadAllEvents, loadCharacter, renderMarkdown, } from "@/lib/content"; @@ -89,14 +92,25 @@ export default async function CharacterPage({ const fm = character.frontmatter; - const [allCharacters, allHouses, allWeapons, allDragons, portraits] = - await Promise.all([ - loadAllCharacters(), - loadAllHouses(), - loadAllWeapons(), - loadAllDragons(), - findPortraitVariants({ slug, name: fm.name, sex: fm.sex }), - ]); + const [ + allCharacters, + allHouses, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + portraits, + ] = await Promise.all([ + loadAllCharacters(), + loadAllHouses(), + loadAllWeapons(), + loadAllDragons(), + loadAllCastles(), + loadAllBattles(), + loadAllEvents(), + findPortraitVariants({ slug, name: fm.name, sex: fm.sex }), + ]); const charactersBySlug = bySlug(allCharacters); const housesBySlug = bySlug(allHouses); @@ -152,6 +166,9 @@ export default async function CharacterPage({ slug: d.slug, frontmatter: d.frontmatter, })), + allCastles, + allBattles, + allEvents, current: { kind: "character", slug, mentions: fm.mentions }, }); const html = character.body.trim() diff --git a/app/dragons/[slug]/page.tsx b/app/dragons/[slug]/page.tsx index d4b73d3c..9289e1e3 100644 --- a/app/dragons/[slug]/page.tsx +++ b/app/dragons/[slug]/page.tsx @@ -6,6 +6,9 @@ import { loadAllWeapons, loadAllHouses, loadAllCharacters, + loadAllCastles, + loadAllBattles, + loadAllEvents, renderMarkdown, } from "@/lib/content"; import { buildProseLinkIndex } from "@/lib/prose-links"; @@ -42,14 +45,25 @@ export default async function DragonPage({ params: Promise<{ slug: string }>; }) { const { slug } = await params; - const [dragon, allHouses, allCharacters, allWeapons, allDragons] = - await Promise.all([ - loadDragon(slug).catch(() => null), - loadAllHouses(), - loadAllCharacters(), - loadAllWeapons(), - loadAllDragons(), - ]); + const [ + dragon, + allHouses, + allCharacters, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + ] = await Promise.all([ + loadDragon(slug).catch(() => null), + loadAllHouses(), + loadAllCharacters(), + loadAllWeapons(), + loadAllDragons(), + loadAllCastles(), + loadAllBattles(), + loadAllEvents(), + ]); if (!dragon) notFound(); const housesBySlug = bySlug(allHouses); @@ -73,6 +87,9 @@ export default async function DragonPage({ slug: d.slug, frontmatter: d.frontmatter, })), + allCastles, + allBattles, + allEvents, current: { kind: "dragon", slug, mentions: dragon.frontmatter.mentions }, }); const html = diff --git a/app/events/[slug]/page.tsx b/app/events/[slug]/page.tsx index ba48c9bf..d8ccc65e 100644 --- a/app/events/[slug]/page.tsx +++ b/app/events/[slug]/page.tsx @@ -1,6 +1,17 @@ import { notFound } from "next/navigation"; import Link from "next/link"; -import { loadEvent, loadAllEvents, renderMarkdown } from "@/lib/content"; +import { + loadEvent, + loadAllEvents, + loadAllHouses, + loadAllCharacters, + loadAllWeapons, + loadAllDragons, + loadAllCastles, + loadAllBattles, + renderMarkdown, +} from "@/lib/content"; +import { buildProseLinkIndex } from "@/lib/prose-links"; import { PlateLayout } from "@/components/PlateLayout"; import { Sources } from "@/components/Sources"; import { formatBattleWhen } from "@/lib/battle-date"; @@ -32,11 +43,41 @@ export default async function EventPage({ params: Promise<{ slug: string }>; }) { const { slug } = await params; - const event = await loadEvent(slug).catch(() => null); + const [ + event, + allHouses, + allCharacters, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + ] = await Promise.all([ + loadEvent(slug).catch(() => null), + loadAllHouses(), + loadAllCharacters(), + loadAllWeapons(), + loadAllDragons(), + loadAllCastles(), + loadAllBattles(), + loadAllEvents(), + ]); if (!event) notFound(); const fm = event.frontmatter; - const html = event.body.trim() ? await renderMarkdown(event.body) : ""; + const proseLinks = buildProseLinkIndex({ + allCharacters, + allHouses, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + current: { kind: "event", slug, mentions: fm.mentions }, + }); + const html = event.body.trim() + ? await renderMarkdown(event.body, { proseLinks }) + : ""; const typeLabel = fm.type[0].toUpperCase() + fm.type.slice(1); const subtitle = [ typeLabel, diff --git a/app/houses/[slug]/page.tsx b/app/houses/[slug]/page.tsx index c66e96f7..86a33c51 100644 --- a/app/houses/[slug]/page.tsx +++ b/app/houses/[slug]/page.tsx @@ -7,6 +7,8 @@ import { loadAllCharacters, loadAllWeapons, loadAllDragons, + loadAllBattles, + loadAllEvents, renderMarkdown, } from "@/lib/content"; import { PlateLayout } from "@/components/PlateLayout"; @@ -55,15 +57,25 @@ export default async function HousePage({ params: Promise<{ slug: string }>; }) { const { slug } = await params; - const [house, allHouses, castles, characters, allWeapons, allDragons] = - await Promise.all([ - loadHouse(slug).catch(() => null), - loadAllHouses(), - loadAllCastles(), - loadAllCharacters(), - loadAllWeapons(), - loadAllDragons(), - ]); + const [ + house, + allHouses, + castles, + characters, + allWeapons, + allDragons, + allBattles, + allEvents, + ] = await Promise.all([ + loadHouse(slug).catch(() => null), + loadAllHouses(), + loadAllCastles(), + loadAllCharacters(), + loadAllWeapons(), + loadAllDragons(), + loadAllBattles(), + loadAllEvents(), + ]); if (!house) notFound(); const housesBySlug = bySlug(allHouses); @@ -101,6 +113,9 @@ export default async function HousePage({ slug: d.slug, frontmatter: d.frontmatter, })), + allCastles: castles, + allBattles, + allEvents, current: { kind: "house", slug, mentions: house.frontmatter.mentions }, }); const html = await renderMarkdown(house.body, { proseLinks }); diff --git a/app/weapons/[slug]/page.tsx b/app/weapons/[slug]/page.tsx index 8549ec93..d7bbe05f 100644 --- a/app/weapons/[slug]/page.tsx +++ b/app/weapons/[slug]/page.tsx @@ -5,6 +5,9 @@ import { loadWeapon, loadAllWeapons, loadAllDragons, + loadAllCastles, + loadAllBattles, + loadAllEvents, loadAllHouses, loadAllCharacters, renderMarkdown, @@ -63,15 +66,27 @@ export default async function WeaponPage({ params: Promise<{ slug: string }>; }) { const { slug } = await params; - const [weapon, allHouses, allCharacters, allWeapons, allDragons, image] = - await Promise.all([ - loadWeapon(slug).catch(() => null), - loadAllHouses(), - loadAllCharacters(), - loadAllWeapons(), - loadAllDragons(), - findWeaponImage(slug), - ]); + const [ + weapon, + allHouses, + allCharacters, + allWeapons, + allDragons, + allCastles, + allBattles, + allEvents, + image, + ] = await Promise.all([ + loadWeapon(slug).catch(() => null), + loadAllHouses(), + loadAllCharacters(), + loadAllWeapons(), + loadAllDragons(), + loadAllCastles(), + loadAllBattles(), + loadAllEvents(), + findWeaponImage(slug), + ]); if (!weapon) notFound(); const housesBySlug = bySlug(allHouses); @@ -95,6 +110,9 @@ export default async function WeaponPage({ slug: d.slug, frontmatter: d.frontmatter, })), + allCastles, + allBattles, + allEvents, current: { kind: "weapon", slug, mentions: weapon.frontmatter.mentions }, }); const html = From 9bef051b849d2cbbc0f01b98479cf4dc46abe3e6 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:46:39 -0400 Subject: [PATCH 04/37] TKW: curate `mentions` for battle and event bodies - 57 battles and 29 events list the characters their bodies name by first name only, and the houses named bare - every slug checked against date and sentence; namesake hits (Karstarks as ancient Starks, Sept of Baelor as the king) left out - one character per first name per entry, since the first to register takes the bare name --- content/battles/andal-wars-of-conquest.md | 1 + content/battles/battle-at-duskendale.md | 1 + content/battles/battle-at-rooks-rest.md | 1 + content/battles/battle-beneath-the-gods-eye.md | 7 +++++++ content/battles/battle-in-the-gullet.md | 1 + content/battles/battle-in-the-whispering-wood.md | 1 + content/battles/battle-of-ashford.md | 1 + content/battles/battle-of-fair-isle.md | 1 + content/battles/battle-of-ice.md | 1 + content/battles/battle-of-oxcross.md | 1 + content/battles/battle-of-summerhall.md | 1 + content/battles/battle-of-the-bells.md | 1 + content/battles/battle-of-the-blackwater.md | 9 +++++++++ content/battles/battle-of-the-burning-mill.md | 1 + content/battles/battle-of-the-camps.md | 1 + content/battles/battle-of-the-fords.md | 1 + content/battles/battle-of-the-golden-tooth.md | 1 + content/battles/battle-of-the-green-fork.md | 1 + content/battles/battle-of-the-shield-islands.md | 1 + content/battles/battle-of-the-trident.md | 1 + content/battles/burning-of-harrenhal.md | 1 + content/battles/capture-and-sack-of-winterfell.md | 1 + content/battles/daeron-is-conquest-of-dorne.md | 1 + content/battles/death-of-rhaenys-at-the-hellholt.md | 1 + content/battles/disaster-at-the-fist-of-the-first-men.md | 1 + content/battles/dornish-uprising.md | 1 + content/battles/faith-militant-uprising.md | 9 +++++++++ content/battles/field-of-fire.md | 1 + content/battles/first-battle-of-the-last-storm.md | 1 + content/battles/first-battle-of-tumbleton.md | 1 + content/battles/first-blackfyre-rebellion.md | 8 ++++++++ content/battles/first-dornish-war-invasion.md | 1 + .../ironborn-wars-of-the-greyiron-and-hoare-kings.md | 1 + content/battles/raids-in-the-riverlands.md | 1 + content/battles/red-wedding.md | 1 + content/battles/sack-of-harrenhal.md | 1 + content/battles/sack-of-kings-landing.md | 1 + content/battles/sack-of-meereen.md | 1 + content/battles/second-battle-of-tumbleton.md | 1 + content/battles/second-blackfyre-rebellion.md | 1 + content/battles/siege-of-riverrun.md | 1 + content/battles/siege-of-storms-end.md | 1 + content/battles/skagosi-rebellion.md | 1 + content/battles/skirmish-at-the-tower-of-joy.md | 1 + content/battles/stark-wars-of-unification.md | 1 + content/battles/storm-king-reach-wars.md | 1 + content/battles/storming-of-pyke.md | 1 + content/battles/storming-of-the-dragonpit.md | 1 + content/battles/taking-and-recapture-of-moat-cailin.md | 1 + content/battles/the-butchers-ball.md | 1 + content/battles/the-dragons-wroth.md | 1 + content/battles/the-fishfeed.md | 1 + content/battles/the-muddy-mess.md | 1 + content/battles/third-and-fourth-blackfyre-rebellions.md | 1 + content/battles/tristifer-iv-mudds-hundred-battles.md | 1 + content/battles/vulture-kings-uprising.md | 1 + content/battles/war-of-the-ninepenny-kings.md | 1 + content/events/assassination-of-jon-snow.md | 1 + content/events/birth-of-the-dragons.md | 1 + content/events/death-of-jon-arryn.md | 1 + content/events/death-of-king-robert.md | 1 + content/events/death-of-the-dragons.md | 1 + content/events/death-of-tywin-lannister.md | 1 + content/events/doom-of-valyria.md | 1 + content/events/election-of-jon-snow.md | 1 + content/events/execution-of-eddard-stark.md | 1 + content/events/exile-of-jalabhar-xho.md | 1 + content/events/exodus-of-house-targaryen.md | 1 + content/events/fall-of-bran-stark.md | 1 + content/events/flight-from-daznaks-pit.md | 1 + content/events/flight-of-the-last-targaryens.md | 1 + content/events/founding-of-kings-landing.md | 2 ++ content/events/garth-greenhand-seeds-the-reach.md | 1 + content/events/golden-crown-of-viserys.md | 1 + content/events/grant-of-the-new-gift.md | 1 + content/events/great-council-of-101.md | 7 +++++++ content/events/house-of-the-undying.md | 1 + content/events/murder-of-renly-baratheon.md | 1 + content/events/passage-of-the-sorrows.md | 1 + content/events/the-purple-wedding.md | 1 + content/events/the-red-comet.md | 1 + content/events/tragedy-at-summerhall.md | 1 + content/events/union-of-dorne-and-the-iron-throne.md | 1 + content/events/voyage-of-the-cinnamon-wind.md | 1 + content/events/wedding-of-daenerys-and-hizdahr.md | 1 + content/events/wedding-of-robert-and-cersei.md | 1 + 86 files changed, 122 insertions(+) diff --git a/content/battles/andal-wars-of-conquest.md b/content/battles/andal-wars-of-conquest.md index 088a2849..1e357c01 100644 --- a/content/battles/andal-wars-of-conquest.md +++ b/content/battles/andal-wars-of-conquest.md @@ -21,6 +21,7 @@ commanders: [tristifer-iv-mudd, theon-stark] victor: "The Andals" outcome: "The Andals overwhelmed the First Men kingdoms south of the Neck and shattered the children of the forest, but the Kings of Winter turned them back at the Neck, so the North alone kept the old blood and the old gods." casualties: [tristifer-iv-mudd] +mentions: [mudd] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Andal_Invasion diff --git a/content/battles/battle-at-duskendale.md b/content/battles/battle-at-duskendale.md index e3914962..615c9c15 100644 --- a/content/battles/battle-at-duskendale.md +++ b/content/battles/battle-at-duskendale.md @@ -26,6 +26,7 @@ victor: "the Iron Throne" outcome: "A northern foraging host was trapped and destroyed at Duskendale, costing Robb Stark a large part of his foot before the Red Wedding." casualties: [helman-tallhart] aliases: [] +mentions: [tywin-lannister, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_at_Duskendale diff --git a/content/battles/battle-at-rooks-rest.md b/content/battles/battle-at-rooks-rest.md index 12e5f7b8..f860540a 100644 --- a/content/battles/battle-at-rooks-rest.md +++ b/content/battles/battle-at-rooks-rest.md @@ -29,6 +29,7 @@ victor: "greens" outcome: "A green trap that saw Princess Rhaenys and her dragon Meleys slain, though Aegon II and Sunfyre were both grievously maimed." casualties: [rhaenys-targaryen-queen-who-never-was] aliases: ["Battle of Rook's Rest"] +mentions: [aegon-ii-targaryen, rhaenyra-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_at_Rook's_Rest diff --git a/content/battles/battle-beneath-the-gods-eye.md b/content/battles/battle-beneath-the-gods-eye.md index 51f902ed..606e5c62 100644 --- a/content/battles/battle-beneath-the-gods-eye.md +++ b/content/battles/battle-beneath-the-gods-eye.md @@ -23,6 +23,13 @@ victor: "Maegor I" outcome: "Maegor slays his nephew Aegon and the dragon Quicksilver above the God's Eye, ending the rival claim to the Iron Throne." casualties: [aegon-the-uncrowned] aliases: ["The Battle Beneath the God's Eye"] +mentions: + [ + aegon-the-uncrowned, + jaehaerys-i-targaryen, + maegor-i-targaryen, + aenys-i-targaryen, + ] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_Beneath_the_Gods_Eye diff --git a/content/battles/battle-in-the-gullet.md b/content/battles/battle-in-the-gullet.md index 75ae9c52..5406a7c8 100644 --- a/content/battles/battle-in-the-gullet.md +++ b/content/battles/battle-in-the-gullet.md @@ -23,6 +23,7 @@ victor: "blacks" outcome: "A ruinously costly black victory that broke the Triarchy fleet but claimed Prince Jacaerys Velaryon and his dragon Vermax." casualties: [jacaerys-velaryon] aliases: ["Battle of the Gullet"] +mentions: [rhaenyra-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_in_the_Gullet diff --git a/content/battles/battle-in-the-whispering-wood.md b/content/battles/battle-in-the-whispering-wood.md index c1630776..f6b76ab2 100644 --- a/content/battles/battle-in-the-whispering-wood.md +++ b/content/battles/battle-in-the-whispering-wood.md @@ -25,6 +25,7 @@ commanders: [robb-stark, brynden-tully, jaime-lannister] victor: "House Stark" outcome: "Robb Stark's night ambush destroyed Jaime Lannister's cavalry and took Jaime himself captive, a devastating blow to the Lannister cause in the riverlands." casualties: [daryn-hornwood] +mentions: [tywin-lannister, stark, karstark, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_in_the_Whispering_Wood diff --git a/content/battles/battle-of-ashford.md b/content/battles/battle-of-ashford.md index 96ef44d6..9af276fd 100644 --- a/content/battles/battle-of-ashford.md +++ b/content/battles/battle-of-ashford.md @@ -25,6 +25,7 @@ commanders: [robert-baratheon, randyll-tarly] victor: "loyalists" outcome: "Randyll Tarly's vanguard falls upon Robert Baratheon before the main Reach host arrives and drives him from the field, the only defeat Robert suffers in the war." aliases: [] +mentions: [aerys-ii-targaryen, tyrell, tarly] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_Ashford diff --git a/content/battles/battle-of-fair-isle.md b/content/battles/battle-of-fair-isle.md index 0423b1d8..07deb8c5 100644 --- a/content/battles/battle-of-fair-isle.md +++ b/content/battles/battle-of-fair-isle.md @@ -21,6 +21,7 @@ participants: commanders: [stannis-baratheon, victarion-greyjoy] victor: "the Iron Throne" outcome: "Stannis Baratheon destroyed the Iron Fleet at sea, ending ironborn command of the western waters and dooming Balon Greyjoy's rebellion." +mentions: [stannis-baratheon, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_Fair_Isle diff --git a/content/battles/battle-of-ice.md b/content/battles/battle-of-ice.md index 4ce7b36f..8cb7b1cf 100644 --- a/content/battles/battle-of-ice.md +++ b/content/battles/battle-of-ice.md @@ -21,6 +21,7 @@ participants: commanders: [stannis-baratheon, roose-bolton] outcome: "The engagement is still unresolved and has not yet occurred in the published novels." aliases: [] +mentions: [frey, bolton, manderly] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_Ice diff --git a/content/battles/battle-of-oxcross.md b/content/battles/battle-of-oxcross.md index ec17f47a..7972c9f2 100644 --- a/content/battles/battle-of-oxcross.md +++ b/content/battles/battle-of-oxcross.md @@ -22,6 +22,7 @@ commanders: [robb-stark, stafford-lannister] victor: "House Stark" outcome: "Robb Stark destroyed Ser Stafford Lannister's raw host in a night attack, slew Stafford, and threw open the westerlands to northern raiders." casualties: [stafford-lannister] +mentions: [tywin-lannister, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_Oxcross diff --git a/content/battles/battle-of-summerhall.md b/content/battles/battle-of-summerhall.md index 84fd9804..d058ed97 100644 --- a/content/battles/battle-of-summerhall.md +++ b/content/battles/battle-of-summerhall.md @@ -25,6 +25,7 @@ commanders: [robert-baratheon] victor: "rebels" outcome: "Robert Baratheon defeats three loyalist hosts in a single day, scattering the lords Grandison, Cafferen, and Fell before they can combine against him." aliases: [] +mentions: [cafferen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_Summerhall diff --git a/content/battles/battle-of-the-bells.md b/content/battles/battle-of-the-bells.md index cab2ece3..ca658254 100644 --- a/content/battles/battle-of-the-bells.md +++ b/content/battles/battle-of-the-bells.md @@ -26,6 +26,7 @@ victor: "rebels" outcome: "The Stark and Tully hosts storm Stoney Sept as its bells ring the alarm, breaking Jon Connington's search for the wounded Robert and saving the rebellion at its lowest ebb." casualties: [denys-arryn, myles-mooton] aliases: [] +mentions: [catelyn-stark, aerys-ii-targaryen, connington] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Bells diff --git a/content/battles/battle-of-the-blackwater.md b/content/battles/battle-of-the-blackwater.md index f4d0b31c..41e70ea9 100644 --- a/content/battles/battle-of-the-blackwater.md +++ b/content/battles/battle-of-the-blackwater.md @@ -32,6 +32,15 @@ commanders: victor: "House Lannister and House Tyrell" outcome: "Stannis Baratheon's great assault on King's Landing was shattered by wildfire and a boom-chain across the river, then routed when the Lannister and Tyrell host struck his landed army from behind." aliases: ["The Battle of the Blackwater Rush"] +mentions: + [ + joffrey-baratheon, + margaery-tyrell, + renly-baratheon, + tyrell, + baratheon, + lannister, + ] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Blackwater diff --git a/content/battles/battle-of-the-burning-mill.md b/content/battles/battle-of-the-burning-mill.md index 3503a145..a076f7e8 100644 --- a/content/battles/battle-of-the-burning-mill.md +++ b/content/battles/battle-of-the-burning-mill.md @@ -22,6 +22,7 @@ commanders: [samwell-blackwood, amos-bracken] outcome: "A bloody and indecisive clash that drew the riverlands into the war; Lord Samwell Blackwood was slain by Ser Amos Bracken." casualties: [samwell-blackwood] aliases: ["Battle of the Burning Mill"] +mentions: [aegon-ii-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Burning_Mill diff --git a/content/battles/battle-of-the-camps.md b/content/battles/battle-of-the-camps.md index a176ad5c..8d658778 100644 --- a/content/battles/battle-of-the-camps.md +++ b/content/battles/battle-of-the-camps.md @@ -24,6 +24,7 @@ participants: commanders: [robb-stark, brynden-tully, edmure-tully] victor: "House Stark" outcome: "Robb Stark stormed the leaderless Lannister camps and lifted the siege of Riverrun, uniting the northern and river hosts and freeing House Tully." +mentions: [jaime-lannister, tully, stark, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Camps diff --git a/content/battles/battle-of-the-fords.md b/content/battles/battle-of-the-fords.md index a887686b..c133ee38 100644 --- a/content/battles/battle-of-the-fords.md +++ b/content/battles/battle-of-the-fords.md @@ -22,6 +22,7 @@ commanders: [edmure-tully, tywin-lannister, gregor-clegane] victor: "House Tully" outcome: "Edmure Tully held every crossing of the Red Fork against Lord Tywin's host, a river victory that nonetheless spoiled Robb Stark's plan to lure the enemy west." aliases: ["The Battle of the Stone Mill"] +mentions: [robb-stark, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Fords diff --git a/content/battles/battle-of-the-golden-tooth.md b/content/battles/battle-of-the-golden-tooth.md index a90ec011..6fe5ea50 100644 --- a/content/battles/battle-of-the-golden-tooth.md +++ b/content/battles/battle-of-the-golden-tooth.md @@ -24,6 +24,7 @@ participants: commanders: [jaime-lannister] victor: "House Lannister" outcome: "Jaime Lannister broke the river lords holding the pass and opened the road into the riverlands, allowing him to march on Riverrun." +mentions: [piper, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Golden_Tooth diff --git a/content/battles/battle-of-the-green-fork.md b/content/battles/battle-of-the-green-fork.md index d51c0a22..cf2eb90d 100644 --- a/content/battles/battle-of-the-green-fork.md +++ b/content/battles/battle-of-the-green-fork.md @@ -21,6 +21,7 @@ participants: commanders: [roose-bolton, tywin-lannister, tyrion-lannister] victor: "House Lannister" outcome: "Tywin Lannister drove Roose Bolton's northern foot from the field, but the fight was a feint that masked Robb Stark's true march west against Jaime at Riverrun." +mentions: [jaime-lannister, bolton, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Green_Fork diff --git a/content/battles/battle-of-the-shield-islands.md b/content/battles/battle-of-the-shield-islands.md index c9f5d509..6e125e60 100644 --- a/content/battles/battle-of-the-shield-islands.md +++ b/content/battles/battle-of-the-shield-islands.md @@ -22,6 +22,7 @@ commanders: [euron-greyjoy, victarion-greyjoy] victor: "the ironborn" outcome: "Euron Greyjoy seizes the four Shield Islands and looses the Iron Fleet up the Mander into the heart of the Reach." aliases: [] +mentions: [victarion-greyjoy, redwyne] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Shield_Islands diff --git a/content/battles/battle-of-the-trident.md b/content/battles/battle-of-the-trident.md index 38e136dc..e54e6c2a 100644 --- a/content/battles/battle-of-the-trident.md +++ b/content/battles/battle-of-the-trident.md @@ -31,6 +31,7 @@ victor: "rebels" outcome: "Robert Baratheon slays Prince Rhaegar Targaryen in the waters of the Trident, and the loyalist host breaks, deciding the war in the rebels' favor." casualties: [rhaegar-targaryen, lewyn-martell] aliases: [Battle of the Ruby Ford] +mentions: [aerys-ii-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Battle_of_the_Trident diff --git a/content/battles/burning-of-harrenhal.md b/content/battles/burning-of-harrenhal.md index efc492a5..48000a51 100644 --- a/content/battles/burning-of-harrenhal.md +++ b/content/battles/burning-of-harrenhal.md @@ -25,6 +25,7 @@ commanders: [aegon-i-targaryen, harren-hoare] victor: "House Targaryen" outcome: "Aegon burns Harren the Black and all his line within their newly raised castle, ending House Hoare and freeing the riverlands, whose lords bend the knee." casualties: [harren-hoare] +mentions: [aegon-i-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Harrenhal diff --git a/content/battles/capture-and-sack-of-winterfell.md b/content/battles/capture-and-sack-of-winterfell.md index ffb8732a..da16378f 100644 --- a/content/battles/capture-and-sack-of-winterfell.md +++ b/content/battles/capture-and-sack-of-winterfell.md @@ -26,6 +26,7 @@ participants: commanders: [theon-greyjoy, ramsay-bolton] outcome: "Theon Greyjoy seized the lightly held seat of the Starks, only for Ramsay Snow's men to storm it, butcher its people, and leave the castle a gutted ruin." aliases: [] +mentions: [balon-greyjoy, bran-stark, ramsay-bolton, stark, bolton] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Sack_of_Winterfell diff --git a/content/battles/daeron-is-conquest-of-dorne.md b/content/battles/daeron-is-conquest-of-dorne.md index 30c47b7e..317f65da 100644 --- a/content/battles/daeron-is-conquest-of-dorne.md +++ b/content/battles/daeron-is-conquest-of-dorne.md @@ -22,6 +22,7 @@ commanders: [daeron-i-targaryen, baelor-i-targaryen, alyn-velaryon] victor: "Iron Throne" outcome: "The Young Dragon broke the Dornish in the passes and took Sunspear, bringing Dorne under the Iron Throne for the first time." casualties: [rickon-stark-son-of-cregan] +mentions: [aegon-i-targaryen, fowler, targaryen, yronwood] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Conquest_of_Dorne diff --git a/content/battles/death-of-rhaenys-at-the-hellholt.md b/content/battles/death-of-rhaenys-at-the-hellholt.md index 5a2ef80a..ddc890c7 100644 --- a/content/battles/death-of-rhaenys-at-the-hellholt.md +++ b/content/battles/death-of-rhaenys-at-the-hellholt.md @@ -25,6 +25,7 @@ commanders: [rhaenys-targaryen] victor: "Dorne" outcome: "Queen Rhaenys and Meraxes are slain over the Hellholt; the loss shatters Aegon's restraint and begins the Dragon's Wroth." casualties: [rhaenys-targaryen] +mentions: [aegon-i-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Meraxes diff --git a/content/battles/disaster-at-the-fist-of-the-first-men.md b/content/battles/disaster-at-the-fist-of-the-first-men.md index d8eaad33..53c6d224 100644 --- a/content/battles/disaster-at-the-fist-of-the-first-men.md +++ b/content/battles/disaster-at-the-fist-of-the-first-men.md @@ -21,6 +21,7 @@ commanders: [jeor-mormont] victor: "the Others" outcome: "The Great Ranging is shattered atop the Fist and its survivors flee south in disarray." aliases: [] +mentions: [others] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Fist_of_the_First_Men diff --git a/content/battles/dornish-uprising.md b/content/battles/dornish-uprising.md index 215aa66c..d6b8939c 100644 --- a/content/battles/dornish-uprising.md +++ b/content/battles/dornish-uprising.md @@ -22,6 +22,7 @@ commanders: [daeron-i-targaryen] victor: "Dorne" outcome: "The Dornish threw off Targaryen rule and slew King Daeron I beneath a peace banner, restoring Dorne's independence." casualties: [daeron-i-targaryen] +mentions: [baelor-i-targaryen, daeron-i-targaryen, targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Conquest_of_Dorne diff --git a/content/battles/faith-militant-uprising.md b/content/battles/faith-militant-uprising.md index 60a2a6a6..dee04054 100644 --- a/content/battles/faith-militant-uprising.md +++ b/content/battles/faith-militant-uprising.md @@ -21,6 +21,15 @@ participants: commanders: [maegor-i-targaryen, aenys-i-targaryen, jaehaerys-i-targaryen] victor: "Iron Throne" outcome: "The militant orders of the Faith are crushed and later disbanded, and the Faith renounces the sword in exchange for a royal pardon." +mentions: + [ + aegon-the-uncrowned, + jaehaerys-i-targaryen, + maegor-i-targaryen, + rhaena-targaryen-daughter-of-aenys, + alys-harroway, + aenys-i-targaryen, + ] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Faith_Militant_uprising diff --git a/content/battles/field-of-fire.md b/content/battles/field-of-fire.md index 54a57a48..413a42ca 100644 --- a/content/battles/field-of-fire.md +++ b/content/battles/field-of-fire.md @@ -22,6 +22,7 @@ commanders: [aegon-i-targaryen, loren-i-lannister, mern-ix-gardener] victor: "House Targaryen" outcome: "Aegon's three dragons burn the largest host ever raised in Westeros; King Mern dies and the Gardener line is extinguished, while King Loren yields and keeps Casterly Rock." casualties: [mern-ix-gardener] +mentions: [rhaenys-targaryen, visenya-targaryen, gardener, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Field_of_Fire diff --git a/content/battles/first-battle-of-the-last-storm.md b/content/battles/first-battle-of-the-last-storm.md index 8fffa8fa..dff72f52 100644 --- a/content/battles/first-battle-of-the-last-storm.md +++ b/content/battles/first-battle-of-the-last-storm.md @@ -25,6 +25,7 @@ commanders: [orys-baratheon, argilac-durrandon] victor: "House Targaryen" outcome: "Orys Baratheon slays Argilac the Arrogant, ending the line of the Storm Kings and winning Storm's End, the Durrandon arms, and Argilac's daughter." casualties: [argilac-durrandon] +mentions: [targaryen, baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Last_Storm diff --git a/content/battles/first-battle-of-tumbleton.md b/content/battles/first-battle-of-tumbleton.md index 33964f77..25a40ca6 100644 --- a/content/battles/first-battle-of-tumbleton.md +++ b/content/battles/first-battle-of-tumbleton.md @@ -27,6 +27,7 @@ victor: "greens" outcome: "The Two Betrayers turned their dragons upon Rhaenyra's defenders, shattering the black host and delivering Tumbleton to fire and sack." casualties: [roderick-dustin] aliases: ["Fall of Tumbleton", "First Tumbleton"] +mentions: [aegon-ii-targaryen, rhaenyra-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/First_Battle_of_Tumbleton diff --git a/content/battles/first-blackfyre-rebellion.md b/content/battles/first-blackfyre-rebellion.md index 3b3dc1ee..8d4d23c3 100644 --- a/content/battles/first-blackfyre-rebellion.md +++ b/content/battles/first-blackfyre-rebellion.md @@ -37,6 +37,14 @@ casualties: quentyn-ball, ] aliases: ["Battle of the Redgrass Field"] +mentions: + [ + aegon-iv-targaryen, + aemon-blackfyre-son-of-daemon-i, + daemon-i-blackfyre, + daeron-ii-targaryen, + blackfyre, + ] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/First_Blackfyre_Rebellion diff --git a/content/battles/first-dornish-war-invasion.md b/content/battles/first-dornish-war-invasion.md index 14d3d31b..be87f97f 100644 --- a/content/battles/first-dornish-war-invasion.md +++ b/content/battles/first-dornish-war-invasion.md @@ -35,6 +35,7 @@ commanders: victor: "Dorne" outcome: "After nearly a decade of raids, burnings, and reprisals, the war ends in stalemate, and Dorne remains unconquered and independent." casualties: [rhaenys-targaryen] +mentions: [aegon-i-targaryen, rhaenys-targaryen, daeron-ii-targaryen, yronwood] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/First_Dornish_War diff --git a/content/battles/ironborn-wars-of-the-greyiron-and-hoare-kings.md b/content/battles/ironborn-wars-of-the-greyiron-and-hoare-kings.md index 96ee3e1d..69774718 100644 --- a/content/battles/ironborn-wars-of-the-greyiron-and-hoare-kings.md +++ b/content/battles/ironborn-wars-of-the-greyiron-and-hoare-kings.md @@ -21,6 +21,7 @@ participants: commanders: [urron-greyiron, harwyn-hoare, harren-hoare] victor: "The Ironborn" outcome: "The ironborn extended their reaving across the sunset sea, and under the black-blooded Hoare kings conquered the riverlands, ruling them until Aegon's Conquest." +mentions: [aegon-i-targaryen, greyiron] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Ironborn diff --git a/content/battles/raids-in-the-riverlands.md b/content/battles/raids-in-the-riverlands.md index 61732460..f07c373a 100644 --- a/content/battles/raids-in-the-riverlands.md +++ b/content/battles/raids-in-the-riverlands.md @@ -21,6 +21,7 @@ participants: commanders: [gregor-clegane, beric-dondarrion, tywin-lannister] victor: "House Lannister" outcome: "Lannister raiders under Ser Gregor Clegane burned the southern riverlands unopposed and ambushed the party sent to bring them to justice, opening the wider war." +mentions: [tyrion-lannister, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Raids_in_the_riverlands diff --git a/content/battles/red-wedding.md b/content/battles/red-wedding.md index 3efb601b..c0930705 100644 --- a/content/battles/red-wedding.md +++ b/content/battles/red-wedding.md @@ -26,6 +26,7 @@ victor: "House Frey and House Bolton" outcome: "Robb Stark, his lady mother, and the flower of his host were slaughtered under guest right at a wedding feast, breaking the northern cause in a single night." casualties: [robb-stark, catelyn-stark] aliases: [] +mentions: [catelyn-stark, frey, bolton] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Red_Wedding diff --git a/content/battles/sack-of-harrenhal.md b/content/battles/sack-of-harrenhal.md index 3a76618a..e0b12042 100644 --- a/content/battles/sack-of-harrenhal.md +++ b/content/battles/sack-of-harrenhal.md @@ -25,6 +25,7 @@ commanders: [roose-bolton] victor: "House Bolton" outcome: "Harrenhal passed into northern hands when the sellsword Brave Companions turned on their Lannister paymasters and opened the gates to Roose Bolton." aliases: [] +mentions: [lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Harrenhal diff --git a/content/battles/sack-of-kings-landing.md b/content/battles/sack-of-kings-landing.md index 40808917..58eaecd6 100644 --- a/content/battles/sack-of-kings-landing.md +++ b/content/battles/sack-of-kings-landing.md @@ -32,6 +32,7 @@ casualties: elia-martell, ] aliases: [] +mentions: [aegon-son-of-rhaegar, rhaenys-daughter-of-rhaegar] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Sack_of_King's_Landing diff --git a/content/battles/sack-of-meereen.md b/content/battles/sack-of-meereen.md index 25883db3..9205d444 100644 --- a/content/battles/sack-of-meereen.md +++ b/content/battles/sack-of-meereen.md @@ -21,6 +21,7 @@ commanders: [daenerys-targaryen, grey-worm, jorah-mormont, barristan-selmy] victor: "Daenerys Targaryen and the Unsullied" outcome: "Daenerys took Meereen by a rising of its own slaves, hanged the ruling Great Masters, and made the city her seat." aliases: [] +mentions: [daenerys-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Sack_of_Meereen diff --git a/content/battles/second-battle-of-tumbleton.md b/content/battles/second-battle-of-tumbleton.md index 6052c8c5..a6a968b5 100644 --- a/content/battles/second-battle-of-tumbleton.md +++ b/content/battles/second-battle-of-tumbleton.md @@ -26,6 +26,7 @@ commanders: outcome: "Addam Velaryon fell upon the encamped green host to redeem the dragonseeds, and in the ensuing carnage its leadership was gutted and the march on King's Landing broken." casualties: [addam-velaryon, ormund-hightower, jon-roxton] aliases: ["Second Tumbleton"] +mentions: [daeron-targaryen-son-of-viserys-i, targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Second_Battle_of_Tumbleton diff --git a/content/battles/second-blackfyre-rebellion.md b/content/battles/second-blackfyre-rebellion.md index c4998d8d..47f46934 100644 --- a/content/battles/second-blackfyre-rebellion.md +++ b/content/battles/second-blackfyre-rebellion.md @@ -22,6 +22,7 @@ commanders: [daemon-ii-blackfyre, brynden-rivers, gormon-peake] victor: "Iron Throne" outcome: "The plot to crown Daemon II collapsed when Bloodraven descended on Whitewalls, took the pretender captive, and beheaded the ringleaders." casualties: [gormon-peake] +mentions: [aerys-i-targaryen, blackfyre] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Second_Blackfyre_Rebellion diff --git a/content/battles/siege-of-riverrun.md b/content/battles/siege-of-riverrun.md index 6fdca35f..899f9511 100644 --- a/content/battles/siege-of-riverrun.md +++ b/content/battles/siege-of-riverrun.md @@ -25,6 +25,7 @@ commanders: [jaime-lannister, edmure-tully] victor: "House Lannister" outcome: "Jaime Lannister scattered Edmure Tully's host before the walls and ringed Riverrun with three camps, penning the Tullys in their own castle until Robb Stark broke the siege." aliases: ["The First Siege of Riverrun"] +mentions: [lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Siege_of_Riverrun diff --git a/content/battles/siege-of-storms-end.md b/content/battles/siege-of-storms-end.md index ab514355..6a4fb43c 100644 --- a/content/battles/siege-of-storms-end.md +++ b/content/battles/siege-of-storms-end.md @@ -25,6 +25,7 @@ commanders: [stannis-baratheon, mace-tyrell, paxter-redwyne] victor: "rebels" outcome: "Mace Tyrell besieges Storm's End for nearly a year but never breaks it; Stannis Baratheon's garrison, saved from starvation by an onion smuggler, holds until the war's end lifts the siege." aliases: [] +mentions: [stannis-baratheon, redwyne] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Siege_of_Storm's_End diff --git a/content/battles/skagosi-rebellion.md b/content/battles/skagosi-rebellion.md index 76e9d495..ba910ec4 100644 --- a/content/battles/skagosi-rebellion.md +++ b/content/battles/skagosi-rebellion.md @@ -20,6 +20,7 @@ participants: houses: [] victor: "House Stark" outcome: "The Skagosi rose against Winterfell and were brought back beneath the direwolf's rule by a King of Winter, though at great cost." +mentions: [stark] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Skagos diff --git a/content/battles/skirmish-at-the-tower-of-joy.md b/content/battles/skirmish-at-the-tower-of-joy.md index 6b813698..fc5482a8 100644 --- a/content/battles/skirmish-at-the-tower-of-joy.md +++ b/content/battles/skirmish-at-the-tower-of-joy.md @@ -23,6 +23,7 @@ victor: "rebels" outcome: "Eddard Stark and his companions overcome three knights of the Kingsguard guarding the Tower of Joy; only Ned and Howland Reed survive the clash." casualties: [arthur-dayne, oswell-whent, willam-dustin] aliases: [Battle of the Tower of Joy] +mentions: [lyanna-stark, barbrey-ryswell, rhaegar-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Tower_of_Joy diff --git a/content/battles/stark-wars-of-unification.md b/content/battles/stark-wars-of-unification.md index 6c991b5f..883d707f 100644 --- a/content/battles/stark-wars-of-unification.md +++ b/content/battles/stark-wars-of-unification.md @@ -21,6 +21,7 @@ commanders: [jon-stark, theon-stark, rickard-stark-the-laughing-wolf, rodrik-stark] victor: "House Stark" outcome: "Over many lifetimes the Kings of Winter broke or subdued every rival power in the North, uniting the whole of it under Winterfell." +mentions: [stark] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Kings_of_Winter diff --git a/content/battles/storm-king-reach-wars.md b/content/battles/storm-king-reach-wars.md index fc0d1b81..1713d8af 100644 --- a/content/battles/storm-king-reach-wars.md +++ b/content/battles/storm-king-reach-wars.md @@ -19,6 +19,7 @@ participants: - side: House Gardener houses: [gardener] outcome: "The Marches changed hands again and again over thousands of years, with neither realm able to hold them for long, until both fell at last to Aegon the Conqueror." +mentions: [mern-ix-gardener, argilac-durrandon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Dornish_Marches diff --git a/content/battles/storming-of-pyke.md b/content/battles/storming-of-pyke.md index ca32e341..6c04e49c 100644 --- a/content/battles/storming-of-pyke.md +++ b/content/battles/storming-of-pyke.md @@ -25,6 +25,7 @@ commanders: [robert-baratheon, stannis-baratheon, balon-greyjoy] victor: "the Iron Throne" outcome: "Robert Baratheon's host stormed Pyke and broke the rebellion; Balon Greyjoy bent the knee and gave up his last surviving son, Theon, as a hostage and ward." casualties: [maron-greyjoy] +mentions: [rodrik-greyjoy, theon-greyjoy, stannis-baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Siege_of_Pyke diff --git a/content/battles/storming-of-the-dragonpit.md b/content/battles/storming-of-the-dragonpit.md index 7c95300d..e826d31a 100644 --- a/content/battles/storming-of-the-dragonpit.md +++ b/content/battles/storming-of-the-dragonpit.md @@ -24,6 +24,7 @@ participants: victor: "Smallfolk of King's Landing" outcome: "A crazed mob broke into the Dragonpit and slew the chained dragons, gutting Targaryen power and turning the capital against Queen Rhaenyra." aliases: ["Storming of the Dragonpit"] +mentions: [joffrey-velaryon, helaena-targaryen, rhaenyra-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Storming_of_the_Dragonpit diff --git a/content/battles/taking-and-recapture-of-moat-cailin.md b/content/battles/taking-and-recapture-of-moat-cailin.md index 069f0eda..ea0bc64f 100644 --- a/content/battles/taking-and-recapture-of-moat-cailin.md +++ b/content/battles/taking-and-recapture-of-moat-cailin.md @@ -25,6 +25,7 @@ commanders: [ramsay-bolton] victor: "House Bolton and House Frey" outcome: "The ironborn seized the ruined causeway fortress to choke the neck, then were tricked into yielding it to Ramsay Bolton, reopening the only overland road into the north." aliases: [] +mentions: [frey, bolton] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Moat_Cailin diff --git a/content/battles/the-butchers-ball.md b/content/battles/the-butchers-ball.md index f799949e..b1792f3e 100644 --- a/content/battles/the-butchers-ball.md +++ b/content/battles/the-butchers-ball.md @@ -23,6 +23,7 @@ victor: "blacks" outcome: "Ser Criston Cole's host was surrounded and slaughtered near the God's Eye, and the Kingmaker himself was cut down after refusing to yield." casualties: [criston-cole] aliases: ["Battle by the Lakeshore"] +mentions: [aegon-ii-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Butcher's_Ball diff --git a/content/battles/the-dragons-wroth.md b/content/battles/the-dragons-wroth.md index 1711a221..65be1d4c 100644 --- a/content/battles/the-dragons-wroth.md +++ b/content/battles/the-dragons-wroth.md @@ -21,6 +21,7 @@ participants: commanders: [aegon-i-targaryen, visenya-targaryen] victor: "Dorne" outcome: "Aegon and Visenya burn the castles of Dorne for three years in vengeance for Rhaenys, but the Dornish endure until a peace is agreed." +mentions: [rhaenys-targaryen, visenya-targaryen, yronwood] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Dragon%27s_Wroth diff --git a/content/battles/the-fishfeed.md b/content/battles/the-fishfeed.md index 84a5e209..8a37c390 100644 --- a/content/battles/the-fishfeed.md +++ b/content/battles/the-fishfeed.md @@ -21,6 +21,7 @@ participants: commanders: [roderick-dustin, benjicot-blackwood] victor: "blacks" outcome: "Three converging black hosts annihilated a leaderless westerman army, casting so many dead into the rivers that the fish grew fat." +mentions: [aegon-ii-targaryen, rhaenyra-targaryen, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Fishfeed diff --git a/content/battles/the-muddy-mess.md b/content/battles/the-muddy-mess.md index 2db2743d..6eb9245e 100644 --- a/content/battles/the-muddy-mess.md +++ b/content/battles/the-muddy-mess.md @@ -22,6 +22,7 @@ commanders: [borros-baratheon, benjicot-blackwood] victor: "blacks" outcome: "The river lords broke Lord Borros Baratheon's stormland host in the rain and mud, and his death ended the last organized green resistance." aliases: ["Battle at the Kingsroad"] +mentions: [aegon-ii-targaryen, frey] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Muddy_Mess diff --git a/content/battles/third-and-fourth-blackfyre-rebellions.md b/content/battles/third-and-fourth-blackfyre-rebellions.md index 4ba1dc66..9727d192 100644 --- a/content/battles/third-and-fourth-blackfyre-rebellions.md +++ b/content/battles/third-and-fourth-blackfyre-rebellions.md @@ -23,6 +23,7 @@ commanders: victor: "Iron Throne" outcome: "Both risings were crushed along the Dornish Marches, and neither Haegon nor Daemon III came near the crown their forebears had sought." casualties: [haegon-blackfyre, daemon-iii-blackfyre] +mentions: [aegon-v-targaryen, blackfyre] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Blackfyre_Rebellion diff --git a/content/battles/tristifer-iv-mudds-hundred-battles.md b/content/battles/tristifer-iv-mudds-hundred-battles.md index 1a408fba..2bb45994 100644 --- a/content/battles/tristifer-iv-mudds-hundred-battles.md +++ b/content/battles/tristifer-iv-mudds-hundred-battles.md @@ -22,6 +22,7 @@ commanders: [tristifer-iv-mudd] victor: "Andal invaders" outcome: "Tristifer IV won ninety-nine victories but lost his hundredth battle and his life; his heir could not hold the realm, and the kingdom of the rivers passed to the Andals." casualties: [tristifer-iv-mudd] +mentions: [mudd] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Tristifer_IV_Mudd diff --git a/content/battles/vulture-kings-uprising.md b/content/battles/vulture-kings-uprising.md index cd069974..c5e5d6cc 100644 --- a/content/battles/vulture-kings-uprising.md +++ b/content/battles/vulture-kings-uprising.md @@ -21,6 +21,7 @@ participants: commanders: [orys-baratheon, wyl-of-wyl] victor: "Iron Throne" outcome: "The first Vulture King's host is broken and scattered, though Orys Baratheon is taken by the Wyl of Wyl and loses a hand to ransom." +mentions: [caron, wyl, dondarrion] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Vulture_King diff --git a/content/battles/war-of-the-ninepenny-kings.md b/content/battles/war-of-the-ninepenny-kings.md index 704cd8b0..87653431 100644 --- a/content/battles/war-of-the-ninepenny-kings.md +++ b/content/battles/war-of-the-ninepenny-kings.md @@ -22,6 +22,7 @@ victor: "Iron Throne" outcome: "The realm broke the Band of Nine on the Stepstones, and Barristan Selmy slew Maelys the Monstrous, ending the male line of the Blackfyres." casualties: [maelys-i-blackfyre, ormund-baratheon] aliases: ["Fifth Blackfyre Rebellion"] +mentions: [jaehaerys-ii-targaryen, maelys-i-blackfyre, blackfyre] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/War_of_the_Ninepenny_Kings diff --git a/content/events/assassination-of-jon-snow.md b/content/events/assassination-of-jon-snow.md index 8b653623..d2e3fbdc 100644 --- a/content/events/assassination-of-jon-snow.md +++ b/content/events/assassination-of-jon-snow.md @@ -12,6 +12,7 @@ coords: x: 460 y: 108 outcome: "Sworn brothers put their knives in the Lord Commander for the Watch; he falls in the snow at Castle Black, his fate unwritten." +mentions: [ramsay-bolton] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Jon_Snow diff --git a/content/events/birth-of-the-dragons.md b/content/events/birth-of-the-dragons.md index 6b22077e..16e003a3 100644 --- a/content/events/birth-of-the-dragons.md +++ b/content/events/birth-of-the-dragons.md @@ -9,6 +9,7 @@ date: location: "The Dothraki sea" landmass: essos outcome: "Daenerys walks into Drogo's pyre and out of the ashes unburnt, with three living dragons, the first in a century and a half." +mentions: [jorah-mormont] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Daenerys_Targaryen diff --git a/content/events/death-of-jon-arryn.md b/content/events/death-of-jon-arryn.md index 107162ea..8e280d9f 100644 --- a/content/events/death-of-jon-arryn.md +++ b/content/events/death-of-jon-arryn.md @@ -12,6 +12,7 @@ coords: x: 590 y: 830 outcome: "The Hand of the King dies of a sudden fever (poison, in truth) and Robert rides north to make Eddard Stark his Hand." +mentions: [robert-baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Jon_Arryn diff --git a/content/events/death-of-king-robert.md b/content/events/death-of-king-robert.md index 2635a401..80d37cd6 100644 --- a/content/events/death-of-king-robert.md +++ b/content/events/death-of-king-robert.md @@ -9,6 +9,7 @@ date: location: "The Kingswood" landmass: westeros outcome: "A boar, strongwine, and a queen's design end the first Baratheon king; the peace he won at the Trident dies with him." +mentions: [robert-baratheon, cersei-lannister, lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Robert_I_Baratheon diff --git a/content/events/death-of-the-dragons.md b/content/events/death-of-the-dragons.md index 7fc1dea9..caa1de41 100644 --- a/content/events/death-of-the-dragons.md +++ b/content/events/death-of-the-dragons.md @@ -12,6 +12,7 @@ coords: x: 590 y: 830 outcome: "The last dragon dies stunted and sickly under Aegon III, and House Targaryen rules on by right and habit alone." +mentions: [aegon-iii-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Last_dragon diff --git a/content/events/death-of-tywin-lannister.md b/content/events/death-of-tywin-lannister.md index 813dd3fb..4884f029 100644 --- a/content/events/death-of-tywin-lannister.md +++ b/content/events/death-of-tywin-lannister.md @@ -12,6 +12,7 @@ coords: x: 592 y: 830 outcome: "Tyrion puts a crossbow bolt through his father on the privy and flees across the narrow sea; the lion's realm begins to unravel." +mentions: [oberyn-martell, tywin-lannister, jaime-lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Tywin_Lannister diff --git a/content/events/doom-of-valyria.md b/content/events/doom-of-valyria.md index 98d34246..bdf72422 100644 --- a/content/events/doom-of-valyria.md +++ b/content/events/doom-of-valyria.md @@ -9,6 +9,7 @@ date: location: "Valyria" landmass: essos outcome: "The Fourteen Flames erupt and the Freehold perishes in a day; the Lands of the Long Summer shatter into the Smoking Sea." +mentions: [aegon-i-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Doom_of_Valyria diff --git a/content/events/election-of-jon-snow.md b/content/events/election-of-jon-snow.md index 5b34cbd5..7c0f15ee 100644 --- a/content/events/election-of-jon-snow.md +++ b/content/events/election-of-jon-snow.md @@ -12,6 +12,7 @@ coords: x: 460 y: 108 outcome: "Ned Stark's bastard becomes the nine hundred and ninety-eighth Lord Commander of the Night's Watch, and lets the wildlings through the Wall." +mentions: [stannis-baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Jon_Snow diff --git a/content/events/execution-of-eddard-stark.md b/content/events/execution-of-eddard-stark.md index a1c0765e..14e7f81a 100644 --- a/content/events/execution-of-eddard-stark.md +++ b/content/events/execution-of-eddard-stark.md @@ -12,6 +12,7 @@ coords: x: 590 y: 830 outcome: "Joffrey takes Lord Stark's head on the steps of the Great Sept, and all hope of peace between wolf and lion with it." +mentions: [joffrey-baratheon, cersei-lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Eddard_Stark diff --git a/content/events/exile-of-jalabhar-xho.md b/content/events/exile-of-jalabhar-xho.md index 50452be8..2de8f007 100644 --- a/content/events/exile-of-jalabhar-xho.md +++ b/content/events/exile-of-jalabhar-xho.md @@ -9,6 +9,7 @@ date: location: "Red Flower Vale" landmass: summer-isles outcome: "The defeated Prince of Red Flower Vale flees to Robert's court, forever petitioning for swords to win back his vale." +mentions: [robert-baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Jalabhar_Xho diff --git a/content/events/exodus-of-house-targaryen.md b/content/events/exodus-of-house-targaryen.md index 77e589c3..f002df27 100644 --- a/content/events/exodus-of-house-targaryen.md +++ b/content/events/exodus-of-house-targaryen.md @@ -12,6 +12,7 @@ coords: x: 660 y: 870 outcome: "Warned by Daenys the Dreamer, the Targaryens quit Valyria for Dragonstone twelve years before the Doom, and alone of the dragonlords survive it." +mentions: [aegon-i-targaryen, daenys-targaryen, aenar-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aenar_Targaryen diff --git a/content/events/fall-of-bran-stark.md b/content/events/fall-of-bran-stark.md index 114b7da1..d5b289c0 100644 --- a/content/events/fall-of-bran-stark.md +++ b/content/events/fall-of-bran-stark.md @@ -12,6 +12,7 @@ coords: x: 400 y: 430 outcome: "A boy who saw too much is thrown from a tower and lives, crippled; the things done to silence him set the realm alight." +mentions: [robert-baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Bran_Stark diff --git a/content/events/flight-from-daznaks-pit.md b/content/events/flight-from-daznaks-pit.md index 77d94aaf..9cec8aaf 100644 --- a/content/events/flight-from-daznaks-pit.md +++ b/content/events/flight-from-daznaks-pit.md @@ -9,6 +9,7 @@ date: location: "Meereen" landmass: essos outcome: "Drogon descends upon the fighting pit and carries the queen away to the Dothraki sea, while a slaver host closes on Meereen." +mentions: [daenerys-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Daznak%27s_Pit diff --git a/content/events/flight-of-the-last-targaryens.md b/content/events/flight-of-the-last-targaryens.md index cdc22059..0d4a890b 100644 --- a/content/events/flight-of-the-last-targaryens.md +++ b/content/events/flight-of-the-last-targaryens.md @@ -9,6 +9,7 @@ date: location: "Braavos and the Free Cities" landmass: essos outcome: "Viserys and the infant Daenerys are spirited across the narrow sea, beggar heirs of a fallen dynasty." +mentions: [robert-baratheon, viserys-iii-targaryen, rhaella-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Daenerys_Targaryen diff --git a/content/events/founding-of-kings-landing.md b/content/events/founding-of-kings-landing.md index 47b37f45..279b2468 100644 --- a/content/events/founding-of-kings-landing.md +++ b/content/events/founding-of-kings-landing.md @@ -12,6 +12,8 @@ coords: x: 590 y: 830 outcome: "Aegon is anointed by the Faith, the Iron Throne is forged from the swords of his enemies, and a city rises where he first came ashore." +mentions: + [aegon-i-targaryen, rhaenys-targaryen, visenya-targaryen, maegor-i-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/King%27s_Landing diff --git a/content/events/garth-greenhand-seeds-the-reach.md b/content/events/garth-greenhand-seeds-the-reach.md index 0d2b0730..26bf5127 100644 --- a/content/events/garth-greenhand-seeds-the-reach.md +++ b/content/events/garth-greenhand-seeds-the-reach.md @@ -9,6 +9,7 @@ date: location: "The Reach" landmass: westeros outcome: "The Reach flowers, and from Garth's many children spring the great houses of the south." +mentions: [gardener, rowan] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Garth_Greenhand diff --git a/content/events/golden-crown-of-viserys.md b/content/events/golden-crown-of-viserys.md index f89cbdca..1462487e 100644 --- a/content/events/golden-crown-of-viserys.md +++ b/content/events/golden-crown-of-viserys.md @@ -9,6 +9,7 @@ date: location: "Vaes Dothrak" landmass: essos outcome: "Drogo crowns the beggar king with molten gold in the sacred city; Daenerys watches, and knows he was no dragon." +mentions: [daenerys-targaryen, viserys-iii-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Viserys_Targaryen diff --git a/content/events/grant-of-the-new-gift.md b/content/events/grant-of-the-new-gift.md index 6f7e0429..7dc7942b 100644 --- a/content/events/grant-of-the-new-gift.md +++ b/content/events/grant-of-the-new-gift.md @@ -9,6 +9,7 @@ date: location: "The Wall" landmass: westeros outcome: "Good Queen Alysanne doubles the Night's Watch lands, the crowning kindness of the golden reign of Jaehaerys the Conciliator." +mentions: [jaehaerys-i-targaryen, alysanne-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/New_Gift diff --git a/content/events/great-council-of-101.md b/content/events/great-council-of-101.md index c6cb1cc2..b2f3c3a6 100644 --- a/content/events/great-council-of-101.md +++ b/content/events/great-council-of-101.md @@ -12,6 +12,13 @@ coords: x: 555 y: 765 outcome: "The lords choose Viserys over Rhaenys's line, fixing the precedent that the Iron Throne passes by the male line, the seed of the Dance." +mentions: + [ + viserys-i-targaryen, + jaehaerys-i-targaryen, + rhaenys-targaryen-queen-who-never-was, + baelon-targaryen, + ] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Great_Council_of_101 diff --git a/content/events/house-of-the-undying.md b/content/events/house-of-the-undying.md index daf5b40e..aced776e 100644 --- a/content/events/house-of-the-undying.md +++ b/content/events/house-of-the-undying.md @@ -9,6 +9,7 @@ date: location: "Qarth" landmass: essos outcome: "The warlocks' prophecies (three fires, three mounts, three treasons) are paid for in dragonflame, and Qarth is fled." +mentions: [daenerys-targaryen, rhaegar-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/House_of_the_Undying diff --git a/content/events/murder-of-renly-baratheon.md b/content/events/murder-of-renly-baratheon.md index 7b010bf2..dd8a0e30 100644 --- a/content/events/murder-of-renly-baratheon.md +++ b/content/events/murder-of-renly-baratheon.md @@ -12,6 +12,7 @@ coords: x: 645 y: 935 outcome: "A shadow with Stannis's face kills the king of summer in his own pavilion, and his hundred thousand melt away." +mentions: [stannis-baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Renly_Baratheon diff --git a/content/events/passage-of-the-sorrows.md b/content/events/passage-of-the-sorrows.md index fd4fc835..eb8587a5 100644 --- a/content/events/passage-of-the-sorrows.md +++ b/content/events/passage-of-the-sorrows.md @@ -9,6 +9,7 @@ date: location: "Chroyane" landmass: essos outcome: "The Shy Maid slips through the drowned ruin of Chroyane; the stone men attack, and Jon Connington takes the greyscale in silence." +mentions: [rhaegar-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Chroyane diff --git a/content/events/the-purple-wedding.md b/content/events/the-purple-wedding.md index 820ecf68..73cdfd25 100644 --- a/content/events/the-purple-wedding.md +++ b/content/events/the-purple-wedding.md @@ -12,6 +12,7 @@ coords: x: 590 y: 830 outcome: "King Joffrey is poisoned at his own wedding feast; Tyrion Lannister is seized for the murder, and Sansa Stark vanishes." +mentions: [tyrion-lannister, cersei-lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Joffrey_I_Baratheon diff --git a/content/events/the-red-comet.md b/content/events/the-red-comet.md index 5ce7cb40..a5585c60 100644 --- a/content/events/the-red-comet.md +++ b/content/events/the-red-comet.md @@ -9,6 +9,7 @@ date: location: "The skies of the world" landmass: westeros outcome: "A bleeding star spans the sky from Winterfell to Qarth, and every people reads in it the omen it desires." +mentions: [joffrey-baratheon] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Red_comet diff --git a/content/events/tragedy-at-summerhall.md b/content/events/tragedy-at-summerhall.md index 9e3b7900..53971af8 100644 --- a/content/events/tragedy-at-summerhall.md +++ b/content/events/tragedy-at-summerhall.md @@ -12,6 +12,7 @@ coords: x: 555 y: 1060 outcome: "Fire consumes the summer palace, King Aegon V, and Prince Duncan; Rhaegar Targaryen is born amid the smoke and grief." +mentions: [aegon-v-targaryen, rhaella-targaryen, rhaegar-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Tragedy_at_Summerhall diff --git a/content/events/union-of-dorne-and-the-iron-throne.md b/content/events/union-of-dorne-and-the-iron-throne.md index 778154de..d70be2ba 100644 --- a/content/events/union-of-dorne-and-the-iron-throne.md +++ b/content/events/union-of-dorne-and-the-iron-throne.md @@ -9,6 +9,7 @@ date: location: "Dorne and King's Landing" landmass: westeros outcome: "Dorne joins the realm by marriage rather than conquest, and the Seven Kingdoms are whole at last." +mentions: [daenerys-daughter-of-aegon-iv, daeron-i-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Daeron_II_Targaryen diff --git a/content/events/voyage-of-the-cinnamon-wind.md b/content/events/voyage-of-the-cinnamon-wind.md index b5a497bf..326b4902 100644 --- a/content/events/voyage-of-the-cinnamon-wind.md +++ b/content/events/voyage-of-the-cinnamon-wind.md @@ -9,6 +9,7 @@ date: location: "The Summer Sea" landmass: summer-isles outcome: "The swan ship of Tall Trees Town carries Samwell Tarly toward Oldtown; Maester Aemon Targaryen dies at sea, aged one hundred and two." +mentions: [aemon-targaryen-maester] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Cinnamon_Wind diff --git a/content/events/wedding-of-daenerys-and-hizdahr.md b/content/events/wedding-of-daenerys-and-hizdahr.md index 08bccdd8..cc9d6468 100644 --- a/content/events/wedding-of-daenerys-and-hizdahr.md +++ b/content/events/wedding-of-daenerys-and-hizdahr.md @@ -9,6 +9,7 @@ date: location: "Meereen" landmass: essos outcome: "The dragon queen weds a Ghiscari noble to buy peace for Meereen; the murders stop, and the fighting pits reopen." +mentions: [daenerys-targaryen] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Hizdahr_zo_Loraq diff --git a/content/events/wedding-of-robert-and-cersei.md b/content/events/wedding-of-robert-and-cersei.md index 210e979d..f0ee6e95 100644 --- a/content/events/wedding-of-robert-and-cersei.md +++ b/content/events/wedding-of-robert-and-cersei.md @@ -12,6 +12,7 @@ coords: x: 590 y: 830 outcome: "The stag weds the lion to bind Casterly Rock to the new dynasty; the realm settles into an uneasy, indebted peace." +mentions: [cersei-lannister] sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Robert_I_Baratheon From 2c29c6322218240e1ae554d98f715eed25ca3428 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:46:48 -0400 Subject: [PATCH 05/37] TKW: teach `populate-entry` and the orphan audit the wider linker - `populate-entry` drops the stale "`battles.mentions` does nothing" and "battle bodies never link" rows, adds the `mentions`, alias, and house-named-castle rules, and documents `events.aliases` and `events.mentions` - `audit-orphans.ts` passes castles, battles, and events into `buildProseLinkIndex`, counts battle and event bodies as link sources, and matches the per-kind self rule --- .../skills/orphan-content/audit-orphans.ts | 29 +++++++--- .claude/skills/populate-entry/SKILL.md | 53 +++++++++++-------- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/.claude/skills/orphan-content/audit-orphans.ts b/.claude/skills/orphan-content/audit-orphans.ts index 11c782df..b4962306 100644 --- a/.claude/skills/orphan-content/audit-orphans.ts +++ b/.claude/skills/orphan-content/audit-orphans.ts @@ -377,10 +377,9 @@ function mentionEdges({ /** * Which bodies `remarkProseLinks` would turn into a link to each target. * - * Only `characters`, `houses`, `weapons` and `dragons` render markdown with a - * prose-link index; `app/battles`, `app/castles` and `app/events` call - * `renderMarkdown` with no index, so their bodies emit no links at all and are - * excluded as sources. + * Every detail page except `app/castles` renders markdown with a prose-link + * index, so castle bodies emit no links at all and are excluded as sources. + * Castles, battles and events are still link targets from every other body. * * The index is built with an empty `mentions` list on purpose. Mentions only * widen a target's surface forms (a bare first name, a bare house name), and @@ -394,6 +393,9 @@ function proseEdges(collections: Collections): Edge[] { allHouses: collections.houses, allWeapons: collections.weapons, allDragons: collections.dragons, + allCastles: collections.castles, + allBattles: collections.battles, + allEvents: collections.events, current: { kind: "character", slug: "", mentions: [] }, }); @@ -402,6 +404,9 @@ function proseEdges(collections: Collections): Edge[] { house: "houses", weapon: "weapons", dragon: "dragons", + castle: "castles", + battle: "battles", + event: "events", } as const satisfies Record; // First form wins, matching `compileIndex` in `lib/prose-links.ts`. Two @@ -452,6 +457,16 @@ function proseEdges(collections: Collections): Edge[] { slug: entry.slug, body: entry.body, })), + ...collections.battles.map((entry) => ({ + collection: "battles" as const, + slug: entry.slug, + body: entry.body, + })), + ...collections.events.map((entry) => ({ + collection: "events" as const, + slug: entry.slug, + body: entry.body, + })), ]; return linkingBodies.flatMap(({ collection, slug, body }) => { @@ -459,9 +474,9 @@ function proseEdges(collections: Collections): Edge[] { const matched = body.match(pattern) ?? []; const hit = matched.reduce>((seen, form) => { const to = formToKey.get(form); - // `compileIndex` drops any target sharing the page's own slug, across - // collections, because `selfSlug` is a bare slug. - if (to && !to.endsWith(`/${slug}`)) seen.add(to); + // `compileIndex` drops only the page's own entry; another collection's + // entry with the same slug still links, matching `targetKey`. + if (to && to !== from) seen.add(to); return seen; }, new Set()); return [...hit].map((to) => ({ from, field: "prose", to })); diff --git a/.claude/skills/populate-entry/SKILL.md b/.claude/skills/populate-entry/SKILL.md index e8a20324..942742ff 100644 --- a/.claude/skills/populate-entry/SKILL.md +++ b/.claude/skills/populate-entry/SKILL.md @@ -21,12 +21,11 @@ The research half of the job is identical across all five: one AWOIAF article, o **The core insight: an empty field is not automatically a gap.** Several schema fields are empty on every entry in their collection because nothing renders them, so filling one in is noise, not progress: -| Field | Filled | Why it stays empty | -| ---------------------- | ------ | ------------------------------------------------------------------------------------ | -| `castles.sworn-houses` | 0/146 | Only `lib/relations.ts` reads it, and nothing in `app/` calls `buildRelationGraph`. | -| `battles.mentions` | 0/72 | `buildProseLinkIndex` never runs on a battle page, so `mentions` cannot do anything. | -| `events.participants` | 0/53 | The event page renders subtitle, body, and sources. Nothing else. | -| `events.casualties` | 0/53 | Same. | +| Field | Filled | Why it stays empty | +| ---------------------- | ------ | ----------------------------------------------------------------------------------- | +| `castles.sworn-houses` | 0/146 | Only `lib/relations.ts` reads it, and nothing in `app/` calls `buildRelationGraph`. | +| `events.participants` | 0/53 | The event page renders subtitle, body, and sources. Nothing else. | +| `events.casualties` | 0/53 | Same. | `audit-entries.ts` encodes this: a field only counts against an entry when the rest of its own collection fills it. Score is deviation from the collection norm, not distance from the schema. @@ -75,7 +74,11 @@ Voice notes, matching `harrenhal.md`, `dreadfort.md`, and `battle-of-the-blackwa - Never invent canon. If AWOIAF does not record it, leave it out. - No em dashes or en dashes anywhere in this repo. -Prose auto-linking runs on characters, houses, weapons, and dragons only. `app/castles/[slug]`, `app/battles/[slug]`, and `app/events/[slug]` call `renderMarkdown` without a `proseLinks` index, so nothing in those three bodies becomes a link. Write names freely there; also do not expect the reader to be able to click them. +Prose auto-linking runs on character, house, weapon, dragon, battle, and event pages. Only `app/castles/[slug]` still calls `renderMarkdown` without a `proseLinks` index, so a castle body never links out. The link targets are characters, houses, weapons, dragons, castles, battles, and events; each is matched on its `name` and `aliases`, and a name that starts with "The" also matches without the article, so "the Twins" and "the Red Wedding" link. Three rules follow from `lib/prose-links.ts`: + +- `mentions` widens the match. A character listed there also links on first name alone ("Lord Tywin"), and a house listed there links on its bare name ("the Lannister host"). List one character per first name: a shared first name goes to whichever target registers first, so two Aegons in one `mentions` list means one of them never links. +- A castle that shares its name with a house (Darry, Rosby, the Hightower) never auto-links, because `mentions` carries bare slugs and cannot tell the castle from the house. Write an explicit markdown link when the castle is meant. +- Write `aliases` without a leading article ("Doom", not "the Doom"): the alias would otherwise win the match at "the" and swallow the longer "Doom of Valyria". ## Step 3: frontmatter, per collection @@ -113,8 +116,8 @@ The most complex frontmatter in the repo, and every field below renders in `Batt | `victor` | no | 63/72. The winning `side` label, spelled the same way. Omit only when the outcome was genuinely undecided. | | `outcome` | no | 69/72. One sentence, present tense. | | `casualties[]` | no | 33/72. Character slugs. Renders as "Fallen". | -| `aliases[]` | no | 23/72. Renders as "Also called". | -| `mentions[]` | no | Leave empty. See the overview table. | +| `aliases[]` | no | 23/72. Renders as "Also called", and every alias is a prose-link surface form. | +| `mentions[]` | no | Characters the body names by first name only, and houses it names by bare name. One character per first name. | **The `region` and Essos trap.** `landmassForBattle` in `lib/timeline.ts` puts a battle in the Westeros timeline column when it has any `region`, and otherwise checks a hardcoded `ESSOS_SLUGS` set. So an Essos battle needs **both** no `region` **and** an entry in `ESSOS_SLUGS`. Adding `region: crownlands` to `battle-of-meereen` to clear an audit gap would silently move it to the wrong column. Battles beyond the Wall and realm-wide wars correctly carry no `region` either. @@ -127,6 +130,8 @@ The most complex frontmatter in the repo, and every field below renders in `Batt | `location` | yes | 53/53 store a **display string** ("King's Landing", "Vaes Dothrak"), never a slug. | | `landmass` | yes | `westeros`, `essos`, `summer-isles`. This alone picks the timeline column; events need no `ESSOS_SLUGS`. | | `outcome` | no | 53/53 carry it even though nothing renders it. Keep the convention. | +| `aliases` | no | Prose-link surface forms for the event, written without a leading article. | +| `mentions` | no | Same rule as battles: first-name characters and bare-name houses the body uses. One character per first name. | `buildRelationGraph` in `lib/relations.ts` keys `eventsByLocation` off `location` as though it were a castle slug. No entry stores a slug there, so that map is empty. Do not "fix" one entry to a slug; the page prints `location` verbatim in the subtitle. @@ -170,6 +175,7 @@ Seven entries, all populated. Use this section when adding an eighth. | `dragons.house` | `content/houses/` | | `dragons.riders[]` | `content/characters/` | | `weapons.mentions[]`, `dragons.mentions[]` | any entity slug | +| `battles.mentions[]`, `events.mentions[]` | any entity slug | Check before writing a slug: `ls content/houses/.md`. Do not create a stub in another collection just to satisfy a reference; drop the reference instead. @@ -224,20 +230,21 @@ bun run build # static export; run it after touching cont ## Common mistakes -| Mistake | Why it goes wrong | -| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| Filling every empty field the schema allows | `sworn-houses`, `battles.mentions`, `events.participants`, and `events.casualties` are empty corpus-wide. | -| Adding `region` to an Essos battle to clear a gap | Moves it to the Westeros timeline column. `region` plus `ESSOS_SLUGS` decide the column together. | -| Writing a castle slug into `events.location` | All 53 entries store a display string, and the page prints it verbatim. | -| Putting `## ` headings in a battle, event, weapon, or dragon body | 0 of those 162 entries use headings. Only castles do. | -| Writing a castle body of three or four sections | The longest castle in the repo is 1,097 non-whitespace characters. Median is 593. | -| `precision: exact` on a legendary date | Drops the asterisk the timeline uses to mark approximate dates. | -| Referencing a character or house slug that does not exist | `lib/content-integrity.test.ts` fails the build. There is no graceful fallback here. | -| Expecting names in a castle or battle body to auto-link | Those pages call `renderMarkdown` without a `proseLinks` index. | -| Retrying plain `WebFetch` on awoiaf.westeros.org | Cloudflare 403s every page. Go straight to the CDX pipeline. | -| Citing the `web.archive.org` URL in `sources` | The mirror is the fetch mechanism, not the citation. | -| `bun test` instead of `bun run test` | The script is `bun test --isolate --dots`; the bare form mis-reports the DOM suite. | -| Committing without `bun format` | `oxfmt` covers `.claude/**/*.ts` and markdown, and CI fails on drift. | +| Mistake | Why it goes wrong | +| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | +| Filling every empty field the schema allows | `sworn-houses`, `events.participants`, and `events.casualties` are empty corpus-wide. | +| Adding `region` to an Essos battle to clear a gap | Moves it to the Westeros timeline column. `region` plus `ESSOS_SLUGS` decide the column together. | +| Writing a castle slug into `events.location` | All 53 entries store a display string, and the page prints it verbatim. | +| Putting `## ` headings in a battle, event, weapon, or dragon body | 0 of those 162 entries use headings. Only castles do. | +| Writing a castle body of three or four sections | The longest castle in the repo is 1,097 non-whitespace characters. Median is 593. | +| `precision: exact` on a legendary date | Drops the asterisk the timeline uses to mark approximate dates. | +| Referencing a character or house slug that does not exist | `lib/content-integrity.test.ts` fails the build. There is no graceful fallback here. | +| Expecting names in a castle body to auto-link | The castle page calls `renderMarkdown` without a `proseLinks` index. Battles and events do link. | +| Listing two characters who share a first name in `mentions` | The first to register takes the bare name; the other never links on it. | +| Retrying plain `WebFetch` on awoiaf.westeros.org | Cloudflare 403s every page. Go straight to the CDX pipeline. | +| Citing the `web.archive.org` URL in `sources` | The mirror is the fetch mechanism, not the citation. | +| `bun test` instead of `bun run test` | The script is `bun test --isolate --dots`; the bare form mis-reports the DOM suite. | +| Committing without `bun format` | `oxfmt` covers `.claude/**/*.ts` and markdown, and CI fails on drift. | ## Related skills From b7d4a6ec115df500f0dbf16793debbe251086d03 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:24:35 -0400 Subject: [PATCH 06/37] TKW: let `mentions` settle a shared name in the prose linker - 50 character names are shared by two or more entries, and the first to register kept the surface form regardless of the page - `targetsOf` now orders each kind's entries with the page's `mentions` first, so a page that names the intended entry links to it - unmentioned collisions keep the previous first-wins order --- lib/prose-links.test.ts | 43 +++++++++++++++++++++++++++++++++++++++++ lib/prose-links.ts | 19 +++++++++++++++++- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/prose-links.test.ts b/lib/prose-links.test.ts index 9ddc7f0a..fe841230 100644 --- a/lib/prose-links.test.ts +++ b/lib/prose-links.test.ts @@ -709,3 +709,46 @@ describe("prose-links: castles, battles, and events", () => { ]); }); }); + +describe("prose-links: shared names", () => { + const ELDER = character({ + slug: "rhaenys-targaryen", + name: "Rhaenys Targaryen", + }); + const YOUNGER = character({ + slug: "rhaenys-targaryen-queen-who-never-was", + name: "Rhaenys Targaryen", + }); + + it("gives a shared name to the first entry when neither is mentioned", async () => { + const index = indexFor({ + current: { kind: "dragon", slug: "meleys" }, + characters: [ELDER, YOUNGER], + }); + const html = await renderWith( + "Claimed by Princess Rhaenys Targaryen.", + index, + ); + expect(html).toContain( + 'Rhaenys Targaryen', + ); + }); + + it("lets `mentions` pick the winner when two entries share a name", async () => { + const index = indexFor({ + current: { + kind: "dragon", + slug: "meleys", + mentions: ["rhaenys-targaryen-queen-who-never-was"], + }, + characters: [ELDER, YOUNGER], + }); + const html = await renderWith( + "Claimed by Princess Rhaenys Targaryen.", + index, + ); + expect(html).toContain( + 'Rhaenys Targaryen', + ); + }); +}); diff --git a/lib/prose-links.ts b/lib/prose-links.ts index 3a1c5d6f..70b0de8f 100644 --- a/lib/prose-links.ts +++ b/lib/prose-links.ts @@ -86,12 +86,22 @@ function targetsOf({ kind, entries, forms, + mentioned, }: { kind: ProseLinkKind; entries: ReadonlyArray<{ frontmatter: T }>; forms: (frontmatter: T) => string[]; + mentioned: ReadonlySet; }): ProseLinkTarget[] { - return entries.flatMap(({ frontmatter: fm }) => { + // The first target to register a surface form keeps it, so an entry the + // page lists in `mentions` goes first: three characters are named + // "Rhaenys Targaryen", and only the page knows which one it means. + const ordered = entries.toSorted( + (a, b) => + Number(mentioned.has(b.frontmatter.slug)) - + Number(mentioned.has(a.frontmatter.slug)), + ); + return ordered.flatMap(({ frontmatter: fm }) => { if (fm.draft) return []; const surfaceForms = uniqueOrdered(forms(fm)); if (surfaceForms.length === 0) return []; @@ -135,6 +145,7 @@ export function buildProseLinkIndex(args: { const characterTargets = targetsOf({ kind: "character", entries: allCharacters, + mentioned, forms: (fm) => { if (fm.placeholder) return []; const forms = [fm.name, ...fm.aliases]; @@ -146,6 +157,7 @@ export function buildProseLinkIndex(args: { const houseTargets = targetsOf({ kind: "house", entries: allHouses, + mentioned, forms: (fm) => { const forms = [fm.name]; if (mentioned.has(fm.slug)) { @@ -159,12 +171,14 @@ export function buildProseLinkIndex(args: { const weaponTargets = targetsOf({ kind: "weapon", entries: allWeapons, + mentioned, forms: (fm) => [fm.name, ...fm.aliases], }); const dragonTargets = targetsOf({ kind: "dragon", entries: allDragons, + mentioned, forms: (fm) => [fm.name, ...fm.aliases], }); @@ -178,6 +192,7 @@ export function buildProseLinkIndex(args: { const castleTargets = targetsOf({ kind: "castle", entries: allCastles, + mentioned, forms: (fm) => { const forms = [fm.name, stripArticle(fm.name)]; return forms.some((f) => houseShortNames.has(f)) ? [] : forms; @@ -187,12 +202,14 @@ export function buildProseLinkIndex(args: { const battleTargets = targetsOf({ kind: "battle", entries: allBattles, + mentioned, forms: (fm) => [fm.name, ...fm.aliases, stripArticle(fm.name)], }); const eventTargets = targetsOf({ kind: "event", entries: allEvents, + mentioned, forms: (fm) => [fm.name, ...fm.aliases, stripArticle(fm.name)], }); From 783b6a08df5b91098c2b7d166b5216e07dbb6530 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:47:49 -0400 Subject: [PATCH 07/37] TKW: add regnal aliases to the Targaryen kings - "Aegon I" through "Aegon V", "Aenys I", "Maegor I", "Jaehaerys I" and "II", "Viserys I" and "II", "Daeron I" and "II", "Baelor I", "Aerys I", "Maekar I" as `aliases`, so "King Aegon I" in a body links - `aegon-i-targaryen` also gains "Aegon the Conqueror" and "Aegon the Dragon"; the existing "The Conqueror" never matched lowercase prose - `aerys-ii-targaryen` already carried "Aerys II" and is unchanged --- content/characters/aegon-i-targaryen.md | 3 +++ content/characters/aegon-ii-targaryen.md | 1 + content/characters/aegon-iii-targaryen.md | 1 + content/characters/aegon-iv-targaryen.md | 1 + content/characters/aegon-v-targaryen.md | 1 + content/characters/aenys-i-targaryen.md | 1 + content/characters/aerys-i-targaryen.md | 2 ++ content/characters/baelor-i-targaryen.md | 1 + content/characters/daeron-i-targaryen.md | 1 + content/characters/daeron-ii-targaryen.md | 1 + content/characters/jaehaerys-i-targaryen.md | 1 + content/characters/jaehaerys-ii-targaryen.md | 2 ++ content/characters/maegor-i-targaryen.md | 1 + content/characters/maekar-i-targaryen.md | 1 + content/characters/viserys-i-targaryen.md | 1 + content/characters/viserys-ii-targaryen.md | 2 ++ 16 files changed, 21 insertions(+) diff --git a/content/characters/aegon-i-targaryen.md b/content/characters/aegon-i-targaryen.md index db295186..dc3d4ccb 100644 --- a/content/characters/aegon-i-targaryen.md +++ b/content/characters/aegon-i-targaryen.md @@ -29,6 +29,9 @@ aliases: - The Dragon - The Dragonlord - Of Dragonstone + - Aegon I + - Aegon the Conqueror + - Aegon the Dragon sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aegon_I_Targaryen diff --git a/content/characters/aegon-ii-targaryen.md b/content/characters/aegon-ii-targaryen.md index 30f70abd..0c42216a 100644 --- a/content/characters/aegon-ii-targaryen.md +++ b/content/characters/aegon-ii-targaryen.md @@ -28,6 +28,7 @@ titles: aliases: - Aegon the Elder - Aegon the Usurper + - Aegon II sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aegon_II_Targaryen diff --git a/content/characters/aegon-iii-targaryen.md b/content/characters/aegon-iii-targaryen.md index facc59bd..45b2e222 100644 --- a/content/characters/aegon-iii-targaryen.md +++ b/content/characters/aegon-iii-targaryen.md @@ -34,6 +34,7 @@ aliases: - The Younger - The Unhappy - The Uncrowned King + - Aegon III sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aegon_III_Targaryen diff --git a/content/characters/aegon-iv-targaryen.md b/content/characters/aegon-iv-targaryen.md index ac2ff5fd..9bfc2ff3 100644 --- a/content/characters/aegon-iv-targaryen.md +++ b/content/characters/aegon-iv-targaryen.md @@ -30,6 +30,7 @@ titles: - Prince of Dragonstone aliases: - The Unworthy + - Aegon IV sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aegon_IV_Targaryen diff --git a/content/characters/aegon-v-targaryen.md b/content/characters/aegon-v-targaryen.md index 2299a77a..1f1ef725 100644 --- a/content/characters/aegon-v-targaryen.md +++ b/content/characters/aegon-v-targaryen.md @@ -31,6 +31,7 @@ aliases: - Egg - The Fortunate - The Prince Who Was An Egg + - Aegon V sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aegon_V_Targaryen diff --git a/content/characters/aenys-i-targaryen.md b/content/characters/aenys-i-targaryen.md index dd26d98b..4586813b 100644 --- a/content/characters/aenys-i-targaryen.md +++ b/content/characters/aenys-i-targaryen.md @@ -30,6 +30,7 @@ titles: - Protector of the Realm aliases: - King Abomination + - Aenys I sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aenys_I_Targaryen diff --git a/content/characters/aerys-i-targaryen.md b/content/characters/aerys-i-targaryen.md index bfa7ad2d..3407546f 100644 --- a/content/characters/aerys-i-targaryen.md +++ b/content/characters/aerys-i-targaryen.md @@ -20,6 +20,8 @@ titles: - King of the Andals, the Rhoynar, and the First Men - Lord of the Seven Kingdoms - Protector of the Realm +aliases: + - Aerys I sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Aerys_I_Targaryen diff --git a/content/characters/baelor-i-targaryen.md b/content/characters/baelor-i-targaryen.md index 4ca24840..63bee29f 100644 --- a/content/characters/baelor-i-targaryen.md +++ b/content/characters/baelor-i-targaryen.md @@ -25,6 +25,7 @@ aliases: - The Beloved - The Septon King - The Befuddled + - Baelor I sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Baelor_I_Targaryen diff --git a/content/characters/daeron-i-targaryen.md b/content/characters/daeron-i-targaryen.md index 82648fdd..f842a60f 100644 --- a/content/characters/daeron-i-targaryen.md +++ b/content/characters/daeron-i-targaryen.md @@ -22,6 +22,7 @@ aliases: - The Young Dragon - Boy King - Daeron the Dragon + - Daeron I sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Daeron_I_Targaryen diff --git a/content/characters/daeron-ii-targaryen.md b/content/characters/daeron-ii-targaryen.md index 99f4bb12..8e2abeb1 100644 --- a/content/characters/daeron-ii-targaryen.md +++ b/content/characters/daeron-ii-targaryen.md @@ -28,6 +28,7 @@ titles: aliases: - The Good - The Falseborn + - Daeron II sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Daeron_II_Targaryen diff --git a/content/characters/jaehaerys-i-targaryen.md b/content/characters/jaehaerys-i-targaryen.md index 6e798903..30d9b7eb 100644 --- a/content/characters/jaehaerys-i-targaryen.md +++ b/content/characters/jaehaerys-i-targaryen.md @@ -38,6 +38,7 @@ aliases: - The Conciliator - The Old King - The Wise + - Jaehaerys I sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Jaehaerys_I_Targaryen diff --git a/content/characters/jaehaerys-ii-targaryen.md b/content/characters/jaehaerys-ii-targaryen.md index 1888ee39..6774edee 100644 --- a/content/characters/jaehaerys-ii-targaryen.md +++ b/content/characters/jaehaerys-ii-targaryen.md @@ -23,6 +23,8 @@ titles: - King of the Andals, the Rhoynar, and the First Men - Lord of the Seven Kingdoms - Protector of the Realm +aliases: + - Jaehaerys II sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Jaehaerys_II_Targaryen diff --git a/content/characters/maegor-i-targaryen.md b/content/characters/maegor-i-targaryen.md index 2d25b039..e33d8e7c 100644 --- a/content/characters/maegor-i-targaryen.md +++ b/content/characters/maegor-i-targaryen.md @@ -28,6 +28,7 @@ titles: aliases: - The Cruel - The Abomination on the Iron Throne + - Maegor I sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Maegor_I_Targaryen diff --git a/content/characters/maekar-i-targaryen.md b/content/characters/maekar-i-targaryen.md index 0975e143..70d61ab8 100644 --- a/content/characters/maekar-i-targaryen.md +++ b/content/characters/maekar-i-targaryen.md @@ -13,6 +13,7 @@ died: primary-house: targaryen aliases: - The Anvil + - Maekar I parents: - daeron-ii-targaryen - myriah-martell diff --git a/content/characters/viserys-i-targaryen.md b/content/characters/viserys-i-targaryen.md index a971bbf5..fb3f9b07 100644 --- a/content/characters/viserys-i-targaryen.md +++ b/content/characters/viserys-i-targaryen.md @@ -25,6 +25,7 @@ children: - daeron-targaryen-son-of-viserys-i aliases: - The Young King + - Viserys I titles: - King of the Andals, the Rhoynar, and the First Men - Lord of the Seven Kingdoms diff --git a/content/characters/viserys-ii-targaryen.md b/content/characters/viserys-ii-targaryen.md index 1a7db457..17190aab 100644 --- a/content/characters/viserys-ii-targaryen.md +++ b/content/characters/viserys-ii-targaryen.md @@ -25,6 +25,8 @@ titles: - Lord of the Seven Kingdoms - Protector of the Realm - Hand of the King +aliases: + - Viserys II sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Viserys_II_Targaryen From 45b2ff12b36d9b33ba7d5ac31c671061e88620af Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:50:00 -0400 Subject: [PATCH 08/37] TKW: populate `jaenara-belaerys.md` from AWOIAF - Valyrian dragonrider of Terrax, explorer of Sothoryos, no house entry so `primary-house: null` - one-paragraph body, dates unknown --- content/characters/jaenara-belaerys.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 content/characters/jaenara-belaerys.md diff --git a/content/characters/jaenara-belaerys.md b/content/characters/jaenara-belaerys.md new file mode 100644 index 00000000..f89a99ab --- /dev/null +++ b/content/characters/jaenara-belaerys.md @@ -0,0 +1,15 @@ +--- +slug: jaenara-belaerys +name: Jaenara Belaerys +sex: f +born: null +died: null +primary-house: null +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Jaenara_Belaerys + license: CC-BY-SA-3.0 +draft: false +--- + +A dragonrider of the Valyrian Freehold, of the Belaerys family, remembered for a single feat of exploration. Upon her dragon _Terrax_ she flew farther south into Sothoryos than any who came before her, and returned to Valyria after three years having found nothing but endless jungle, deserts, and mountains. Jaenara declared the southern continent to be as large as Essos, "a land without end", and no Valyrian is recorded to have flown beyond the bounds she set. From 09a57bc0636ecc12cc63c1d0ea3fcf863179848e Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:50:25 -0400 Subject: [PATCH 09/37] TKW: populate `aurion.md` from AWOIAF - Valyrian dragonlord and self-styled Emperor of Valyria, lost with his host in the ruined peninsula - `died` 102 BC at `decade` precision, matching "102 BC or shortly after" --- content/characters/aurion.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 content/characters/aurion.md diff --git a/content/characters/aurion.md b/content/characters/aurion.md new file mode 100644 index 00000000..bfcbd450 --- /dev/null +++ b/content/characters/aurion.md @@ -0,0 +1,21 @@ +--- +slug: aurion +name: Aurion +sex: m +born: null +died: + year: 102 + era: BC + precision: decade +primary-house: null +titles: + - Dragonlord + - Emperor of Valyria +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Aurion + license: CC-BY-SA-3.0 +draft: false +--- + +One of the few dragonlords to outlive the Doom of Valyria, Aurion was in Qohor when the Fourteen Flames burst. The histories of that city record that he raised a host of thirty thousand from the Qohorik colonists, declared himself the first Emperor of Valyria, and flew south upon his dragon at the head of his army to claim what remained of the Freehold and raise it up again. Neither the emperor, his dragon, nor a single man of his host was ever seen again, and the smoking ruin of the peninsula kept whatever it did with them. From de0550847bd3d6fc2b7ac98564c8131ba15e4bd2 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:51:15 -0400 Subject: [PATCH 10/37] TKW: populate `serwyn-of-the-mirror-shield.md` from AWOIAF - Age of Heroes slayer of the dragon Urrax, served the Gardener kings, no house so `primary-house: null` - legendary figure, so `born` and `died` stay `null` like `brandon-the-builder` --- content/characters/serwyn-of-the-mirror-shield.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 content/characters/serwyn-of-the-mirror-shield.md diff --git a/content/characters/serwyn-of-the-mirror-shield.md b/content/characters/serwyn-of-the-mirror-shield.md new file mode 100644 index 00000000..6cb30ad5 --- /dev/null +++ b/content/characters/serwyn-of-the-mirror-shield.md @@ -0,0 +1,15 @@ +--- +slug: serwyn-of-the-mirror-shield +name: Serwyn of the Mirror Shield +sex: m +born: null +died: null +primary-house: null +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Serwyn_of_the_Mirror_Shield + license: CC-BY-SA-3.0 +draft: false +--- + +A hero of the Age of Heroes and a favorite of the smallfolk, who served the Gardener kings of the Reach in the days of the First Men. The songs credit him with saving the princess Daeryssa from giants, and with slaying the dragon _Urrax_: he came at the beast behind a shield polished to a mirror, so that the dragon saw only its own reflection, and put a spear through its eye. It is said that the ghosts of every knight he had killed haunted him thereafter. Singers now make Serwyn a knight of the Kingsguard, though that order was not founded until 10 AC, thousands of years after his time; his fame remains such that Tyrion Lannister reached for his name when measuring the love the smallfolk bore Ser Barristan Selmy. From a558d5b0266b5221547c38bda34d166f241e121d Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:53:57 -0400 Subject: [PATCH 11/37] TKW: populate `grey-king.md` from AWOIAF - legendary first king of the Iron Islands, slayer of the sea dragon Nagga - no house and no dates, matching the other Age of Heroes figures --- content/characters/grey-king.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 content/characters/grey-king.md diff --git a/content/characters/grey-king.md b/content/characters/grey-king.md new file mode 100644 index 00000000..4133829a --- /dev/null +++ b/content/characters/grey-king.md @@ -0,0 +1,17 @@ +--- +slug: grey-king +name: Grey King +sex: m +born: null +died: null +primary-house: null +titles: + - King of the Iron Islands +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Grey_King + license: CC-BY-SA-3.0 +draft: false +--- + +The legendary first king of the ironborn, said to have ruled all the Iron Islands for a thousand and seven years in the Age of Heroes; his given name is not remembered, and he is called the Grey King for the grey of his hair, his beard, and his eyes, which were the color of the winter sea. The legends credit him with slaying the sea dragon _Nagga_, whose bones the Drowned God turned to stone so that the king might raise his hall from her ribs and warm it with her living fire; with taking a mermaid to wife so that his sons could live on land or in the sea; with carving the first longship from the pale wood of Ygg, the demon tree that fed on men; and with stealing fire from the Storm God by taunting him into striking a tree with lightning. He wore a crown of driftwood, so that all who knelt would know his power came from the sea, and at the end of his long life he cast it aside and walked into the waves to sit at the right hand of the Drowned God. He left a hundred sons who fell to quarrelling, and the sixteen who survived divided the isles between them; every great house of the Iron Islands but the Goodbrothers claims descent from him, the Greyjoys of Pyke among them. From f912cdec44875b3babceb70bda9a8eb35855949d Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:55:43 -0400 Subject: [PATCH 12/37] TKW: stop pinning the dragon roster in `content.test.ts` - `loadAllDragons` round-trip asserts the seven seeded slugs are present rather than the whole list, so new dragons do not fail the suite --- lib/content.test.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/content.test.ts b/lib/content.test.ts index ef83ec87..e88d4009 100644 --- a/lib/content.test.ts +++ b/lib/content.test.ts @@ -168,17 +168,19 @@ describe("loadDragon round-trip", () => { }); describe("loadAllDragons round-trip", () => { - it("returns all seven seeded dragons", async () => { + it("returns the seeded dragons", async () => { const all = await loadAllDragons(); - const slugs = all.map((d) => d.frontmatter.slug).sort(); - expect(slugs).toEqual([ - "balerion", - "cannibal", - "caraxes", - "meraxes", - "sunfyre", - "vermithor", - "vhagar", - ]); + const slugs = all.map((d) => d.frontmatter.slug); + expect(slugs).toEqual( + expect.arrayContaining([ + "balerion", + "cannibal", + "caraxes", + "meraxes", + "sunfyre", + "vermithor", + "vhagar", + ]), + ); }); }); From aae2f8473c40c1c4fc4fa1e9caf9a1bfd6ec6c88 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:55:52 -0400 Subject: [PATCH 13/37] TKW: populate `drogon.md` from AWOIAF - first of Daenerys's three dragons; `status: extant`, `died: null`, hatched 299 AC - two-paragraph body from the pyre to Daznak's Pit --- content/dragons/drogon.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 content/dragons/drogon.md diff --git a/content/dragons/drogon.md b/content/dragons/drogon.md new file mode 100644 index 00000000..38d20edc --- /dev/null +++ b/content/dragons/drogon.md @@ -0,0 +1,29 @@ +--- +slug: drogon +name: Drogon +color: black, with red horns, eyes, and spinal plates +size: young +hatched: + year: 299 + era: AC + precision: year +died: null +status: extant +house: targaryen +riders: + - daenerys-targaryen +aliases: + - Balerion come again + - winged shadow +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Drogon + license: CC-BY-SA-3.0 +draft: false +--- + +Drogon is the black dragon of Daenerys Targaryen, hatched in 299 AC from a petrified egg laid upon the funeral pyre of Khal Drogo in the Dothraki sea, and named for the dead khal. He was the largest of the three hatchlings and has remained so, black-scaled and slashed with scarlet, his horns and spinal plates blood red, his eyes like coals; some among Daenerys's followers named him Balerion come again, though the queen would not give him a dead dragon's name. He is also the fiercest and wildest of the three, and the hardest for her to rein. + +It was Drogon who burned the heart of the House of the Undying in Qarth, and Drogon who loosed his flame in the face of Kraznys mo Nakloz at Astapor when the queen said "Dracarys". After a Meereenese shepherd laid the burned bones of his daughter before her throne, Daenerys had her dragons chained, but Drogon killed four men and escaped, flying north toward the Dothraki sea. He returned in 300 AC to Daznak's Pit, drawn by blood and noise, and there Daenerys took up a whip, climbed upon his back, and flew for the first time; he carried her to his lair on a hill in the grass sea, his wings by then twenty feet from tip to tip, and would not be turned back toward the city. From 4b4726bec4a9b071ab669373ab06d85246a5fe8f Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:56:02 -0400 Subject: [PATCH 14/37] TKW: populate `rhaegal.md` from AWOIAF - green dragon named for Rhaegar, never ridden, so `riders: []` - body covers the pit beneath the Great Pyramid, Quentyn Martell's burning, and the lair on Yherizan --- content/dragons/rhaegal.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 content/dragons/rhaegal.md diff --git a/content/dragons/rhaegal.md b/content/dragons/rhaegal.md new file mode 100644 index 00000000..785fdcc1 --- /dev/null +++ b/content/dragons/rhaegal.md @@ -0,0 +1,25 @@ +--- +slug: rhaegal +name: Rhaegal +color: green and bronze, with jade-green scales and bronze eyes +size: young +hatched: + year: 299 + era: AC + precision: year +died: null +status: extant +house: targaryen +riders: [] +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Rhaegal + license: CC-BY-SA-3.0 +draft: false +--- + +Rhaegal is the green dragon of Daenerys Targaryen, hatched with _Drogon_ and _Viserion_ upon Khal Drogo's pyre in the Dothraki sea in 299 AC and named for her brother, Prince Rhaegar Targaryen. His scales and wings are jade green and his eyes bronze, his teeth black needles, and his flame burns orange and yellow shot through with veins of green. No rider has ever mounted him. + +When a shepherd laid the bones of his daughter before the queen in Meereen, Daenerys had Rhaegal and Viserion chained in a makeshift pit beneath the Great Pyramid; it took three days to drag the green dragon from the terrace, and six men were burned in the doing. His confinement made him savage. In 300 AC, after the queen had vanished on Drogon's back, Prince Quentyn Martell came into the pit to claim a dragon with a whip and had eyes only for Viserion; Rhaegal was behind him, and burned him so badly that he died days later. Loosed upon the city, Rhaegal made his lair first upon the pyramid of Hazkar, which collapsed beneath him, and then upon the pyramid of Yherizan, and Ser Barristan Selmy judged him the more dangerous of the two brothers left in Meereen. From 4c5350e7b342e4fcbf2581cf2d2da4e580a0ee14 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:56:11 -0400 Subject: [PATCH 15/37] TKW: populate `viserion.md` from AWOIAF - cream-and-gold dragon named for Viserys, never ridden; alias "white dragon" for the prose linker - body covers the pit, Quentyn Martell, and the lair on Uhlez --- content/dragons/viserion.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 content/dragons/viserion.md diff --git a/content/dragons/viserion.md b/content/dragons/viserion.md new file mode 100644 index 00000000..f24eaa6f --- /dev/null +++ b/content/dragons/viserion.md @@ -0,0 +1,26 @@ +--- +slug: viserion +name: Viserion +color: cream, with gold horns, wing bones, and crest, and eyes of molten gold +size: young +hatched: + year: 299 + era: AC + precision: year +died: null +status: extant +house: targaryen +riders: [] +aliases: + - white dragon +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Viserion + license: CC-BY-SA-3.0 +draft: false +--- + +Viserion is the cream-and-gold dragon of Daenerys Targaryen, hatched in 299 AC upon Khal Drogo's pyre beside _Drogon_ and _Rhaegal_ and named for her brother Viserys. His scales are cream, his horns, wing bones, and spinal crest gold, and his eyes two pools of molten gold; his flame is pale gold shot with red and orange, and men who see him call him the white dragon. He is the gentlest of the three, fond enough of the sellsword Brown Ben Plumm to land upon his shoulder. + +When the queen chained her dragons in Meereen, she led Viserion down to the pit beneath the Great Pyramid herself and shut him in with oxen, and he was chained while he slept off the feast. By the time she showed the dragons to Prince Quentyn Martell he had shattered one chain and melted the others, and clung to the roof of the pit like a great white bat. After Daenerys vanished from Daznak's Pit, Quentyn came with a whip to tame him, and a crossbow bolt from one of the Brazen Beasts turned the dragon on the men; in the chaos the pit doors were left open, and Viserion flew free to make his lair in the pyramid of Uhlez. Ser Barristan Selmy has since seen pale wings moving above the hills beyond the city. From 384d662839e05f4e4bc308bda2f79f9e0878edae Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:57:09 -0400 Subject: [PATCH 16/37] TKW: populate `meleys.md` from AWOIAF - the Red Queen, ridden by Alyssa then Rhaenys, killed at Rook's Rest in 129 AC - `hatched` before 75 AC at `decade` precision; alias written without the article so "the Red Queen" links --- content/dragons/meleys.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 content/dragons/meleys.md diff --git a/content/dragons/meleys.md b/content/dragons/meleys.md new file mode 100644 index 00000000..429f098e --- /dev/null +++ b/content/dragons/meleys.md @@ -0,0 +1,32 @@ +--- +slug: meleys +name: Meleys +color: scarlet, with pink wing membranes and copper crest, horns, and claws +size: great +hatched: + year: 70 + era: AC + precision: decade +died: + year: 129 + era: AC + precision: year +status: dead +house: targaryen +riders: + - alyssa-targaryen-daughter-of-jaehaerys-i + - rhaenys-targaryen-queen-who-never-was +aliases: + - Red Queen +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Meleys + license: CC-BY-SA-3.0 +draft: false +--- + +Meleys the Red Queen was a she-dragon of scarlet scales and pink wings, her crest, horns, and claws bright as copper, and in her youth the swiftest dragon in Westeros, able to outpace both _Caraxes_ and _Vhagar_. She lay unridden in the Dragonpit until 75 AC, when the newly wed Princess Alyssa Targaryen passed over old _Balerion_ for a faster mount and claimed her; Alyssa flew her sons Viserys and Daemon upon Meleys within days of their births, and the dragon went riderless when the princess died in 84 AC. Princess Rhaenys Targaryen claimed her three years later and rode her to Highgarden on the royal progress and to her own wedding with Lord Corlys Velaryon. + +By the Dance of the Dragons Meleys had grown lazy, though she remained cunning and fearsome when roused. In 129 AC Rhaenys flew her to relieve Rook's Rest, where scorpion bolts only angered her and she burned some eight hundred of Ser Criston Cole's men before King Aegon II on _Sunfyre_ and Prince Aemond on _Vhagar_ fell upon her from above. She tore half a wing from Sunfyre in the fight a thousand feet over the field, but she could not prevail against two, and she was torn apart when she struck the ground. A blackened body found beside her carcass was taken for the princess, and the greens carried Meleys's head back to King's Landing. From 43195dac7396e8cdfe661ecf57bd5cff0bdd35a5 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:58:26 -0400 Subject: [PATCH 17/37] TKW: populate `tessarion.md` from AWOIAF - the Blue Queen, Daeron the Daring's dragon, died in the three-way fight at Second Tumbleton in 130 AC - `hatched` by 120 AC at `decade` precision --- content/dragons/tessarion.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 content/dragons/tessarion.md diff --git a/content/dragons/tessarion.md b/content/dragons/tessarion.md new file mode 100644 index 00000000..64fd32fe --- /dev/null +++ b/content/dragons/tessarion.md @@ -0,0 +1,31 @@ +--- +slug: tessarion +name: Tessarion +color: dark cobalt blue, with claws, crest, and belly scales of bright beaten copper +size: young +hatched: + year: 120 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: targaryen +riders: + - daeron-targaryen-son-of-viserys-i +aliases: + - Blue Queen +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Tessarion + license: CC-BY-SA-3.0 +draft: false +--- + +Tessarion, the Blue Queen, was a beautiful young she-dragon of dark cobalt, her claws, crest, and belly scales the color of beaten copper, whose flame burned blue. She had bonded with Prince Daeron Targaryen, youngest son of Viserys I, by 120 AC, and by the outbreak of the Dance of the Dragons she was of fighting weight, though the youngest and smallest of the greens' dragons and only a third the size of _Vermithor_; what she lacked in bulk she made up in nimbleness. + +Daeron rode her to the Battle of the Honeywine in 130 AC, where her arrival turned the day for Lord Ormund Hightower, and thereafter she flew ahead of the Hightower host up the Roseroad, scattering Queen Rhaenyra's loyalists who would not face her fire. She fought at the First Battle of Tumbleton and was left unchained in the camp west of the town. When Addam Velaryon fell upon that camp by night on _Seasmoke_, Daeron was slain in his tent at the outset, and the riderless Tessarion rose shrieking to meet Seasmoke in the air, vanishing into cloud and falling on him from behind, until Vermithor joined the fight and the three dragons tore at one another over the town. She came down broken beside the Mander, and Lord Benjicot Blackwood had his archers end her suffering with arrows through the eye. From c887d15c41f63d43f3f84a8804ddac51b6d33f08 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:59:29 -0400 Subject: [PATCH 18/37] TKW: populate `silverwing.md` from AWOIAF - Alysanne's dragon, then Ulf White's in the Dance; went wild on Red Lake and died by 153 AC - `hatched` and `died` at `decade` precision, matching the 36 to 42 and "by 153" windows --- content/dragons/silverwing.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 content/dragons/silverwing.md diff --git a/content/dragons/silverwing.md b/content/dragons/silverwing.md new file mode 100644 index 00000000..3c33b625 --- /dev/null +++ b/content/dragons/silverwing.md @@ -0,0 +1,31 @@ +--- +slug: silverwing +name: Silverwing +color: silver +size: great +hatched: + year: 36 + era: AC + precision: decade +died: + year: 153 + era: AC + precision: decade +status: dead +house: targaryen +riders: + - alysanne-targaryen + - ulf-white +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Silverwing + license: CC-BY-SA-3.0 +draft: false +--- + +Silverwing was a silvery she-dragon of House Targaryen, hatched, the legend says, from an egg her sister Rhaena laid in the cradle of Alysanne Targaryen in 36 AC. Docile by a dragon's measure and friendly even to strangers, she was often found coiled with _Vermithor_, and she carried Alysanne beside King Jaehaerys on his progresses for half a century: to Oldtown in 54 AC, where she alighted atop the Hightower and fanned its beacon with her wings, and north in 58 AC to White Harbor, Winterfell, and the Wall, where she would not fly beyond the ice. The queen rode her for the last time in 93 AC, weeping as she climbed down, and after Alysanne died in 100 AC Silverwing went back to Dragonstone and lairs in the smoking caverns of the Dragonmont. + +She was the gentlest of the riderless dragons offered at the Sowing of the Seeds in 129 AC, the only one not recorded to have killed a man who tried her, and the dragonseed Ulf White won her. He rode her in the Battle in the Gullet and at the First Battle of Tumbleton, where he and Hugh Hammer turned their cloaks and the dragon burned the town for King Aegon II. When Ulf was poisoned by Ser Hobert Hightower she went riderless again, and Lord Unwin Peake's bounty for a highborn rider cost one knight his arm and another his life. One of only four dragons alive at the end of the Dance, she grew wild under Aegon III and made her lair on an island in Red Lake, where the young king would not go to claim her, and she was dead by 153 AC. From f8d67902dc99224f22be84b6f3cc38429ae92016 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 13:59:38 -0400 Subject: [PATCH 19/37] TKW: populate `seasmoke.md` from AWOIAF - Laenor Velaryon's dragon, later Addam of Hull's; `house: velaryon` because both riders were Velaryons - killed by Vermithor at Second Tumbleton in 130 AC --- content/dragons/seasmoke.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 content/dragons/seasmoke.md diff --git a/content/dragons/seasmoke.md b/content/dragons/seasmoke.md new file mode 100644 index 00000000..360c2440 --- /dev/null +++ b/content/dragons/seasmoke.md @@ -0,0 +1,30 @@ +--- +slug: seasmoke +name: Seasmoke +color: pale silver-grey +size: mature +hatched: + year: 100 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: velaryon +riders: + - laenor-velaryon + - addam-velaryon +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Seasmoke + license: CC-BY-SA-3.0 +draft: false +--- + +Seasmoke was a pale silver-grey dragon, the pride and passion of Ser Laenor Velaryon, who had bonded with him by 101 AC. He was of fighting size by the Dance of the Dragons yet still young, twice the bulk of _Tessarion_ and nimbler in the air than his elders. After Laenor's death in 120 AC he made his lair in the Dragonmont and went riderless for near a decade, until Prince Jacaerys Velaryon called for dragonseeds in 129 AC; Seasmoke killed Ser Steffon Darklyn of the Queensguard before Addam of Hull, fifteen years old, mounted him, and Addam used the dragon to shield his brother Alyn from _Sheepstealer_. + +Seasmoke fought in the Battle in the Gullet and flew at the fall of King's Landing, and was kept in the Dragonpit to guard the city. When Queen Rhaenyra, fearing another turncloak after the Two Betrayers, ordered Ser Addam arrested, he was warned in time and escaped upon Seasmoke, taking the loyalty of the Queen's Hand, Lord Corlys, with him. Addam fell upon the green host at Tumbleton by night in 130 AC to prove that a bastard need not be a traitor. Seasmoke dueled the riderless Tessarion in the air and then, to spare the men below, flew at _Vermithor_; the Bronze Fury locked his jaws in the younger dragon's neck and tore his head away, and died of his own wounds moments after. The bones of the two dragons drew visitors to the rebuilt town for years. From ed7f7fb8491ff83ac48a0de8077a11fe3545d669 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:01:24 -0400 Subject: [PATCH 20/37] TKW: populate `dreamfyre.md` from AWOIAF - Rhaena's dragon and then Helaena's, killed bringing down the Dragonpit dome in 130 AC - `hatched` at `decade` precision for "in or shortly before 32 AC" --- content/dragons/dreamfyre.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 content/dragons/dreamfyre.md diff --git a/content/dragons/dreamfyre.md b/content/dragons/dreamfyre.md new file mode 100644 index 00000000..c8a0f970 --- /dev/null +++ b/content/dragons/dreamfyre.md @@ -0,0 +1,31 @@ +--- +slug: dreamfyre +name: Dreamfyre +color: pale blue, with silver markings and silver crests +size: great +hatched: + year: 32 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: targaryen +riders: + - rhaena-targaryen-daughter-of-aenys + - helaena-targaryen +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Dreamfyre + license: CC-BY-SA-3.0 +draft: false +--- + +Dreamfyre was a slender she-dragon of pale blue and silver, hatched late in the reign of Aegon I and bonded in 32 AC to his nine-year-old granddaughter Rhaena Targaryen, who first rode her at twelve. She carried Rhaena through the worst years of House Targaryen: to exile on Fair Isle after Maegor killed her husband beneath the Gods Eye, back to the Red Keep when the usurper summoned her to be his bride, and away again in 48 AC with her daughter Aerea and the sword _Blackfyre_ to join Jaehaerys. She had laid two clutches of eggs by 43 AC and another on Fair Isle, hatchlings Rhaena raised in the dragon yards of Dragonstone, and in 54 AC she carried her rider across all Westeros for more than a year in a fruitless search for the missing Aerea. Rhaena kept her at Harrenhal until her death in 73 AC, after which Dreamfyre lairs in the Dragonpit. + +Under Viserys I she bonded with Princess Helaena, who rode her from the age of eleven and loved her, but after Helaena's little son was murdered the queen would not fly again. When Helaena threw herself from Maegor's Holdfast in 130 AC it is said Dreamfyre rose with a roar that shook the Dragonpit and snapped two of her chains. Weeks later the mob of King's Landing stormed the pit, and she alone of the four dragons within broke free, killing more men than the other three together, until a crossbow bolt took one of her eyes and, half-blind and maddened, she flew into the great dome. It cracked and half of it fell, and Dreamfyre died beneath the stone with the dragonslayers she had fought. From 744f01fedf36bc71a23362e94fcff6451a76a3f1 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:01:33 -0400 Subject: [PATCH 21/37] TKW: populate `vermax.md` from AWOIAF - Jacaerys Velaryon's cradle dragon, lost in the Gullet in 130 AC; `house: velaryon` after his rider - `hatched` 114 to 120 AC at `decade` precision --- content/dragons/vermax.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 content/dragons/vermax.md diff --git a/content/dragons/vermax.md b/content/dragons/vermax.md new file mode 100644 index 00000000..97a23e2f --- /dev/null +++ b/content/dragons/vermax.md @@ -0,0 +1,29 @@ +--- +slug: vermax +name: Vermax +color: green +size: young +hatched: + year: 114 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: velaryon +riders: + - jacaerys-velaryon +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Vermax + license: CC-BY-SA-3.0 +draft: false +--- + +Vermax hatched from the egg that King Viserys I decreed be laid in the cradle of Prince Jacaerys Velaryon, eldest son of Rhaenyra, an answer to the whispers that the boy was no dragon's blood at all. The books give him no color, though every illustration makes him green. By 129 AC he was thriving, growing larger with every year, and strong for his youth, though snow and cold made him ill-tempered. + +Jacaerys flew him north at the outbreak of the Dance of the Dragons to win the Vale, White Harbor, and Winterfell for his mother, and won all three; Mushroom's tale that Vermax laid a clutch of eggs in the crypts of Winterfell is dismissed by Archmaester Gyldayn as a fool's story. Prince and dragon flew with the dragonseeds against the fleet of the Three Daughters in the Battle in the Gullet in 130 AC, and there, with victory seemingly at hand, Vermax flew too low, whether wounded by a bolt to the eye or dragged down by a grapnel, and crashed into a burning galley; neither dragon nor prince came out of the fire. From 2d2acffd0360768c0a343625ce9a11b61bdc7d04 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:03:33 -0400 Subject: [PATCH 22/37] TKW: populate `arrax.md` from AWOIAF - Lucerys Velaryon's cradle dragon, killed by Vhagar above Shipbreaker Bay in 129 AC - color from the author's note to an illustrator, as the books leave it unstated --- content/dragons/arrax.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 content/dragons/arrax.md diff --git a/content/dragons/arrax.md b/content/dragons/arrax.md new file mode 100644 index 00000000..d6d93677 --- /dev/null +++ b/content/dragons/arrax.md @@ -0,0 +1,29 @@ +--- +slug: arrax +name: Arrax +color: pearlescent white, with a golden chest and golden eyes +size: young +hatched: + year: 115 + era: AC + precision: decade +died: + year: 129 + era: AC + precision: year +status: dead +house: velaryon +riders: + - lucerys-velaryon +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Arrax + license: CC-BY-SA-3.0 +draft: false +--- + +Arrax hatched from the egg King Viserys I ordered laid in the cradle of Prince Lucerys Velaryon, Rhaenyra's second son, and was thriving and growing by 129 AC, strong for his years though only a fifth the size of _Vhagar_. The published books never name his color; the author's own answer to an illustrator was pearlescent white, with a golden chest, golden eyes, and yellow flame. + +At the outbreak of the Dance of the Dragons Lucerys, thirteen, swore to his mother that he would not fight and flew Arrax to Storm's End to ask Lord Borros Baratheon for his swords, only to find Prince Aemond Targaryen already in the hall. Borros would allow no blood beneath his roof, so Aemond followed on Vhagar into the storm that had broken over the bay. Watchers on the walls saw distant blasts of flame above Shipbreaker Bay and heard a shriek louder than the thunder, then the two dragons locked together with the lightning around them; if there was a fight, Archmaester Gyldayn writes, it cannot have lasted long. Arrax fell broken into the storm-lashed water with his rider, and the death of the boy prince made the war a war. From b7c7dd730ed24606111f22af3d640dff0f49deee Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:03:42 -0400 Subject: [PATCH 23/37] TKW: populate `syrax.md` from AWOIAF - Rhaenyra's only dragon, killed by the mob at the Dragonpit in 130 AC after throwing Joffrey Velaryon - `hatched` late in Jaehaerys I's reign at `decade` precision --- content/dragons/syrax.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 content/dragons/syrax.md diff --git a/content/dragons/syrax.md b/content/dragons/syrax.md new file mode 100644 index 00000000..0be40297 --- /dev/null +++ b/content/dragons/syrax.md @@ -0,0 +1,30 @@ +--- +slug: syrax +name: Syrax +color: yellow +size: great +hatched: + year: 100 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: targaryen +riders: + - rhaenyra-targaryen +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Syrax + license: CC-BY-SA-3.0 +draft: false +--- + +Syrax was the yellow she-dragon of Rhaenyra Targaryen and had no other rider: the princess claimed her in 104 AC at the age of seven, when the dragon was still young, and named her for a goddess of old Valyria. She grew huge and formidable, though she was kept in chains and exceedingly well fed, and by the time of the Dance of the Dragons she had not hunted in years and had none of _Caraxes_'s experience of battle. She laid several clutches of eggs in the reign of Viserys I, Caraxes believed to be one of her mates, and from an egg of her last clutch, given to Rhaenyra's stepdaughter Rhaena, the dragon _Morning_ was hatched. + +Rhaenyra could not fly for a time after the stillbirth that opened the war, but she rode Syrax at the taking of King's Landing, and there the dragon was chained in a horse stable in the outer ward of the Red Keep while the other black dragons went to the Dragonpit. When the mob stormed the pit in 130 AC, Prince Joffrey Velaryon tried to ride Syrax to the rescue of the dragons there, and she threw him from her back to his death in mid flight. Drawn by the blood, she flew to the Hill of Rhaenys and, rather than burning the mob from the air, came down among them, killing dozens with tooth and claw until she was slain on the ground; the accounts of who dealt the killing blow contradict one another. From 20dd0802ad1f45ca9d9f4c5960a358c4142bbcf1 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:04:56 -0400 Subject: [PATCH 24/37] TKW: populate `sheepstealer.md` from AWOIAF - wild dragon of Dragonstone tamed by Nettles, last seen in the Mountains of the Moon in 134 AC - `status: lost` with `died: null`, no house, `hatched` at `decade` precision --- content/dragons/sheepstealer.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 content/dragons/sheepstealer.md diff --git a/content/dragons/sheepstealer.md b/content/dragons/sheepstealer.md new file mode 100644 index 00000000..79ffe569 --- /dev/null +++ b/content/dragons/sheepstealer.md @@ -0,0 +1,26 @@ +--- +slug: sheepstealer +name: Sheepstealer +color: mud brown +size: great +hatched: + year: 40 + era: AC + precision: decade +died: null +status: lost +house: null +riders: + - nettles +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Sheepstealer + license: CC-BY-SA-3.0 +draft: false +--- + +Sheepstealer was a wild dragon of an ugly mud-brown color, hatched on Dragonstone while Jaehaerys I was still young and never claimed, so that with each unridden year he grew stranger to men and harder to master. He lairs in the caverns at the back of the Dragonmont and hunted between Driftmark and the Wendwater, and the smallfolk named him for his taste in mutton; he would eat a sheepdog now and then but never harmed a shepherd. By the Dance of the Dragons he was well over fifty years old and one of three wild dragons on the island. + +At the Sowing of 129 AC he killed more would-be riders than _Vermithor_, _Seasmoke_, and _Silverwing_ together, tearing the arm from Silver Denys and burning Alyn of Hull, until a bastard girl called Nettles tamed him by leaving a fresh-killed sheep for him every morning until he suffered her on his back. She rode him in the Battle in the Gullet and at the taking of King's Landing, then hunted _Vhagar_ along the Trident with Prince Daemon from Maidenpool. When Queen Rhaenyra named Nettles a traitor the girl fed him the castle's largest black ram and flew off over the Bay of Crabs. He was later seen at Crackclaw Point and in the Mountains of the Moon, where in 134 AC a royal column found him and a ragged Nettles in a cave and lost sixteen men; the pair flew deeper into the mountains and were never seen again, though the Burned Men's rites are said to remember a fire-witch and her dragon. From bda92f324110e46bfa066beb45c02330f9641ab2 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:08:11 -0400 Subject: [PATCH 25/37] TKW: populate `tyraxes.md` from AWOIAF - Joffrey Velaryon's cradle dragon, killed in his lair at the Storming of the Dragonpit in 130 AC - color from the author's description to an illustrator --- content/dragons/tyraxes.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 content/dragons/tyraxes.md diff --git a/content/dragons/tyraxes.md b/content/dragons/tyraxes.md new file mode 100644 index 00000000..b5f7bcd4 --- /dev/null +++ b/content/dragons/tyraxes.md @@ -0,0 +1,29 @@ +--- +slug: tyraxes +name: Tyraxes +color: pale violet, with dark purple horns +size: young +hatched: + year: 117 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: velaryon +riders: + - joffrey-velaryon +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Tyraxes + license: CC-BY-SA-3.0 +draft: false +--- + +Tyraxes hatched from the egg laid by royal decree in the cradle of Prince Joffrey Velaryon, youngest of Rhaenyra's three sons by Laenor, and was a young and strong dragon by 129 AC, growing every year though a little smaller than his brothers' _Vermax_ and _Arrax_. The books do not give his color; the author has described him to an illustrator as pale violet, with dark purple horns and purple flame. When the Dance of the Dragons began he could carry his rider long distances but was not yet big enough for battle, and Rhaenyra refused Joffrey's every plea to fight. + +He carried Joffrey and Rhaena of Pentos to the Vale to be wards of Lady Jeyne Arryn, and came back to King's Landing after the city fell to the blacks in 130 AC, when Joffrey, not yet thirteen, was named heir and swore to keep Tyraxes for the defense of the Red Keep. The dragon lairs in the Dragonpit, and when the Shepherd's mob marched on the pit Joffrey, forbidden to go to him, took his mother's _Syrax_ instead and was thrown to his death. Tyraxes drew back into his lair as the dragonslayers came, and burned so many in the passage that the way was choked with the dead, but the mob climbed over their own corpses, and the young dragon, tangled in his chains, was hacked to death. From 3ee81850912ed6bbe4550041e341461ec7cfe890 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:08:57 -0400 Subject: [PATCH 26/37] TKW: populate `moondancer.md` from AWOIAF - Baela Targaryen's young dragon, killed by Sunfyre over Dragonstone in 130 AC after crippling him - `hatched: null`, since the source gives no year --- content/dragons/moondancer.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 content/dragons/moondancer.md diff --git a/content/dragons/moondancer.md b/content/dragons/moondancer.md new file mode 100644 index 00000000..5185c7b8 --- /dev/null +++ b/content/dragons/moondancer.md @@ -0,0 +1,27 @@ +--- +slug: moondancer +name: Moondancer +color: pale green, with horns, crest, and wingbones of pearl +size: young +hatched: null +died: + year: 130 + era: AC + precision: year +status: dead +house: targaryen +riders: + - baela-targaryen +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Moondancer + license: CC-BY-SA-3.0 +draft: false +--- + +Moondancer was a slender, beautiful young she-dragon of pale green, her horns, crest, and wingbones the color of pearl, and very quick both in the air and on the ground. Hatched on Dragonstone, she was not yet large enough to carry the thirteen-year-old Lady Baela Targaryen when the Dance of the Dragons began in 129 AC, but within the year Baela was riding her daily to every corner of the island and across to Driftmark, though the dragon was still no bigger than a warhorse and weighed less. + +When Dragonstone was betrayed to King Aegon II in 130 AC, Baela broke from her chambers, loosed Moondancer's chains, and rose to meet _Sunfyre_ as the king came in to land in the castle yard. The smaller dragon was far nimbler than the half-crippled Sunfyre and tore at his back and ruined wing until a blast of his flame took her full in the eyes; blinded, she flew into him and brought them both down together. On the ground her speed counted for nothing against his weight, and Sunfyre killed and devoured her, but the wounds she gave him were mortal, and he died before the year was out. From 1db3948b8f6e8bc0a43016acc2c6f703161ea5d4 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:09:37 -0400 Subject: [PATCH 27/37] TKW: populate `grey-ghost.md` from AWOIAF - wild fish-eating dragon of Dragonstone, killed and part-eaten by Sunfyre in 130 AC - never ridden, no house, `hatched: null` --- content/dragons/grey-ghost.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 content/dragons/grey-ghost.md diff --git a/content/dragons/grey-ghost.md b/content/dragons/grey-ghost.md new file mode 100644 index 00000000..d7f7bcca --- /dev/null +++ b/content/dragons/grey-ghost.md @@ -0,0 +1,25 @@ +--- +slug: grey-ghost +name: Grey Ghost +color: pale grey-white, the color of morning mist +size: young +hatched: null +died: + year: 130 + era: AC + precision: year +status: dead +house: null +riders: [] +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Grey_Ghost + license: CC-BY-SA-3.0 +draft: false +--- + +The Grey Ghost was the smallfolk's name for the shyest of the three wild dragons of Dragonstone, a pale grey-white beast the color of morning mist who could hide himself in cloud and fog and avoided men and their works for years at a time. He lairs in a smoking vent high on the eastern face of the Dragonmont and fed on fish, and was most often glimpsed flying low over the narrow sea to snatch his prey from the water. No man ever claimed or rode him, and his age is not recorded, though he is thought to have been young. + +When Prince Jacaerys Velaryon called the dragonseeds to Dragonstone in 129 AC some went looking for the Grey Ghost, Alyn of Hull among them, but none could find him. In 130 AC the crew of the _Nessaria_ saw two dragons fighting above the Dragonmont and the Grey Ghost slain; the castellan Ser Robert Quince took it for the work of the _Cannibal_, but the killer was in truth the wounded _Sunfyre_, lately returned to the island in secret, who partly devoured him. From 84a3781006d37f25da3d00e61c8edd64420fffea Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:10:40 -0400 Subject: [PATCH 28/37] TKW: populate `quicksilver.md` from AWOIAF - Aenys I's dragon, then Aegon the Uncrowned's, killed by Balerion beneath the Gods Eye in 43 AC - color noted as implied rather than stated, since the books leave it undescribed --- content/dragons/quicksilver.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 content/dragons/quicksilver.md diff --git a/content/dragons/quicksilver.md b/content/dragons/quicksilver.md new file mode 100644 index 00000000..6d3c7d0d --- /dev/null +++ b/content/dragons/quicksilver.md @@ -0,0 +1,31 @@ +--- +slug: quicksilver +name: Quicksilver +color: silver, by her name and her pale white fire, though the books never say +size: mature +hatched: + year: 7 + era: AC + precision: year +died: + year: 43 + era: AC + precision: year +status: dead +house: targaryen +riders: + - aenys-i-targaryen + - aegon-the-uncrowned +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Quicksilver + license: CC-BY-SA-3.0 +draft: false +--- + +Quicksilver hatched on Dragonstone in 7 AC and bonded as a hatchling with the infant Prince Aenys, born the same year; the sickly boy's health mended from that day, and the whispers that he was no son of Aegon the Conqueror died with them. She was Aenys's favorite mount all his life. He flew her to Sunspear in 23 AC for the feast that marked ten years of peace with Dorne, and from Highgarden to his father's funeral on Dragonstone in 37 AC, but when Harren the Red seized Harrenhal that year and Lord Tully urged him to descend upon the castle as his father had, Aenys would not. She lit his own pyre in 42 AC, with _Silverwing_ and _Vermithor_ adding their flames to hers. + +When Maegor usurped the throne, Quicksilver was left in King's Landing while the rightful heir, Prince Aegon, sheltered in the westerlands; in 43 AC he and his wife Rhaena slipped into the city during the king's absence and claimed her at last. Aegon rode her to Pinkmaiden to raise fifteen thousand men against his uncle and led them toward the capital, until a host of crownlanders barred his road south of the Gods Eye and Maegor came out of the sky upon _Balerion_. Quicksilver was a quarter the Black Dread's size and her pale white fire counted for nothing; Balerion crushed her neck in his jaws and tore a wing from her body, and dragon and prince fell together beneath the Gods Eye. From 758adefb98ab55d74d69c11dcfa26dc1e7ba1df5 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:12:30 -0400 Subject: [PATCH 29/37] TKW: populate `stormcloud.md` from AWOIAF - Aegon the Younger's cradle dragon, died at Dragonstone an hour after his first flight from the Gullet in 130 AC - color from the author's description to an illustrator --- content/dragons/stormcloud.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 content/dragons/stormcloud.md diff --git a/content/dragons/stormcloud.md b/content/dragons/stormcloud.md new file mode 100644 index 00000000..72f1ce9c --- /dev/null +++ b/content/dragons/stormcloud.md @@ -0,0 +1,30 @@ +--- +slug: stormcloud +name: Stormcloud +color: turquoise, with black horns and claws +size: young +hatched: + year: 120 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: targaryen +riders: + - aegon-iii-targaryen +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Stormcloud + license: CC-BY-SA-3.0 +draft: false +--- + +Stormcloud hatched from the egg laid in the cradle of Prince Aegon Targaryen, Rhaenyra's elder son by Daemon, and was still a young dragon his nine-year-old rider had never mounted when the Dance of the Dragons began. The books do not give his color; the author has described him to an illustrator as turquoise with black horns and claws. + +Late in 129 AC Prince Jacaerys sent his half-brothers Aegon and Viserys to the safety of Pentos aboard the cog _Gay Abandon_, Aegon with Stormcloud and Viserys with his egg. In the Gullet the cog and her escorts were taken by the warships of the Three Daughters, and Aegon escaped only by climbing onto Stormcloud's back and flying for the first time in his life. He reached Dragonstone clinging to the dragon's neck, but Stormcloud came home with the stubs of countless arrows in his belly and a scorpion bolt through his throat, and died within the hour, hissing, his hot blood running black and smoking from his wounds. Aegon never flew again. From 8ba1ff71c2da9fdbb608610c4e119848d8927b96 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:13:00 -0400 Subject: [PATCH 30/37] TKW: populate `shrykos.md` from AWOIAF - Prince Jaehaerys's cradle dragon, never ridden, killed in the Dragonpit by Hobb the Hewer in 130 AC - `hatched` at `decade` precision from the prince's birth year --- content/dragons/shrykos.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 content/dragons/shrykos.md diff --git a/content/dragons/shrykos.md b/content/dragons/shrykos.md new file mode 100644 index 00000000..6e7ea5bf --- /dev/null +++ b/content/dragons/shrykos.md @@ -0,0 +1,30 @@ +--- +slug: shrykos +name: Shrykos +color: coppery, by illustration, as the books never say +size: young +hatched: + year: 123 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: targaryen +riders: [] +aliases: [] +mentions: + - targaryen + - jaehaerys-son-of-aegon-ii +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Shrykos + license: CC-BY-SA-3.0 +draft: false +--- + +Shrykos was a young she-dragon hatched from the egg placed in the cradle of Prince Jaehaerys, eldest son of Aegon II and Helaena, and bound to him, though he was murdered at six and she was never ridden. The books do not describe her; the illustration of the Dragonpit in _The Rise of the Dragon_ makes her coppery. + +She was chained in the Dragonpit when the Shepherd's mob broke in during 130 AC, and killed scores of them before she died. Her slayer was a woodsman called Hobb the Hewer, who leapt onto her neck as she roared and twisted, locked his legs about her, and brought his axe down seven times, crying the name of one of the Seven with each blow; it was the Stranger's blow that broke through scale and bone into her skull. From 27c71be57e8a7e1536e4b92b5618f48962f0bee4 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:14:19 -0400 Subject: [PATCH 31/37] TKW: populate `morghul.md` from AWOIAF - Princess Jaehaera's cradle dragon, never ridden, killed in the Dragonpit by the Burning Knight in 130 AC - `hatched` at `decade` precision from the princess's birth year --- content/dragons/morghul.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 content/dragons/morghul.md diff --git a/content/dragons/morghul.md b/content/dragons/morghul.md new file mode 100644 index 00000000..7737dba3 --- /dev/null +++ b/content/dragons/morghul.md @@ -0,0 +1,30 @@ +--- +slug: morghul +name: Morghul +color: black, by illustration, as the books never say +size: young +hatched: + year: 123 + era: AC + precision: decade +died: + year: 130 + era: AC + precision: year +status: dead +house: targaryen +riders: [] +aliases: [] +mentions: + - targaryen + - jaehaera-targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Morghul + license: CC-BY-SA-3.0 +draft: false +--- + +Morghul was a young dragon hatched from the egg placed in the cradle of Princess Jaehaera, daughter of Aegon II and twin to Prince Jaehaerys, and bound to her, though she never rode him. The books give him no color; the illustration of the Dragonpit in _The Rise of the Dragon_ paints him black. + +When Rhaenyra's blacks took King's Landing in 130 AC, Jaehaera was spirited out of the city, but Morghul stayed chained in the Dragonpit with _Dreamfyre_, _Tyraxes_, and _Shrykos_ through the queen's half year in the capital. When the Shepherd's mob stormed the pit he slew scores with his fire despite his shackles, until a huge man in heavy armor, remembered only as the Burning Knight, drove a spear through his eye even as the dragon bathed him in flame. Morghul died never having been ridden. From 5f7fa6820b73305c66614ff9f6d150defb96e95c Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:16:05 -0400 Subject: [PATCH 32/37] TKW: populate `terrax.md` from AWOIAF - Jaenara Belaerys's dragon, explorer of Sothoryos; no color, size, or dates recorded --- content/dragons/terrax.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 content/dragons/terrax.md diff --git a/content/dragons/terrax.md b/content/dragons/terrax.md new file mode 100644 index 00000000..0ebaa400 --- /dev/null +++ b/content/dragons/terrax.md @@ -0,0 +1,19 @@ +--- +slug: terrax +name: Terrax +hatched: null +died: null +status: dead +house: null +riders: + - jaenara-belaerys +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Terrax + license: CC-BY-SA-3.0 +draft: false +--- + +Terrax was a dragon of the Valyrian Freehold, ridden by Jaenara Belaerys of the Belaerys family, and is remembered for one flight. His rider took him farther south into Sothoryos than any explorer before or since, and for three years the two of them searched that continent and found only endless jungle, deserts, and mountains, until Jaenara turned home and declared Sothoryos as large as Essos and a land without end. Nothing else is recorded of him, neither his color nor his size nor his fate, though he and his rider lived and died long before the Doom. From dd37917be0b77fff6c4da60c2b3384b8b8d6147e Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:16:14 -0400 Subject: [PATCH 33/37] TKW: populate `urrax.md` from AWOIAF - legendary dragon slain by Serwyn of the Mirror Shield; no dates, house, or rider --- content/dragons/urrax.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 content/dragons/urrax.md diff --git a/content/dragons/urrax.md b/content/dragons/urrax.md new file mode 100644 index 00000000..f86f7306 --- /dev/null +++ b/content/dragons/urrax.md @@ -0,0 +1,18 @@ +--- +slug: urrax +name: Urrax +hatched: null +died: null +status: dead +house: null +riders: [] +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Urrax + license: CC-BY-SA-3.0 +draft: false +--- + +Urrax is the dragon of the songs of the Age of Heroes, slain by Serwyn of the Mirror Shield in the days of the First Men, when Serwyn served the Gardener kings of the Reach. The singers tell that the hero came at the beast behind a shield polished bright as a mirror, so that the dragon saw nothing but its own reflection, and put his spear through its eye. Whether Urrax ever lived is a matter for the singers rather than the maesters; the tale is older than the Kingsguard the songs make Serwyn a knight of by thousands of years, and it is one of the few in Westeros in which a man kills a dragon alone. From de37de052fa60f18bf21366d6cfb8ace55927a78 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:16:23 -0400 Subject: [PATCH 34/37] TKW: populate `nagga.md` from AWOIAF - legendary sea dragon slain by the Grey King, whose stone ribs host the kingsmoot on Old Wyk - no dates, house, or rider --- content/dragons/nagga.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 content/dragons/nagga.md diff --git a/content/dragons/nagga.md b/content/dragons/nagga.md new file mode 100644 index 00000000..52e2b05b --- /dev/null +++ b/content/dragons/nagga.md @@ -0,0 +1,18 @@ +--- +slug: nagga +name: Nagga +hatched: null +died: null +status: dead +house: null +riders: [] +aliases: [] +mentions: [] +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Nagga + license: CC-BY-SA-3.0 +draft: false +--- + +Nagga was the sea dragon of the ironborn legends, slain in the Age of Heroes by the Grey King, who is said to have worn a tall pale crown made from her teeth. When she was dead the Drowned God turned her bones to stone, and from her ribs the king raised his hall on Old Wyk and warmed it with her living fire; when he walked into the sea at the end of his thousand-year reign the Storm God snuffed the fire out and the waves stole his throne, and only the bones remained. Nagga's Ribs still stand on the hill above the shore of Old Wyk, grey stone pillars where the ironborn gather for their kingsmoots, and the priests of the Drowned God count her among the god's oldest gifts. From 1986b7727f1e29925eb37f1f3b941d9624f27fbc Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:16:51 -0400 Subject: [PATCH 35/37] TKW: populate `last-dragon.md` from AWOIAF - the stunted green she-dragon of Aegon III's reign, dead in 153 AC; sourced from the `Dragon` article since she has no name - `hatched` at `decade` precision inside that reign --- content/dragons/last-dragon.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 content/dragons/last-dragon.md diff --git a/content/dragons/last-dragon.md b/content/dragons/last-dragon.md new file mode 100644 index 00000000..18e17439 --- /dev/null +++ b/content/dragons/last-dragon.md @@ -0,0 +1,29 @@ +--- +slug: last-dragon +name: The Last Dragon +color: green +size: hatchling +hatched: + year: 145 + era: AC + precision: decade +died: + year: 153 + era: AC + precision: year +status: dead +house: targaryen +riders: [] +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Dragon + license: CC-BY-SA-3.0 +draft: false +--- + +The last dragon of House Targaryen was a green she-dragon hatched in the reign of Aegon III, small and stunted, with withered wings, one of the misshapen hatchlings that came from the eggs left after the Dance of the Dragons and never grew larger than a mastiff. Ser Arlan of Pennytree saw her as a boy and remembered her all his life. She died young in 153 AC, leaving a clutch of eggs that never hatched, and no dragon was born in Westeros again until Daenerys Targaryen walked into her husband's pyre a century and a half later. + +The maesters and the wise disagree on what her death meant. Archmaester Marwyn holds that the Citadel itself conspired to see the dragons out of the world; the pyromancers of King's Landing say their spells began to fail the day she died; and Ser Arlan told the boy Dunk that the summers had grown shorter since, and the winters longer and crueler. From 1193475e60addcc5d3d093a070d506fb15f61d7d Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:18:38 -0400 Subject: [PATCH 36/37] TKW: populate `morning.md` from AWOIAF - Rhaena Targaryen's dragon, hatched from Syrax's egg in the Vale at the end of 130 AC, the last dragon the Targaryens flew - `died` centered on the 136 to 153 window at `decade` precision --- content/dragons/morning.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 content/dragons/morning.md diff --git a/content/dragons/morning.md b/content/dragons/morning.md new file mode 100644 index 00000000..e951e8d0 --- /dev/null +++ b/content/dragons/morning.md @@ -0,0 +1,30 @@ +--- +slug: morning +name: Morning +color: pale pink, with a black crest and horns +size: young +hatched: + year: 130 + era: AC + precision: year +died: + year: 145 + era: AC + precision: decade +status: dead +house: targaryen +riders: + - rhaena-targaryen-daughter-of-daemon +aliases: [] +mentions: + - targaryen +sources: + - type: awoiaf + url: https://awoiaf.westeros.org/index.php/Morning + license: CC-BY-SA-3.0 +draft: false +--- + +Morning was a she-dragon of pale pink scales with a black crest and horns, hatched in the Vale at the very end of 130 AC from one of the three eggs of _Syrax_'s last clutch that Lady Rhaena Targaryen, daughter of Daemon and Laena, had carried with her into the keeping of Lady Jeyne Arryn. Word of the hatching reached the greens as the new year began and dismayed them, for every dragon of theirs was dead, and Queen Alicent feared the smallfolk would read the birth as the gods' verdict. She was one of only four dragons alive when the Dance ended, and the only one still in Targaryen hands. + +Rhaena brought her to King's Landing after Aegon II's death in 131 AC, where the crowds rejoiced and the boy king Aegon III paled and ordered the wretched creature out of his sight; for years the little dragon rode the city on Rhaena's shoulders like a stole. By 134 AC she had grown enough to lair in the ruins of the Dragonpit, and on the third day of the third moon of 135 AC Rhaena flew her for the first time, circling the city and ranging farther each day after, though the king would never come to see her. Rhaena took her to Dragonstone that year, where they were more welcome, and when the regents deflected her wish to join the royal progress of 136 AC the record of Morning ends; she died at some time before the last dragon in 153 AC, and no one recorded how. From 93f9a3cd924a266648e0c4f731f74c7296afb6c5 Mon Sep 17 00:00:00 2001 From: CJ Rivas Date: Fri, 18 Sep 2026 14:25:43 -0400 Subject: [PATCH 37/37] TKW: pin namesake `mentions` on the new dragons - Daenerys, Rhaenys, Rhaena, Daeron, Lucerys, and Corlys each share a full name with other entries; the intended slug now sits in `mentions` so the linker picks it - `stormcloud.md` names its rider as the future Aegon III instead of the shared "Aegon Targaryen" --- content/dragons/arrax.md | 3 ++- content/dragons/dreamfyre.md | 2 ++ content/dragons/drogon.md | 1 + content/dragons/last-dragon.md | 1 + content/dragons/meleys.md | 2 ++ content/dragons/morning.md | 1 + content/dragons/rhaegal.md | 3 ++- content/dragons/stormcloud.md | 3 ++- content/dragons/tessarion.md | 1 + content/dragons/viserion.md | 3 ++- 10 files changed, 16 insertions(+), 4 deletions(-) diff --git a/content/dragons/arrax.md b/content/dragons/arrax.md index d6d93677..449335bd 100644 --- a/content/dragons/arrax.md +++ b/content/dragons/arrax.md @@ -16,7 +16,8 @@ house: velaryon riders: - lucerys-velaryon aliases: [] -mentions: [] +mentions: + - lucerys-velaryon sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Arrax diff --git a/content/dragons/dreamfyre.md b/content/dragons/dreamfyre.md index c8a0f970..1b16239e 100644 --- a/content/dragons/dreamfyre.md +++ b/content/dragons/dreamfyre.md @@ -19,6 +19,8 @@ riders: aliases: [] mentions: - targaryen + - rhaena-targaryen-daughter-of-aenys + - helaena-targaryen sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Dreamfyre diff --git a/content/dragons/drogon.md b/content/dragons/drogon.md index 38d20edc..1238016d 100644 --- a/content/dragons/drogon.md +++ b/content/dragons/drogon.md @@ -17,6 +17,7 @@ aliases: - winged shadow mentions: - targaryen + - daenerys-targaryen sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Drogon diff --git a/content/dragons/last-dragon.md b/content/dragons/last-dragon.md index 18e17439..1cbf75a3 100644 --- a/content/dragons/last-dragon.md +++ b/content/dragons/last-dragon.md @@ -17,6 +17,7 @@ riders: [] aliases: [] mentions: - targaryen + - daenerys-targaryen sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Dragon diff --git a/content/dragons/meleys.md b/content/dragons/meleys.md index 429f098e..4b3d4cd9 100644 --- a/content/dragons/meleys.md +++ b/content/dragons/meleys.md @@ -20,6 +20,8 @@ aliases: - Red Queen mentions: - targaryen + - rhaenys-targaryen-queen-who-never-was + - corlys-velaryon sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Meleys diff --git a/content/dragons/morning.md b/content/dragons/morning.md index e951e8d0..f40e8dae 100644 --- a/content/dragons/morning.md +++ b/content/dragons/morning.md @@ -18,6 +18,7 @@ riders: aliases: [] mentions: - targaryen + - rhaena-targaryen-daughter-of-daemon sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Morning diff --git a/content/dragons/rhaegal.md b/content/dragons/rhaegal.md index 785fdcc1..7ffd9c8e 100644 --- a/content/dragons/rhaegal.md +++ b/content/dragons/rhaegal.md @@ -12,7 +12,8 @@ status: extant house: targaryen riders: [] aliases: [] -mentions: [] +mentions: + - daenerys-targaryen sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Rhaegal diff --git a/content/dragons/stormcloud.md b/content/dragons/stormcloud.md index 72f1ce9c..794661be 100644 --- a/content/dragons/stormcloud.md +++ b/content/dragons/stormcloud.md @@ -18,6 +18,7 @@ riders: aliases: [] mentions: - targaryen + - aegon-iii-targaryen sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Stormcloud @@ -25,6 +26,6 @@ sources: draft: false --- -Stormcloud hatched from the egg laid in the cradle of Prince Aegon Targaryen, Rhaenyra's elder son by Daemon, and was still a young dragon his nine-year-old rider had never mounted when the Dance of the Dragons began. The books do not give his color; the author has described him to an illustrator as turquoise with black horns and claws. +Stormcloud hatched from the egg laid in the cradle of Prince Aegon, Rhaenyra's elder son by Daemon and the future Aegon III, and was still a young dragon his nine-year-old rider had never mounted when the Dance of the Dragons began. The books do not give his color; the author has described him to an illustrator as turquoise with black horns and claws. Late in 129 AC Prince Jacaerys sent his half-brothers Aegon and Viserys to the safety of Pentos aboard the cog _Gay Abandon_, Aegon with Stormcloud and Viserys with his egg. In the Gullet the cog and her escorts were taken by the warships of the Three Daughters, and Aegon escaped only by climbing onto Stormcloud's back and flying for the first time in his life. He reached Dragonstone clinging to the dragon's neck, but Stormcloud came home with the stubs of countless arrows in his belly and a scorpion bolt through his throat, and died within the hour, hissing, his hot blood running black and smoking from his wounds. Aegon never flew again. diff --git a/content/dragons/tessarion.md b/content/dragons/tessarion.md index 64fd32fe..4d809b19 100644 --- a/content/dragons/tessarion.md +++ b/content/dragons/tessarion.md @@ -19,6 +19,7 @@ aliases: - Blue Queen mentions: - targaryen + - daeron-targaryen-son-of-viserys-i sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Tessarion diff --git a/content/dragons/viserion.md b/content/dragons/viserion.md index f24eaa6f..3eb6089f 100644 --- a/content/dragons/viserion.md +++ b/content/dragons/viserion.md @@ -13,7 +13,8 @@ house: targaryen riders: [] aliases: - white dragon -mentions: [] +mentions: + - daenerys-targaryen sources: - type: awoiaf url: https://awoiaf.westeros.org/index.php/Viserion