This is the full developer documentation for DH-Forge # 404 > Page not found. Check the URL or try using the search bar. # Artifacts > Artifacts are items that can be used in a campaign. ## Ancestry [Section titled “Ancestry”](#ancestry) ID: `Ancestry` The ancestry of a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Ancestry", "type": "object", "properties": { "_type": { "const": "ancestry" }, "name": { "type": "string" }, "description": { "type": "string" }, "primaryFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false }, "secondaryFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "required": [ "_type", "name", "primaryFeature", "secondaryFeature" ], "additionalProperties": false } ``` *** ## Reference to an Ancestry [Section titled “Reference to an Ancestry”](#reference-to-an-ancestry) ID: `ReferenceAncestry` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceAncestry", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "heritage/ancestry" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` *** ## Community [Section titled “Community”](#community) ID: `Community` A community that shaped a characters backstory ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Community", "type": "object", "properties": { "_type": { "const": "community" }, "name": { "type": "string" }, "description": { "type": "string" }, "feature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "required": [ "_type", "name", "feature" ], "additionalProperties": false } ``` *** ## Reference to a Community [Section titled “Reference to a Community”](#reference-to-a-community) ID: `ReferenceCommunity` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceCommunity", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "heritage/community" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` *** ## Domain [Section titled “Domain”](#domain) ID: `Domain` A domain of a character class ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Domain", "type": "object", "properties": { "_type": { "const": "domain" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false } ``` *** ## Reference to a Domain [Section titled “Reference to a Domain”](#reference-to-a-domain) ID: `ReferenceDomain` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceDomain", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/domain" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` *** ## Armor [Section titled “Armor”](#armor) ID: `Armor` A set of armor that can be equipped by a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Armor", "type": "object", "properties": { "_type": { "default": "inventoryArmor", "const": "inventoryArmor" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "baseThresholds": { "$ref": "#/$defs/DamageThresholds" }, "baseScore": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] } }, "required": [ "_type", "name", "description", "baseThresholds", "baseScore", "features" ], "additionalProperties": false, "$defs": { "DamageThresholds": { "id": "DamageThresholds", "title": "Damage Thresholds", "description": "The damage thresholds of a character", "type": "object", "properties": { "_type": { "default": "damageThresholds", "const": "damageThresholds" }, "major": { "type": "integer", "minimum": 0, "maximum": 100 }, "severe": { "type": "integer", "minimum": 0, "maximum": 100 } }, "required": [ "_type", "major", "severe" ], "additionalProperties": false } } } ``` *** ## Reference to a piece of Armor [Section titled “Reference to a piece of Armor”](#reference-to-a-piece-of-armor) ID: `ReferenceArmor` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceArmor", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/armor" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` *** ## Thing [Section titled “Thing”](#thing) ID: `Thing` A thing that can be added to a character’s inventory ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Thing", "type": "object", "properties": { "_type": { "default": "inventoryThing", "const": "inventoryThing" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false } ``` *** ## Reference to a Thing [Section titled “Reference to a Thing”](#reference-to-a-thing) ID: `ReferenceThing` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceThing", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/thing" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` *** ## Weapon [Section titled “Weapon”](#weapon) ID: `Weapon` A weapon that can be equipped by a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Weapon", "type": "object", "properties": { "_type": { "default": "inventoryWeapon", "const": "inventoryWeapon" }, "name": { "type": "string" }, "trait": { "$ref": "#/$defs/TraitName" }, "range": { "$ref": "#/$defs/Range" }, "damageDice": { "$ref": "#/$defs/DiceType" }, "damageType": { "$ref": "#/$defs/DamageType" }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] }, "burden": { "anyOf": [ { "const": "One-Handed" }, { "const": "Two-Handed" } ] } }, "required": [ "_type", "name", "trait", "range", "damageDice", "damageType", "features", "burden" ], "additionalProperties": false, "$defs": { "TraitName": { "id": "TraitName", "title": "Trait Name", "description": "The name of a character trait", "examples": [ "Agility", "Strength", "Finesse", "Instinct", "Presence", "Knowledge" ], "anyOf": [ { "const": "Agility" }, { "const": "Strength" }, { "const": "Finesse" }, { "const": "Instinct" }, { "const": "Presence" }, { "const": "Knowledge" } ] }, "Range": { "id": "Range", "title": "Range", "description": "The range of a weapon or ability", "examples": [ "Melee", "Very Close", "Close", "Far", "Very Far" ], "anyOf": [ { "const": "Melee" }, { "const": "Very Close" }, { "const": "Close" }, { "const": "Far" }, { "const": "Very Far" } ] }, "DiceType": { "id": "DiceType", "title": "Dice Type", "description": "The type of dice to roll", "examples": [ "d4", "d6", "d8", "d10", "d12", "d20" ], "anyOf": [ { "const": "d4" }, { "const": "d6" }, { "const": "d8" }, { "const": "d10" }, { "const": "d12" }, { "const": "d20" } ] }, "DamageType": { "id": "DamageType", "title": "Damage Type", "description": "The type of damage a weapon or ability deals", "examples": [ "Physical", "Magical" ], "anyOf": [ { "const": "Physical" }, { "const": "Magical" } ] } } } ``` *** ## Reference to a Weapon [Section titled “Reference to a Weapon”](#reference-to-a-weapon) ID: `ReferenceWeapon` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceWeapon", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/weapon" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` *** ## Class [Section titled “Class”](#class) ID: `Class` A class of a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Class", "type": "object", "properties": { "_type": { "const": "class" }, "name": { "type": "string" }, "domain": { "$ref": "#/$defs/ReferenceDomain" }, "initialEvasion": { "type": "integer", "minimum": 0, "maximum": 100 }, "initialHitPoints": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "initialInventory": { "type": "array", "items": { "anyOf": [ { "$ref": "#/$defs/Thing" }, { "$ref": "#/$defs/Weapon" }, { "$ref": "#/$defs/Armor" } ] } }, "features": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "hopeFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false }, "subclasses": { "type": "array", "items": { "$ref": "#/$defs/ReferenceSubclass" } } }, "required": [ "_type", "name", "domain", "initialEvasion", "initialHitPoints", "initialInventory", "features", "hopeFeature", "subclasses" ], "additionalProperties": false, "$defs": { "ReferenceDomain": { "id": "ReferenceDomain", "title": "Reference to a Domain", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/domain" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "Thing": { "id": "Thing", "title": "Thing", "description": "A thing that can be added to a character's inventory", "type": "object", "properties": { "_type": { "default": "inventoryThing", "const": "inventoryThing" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false }, "Weapon": { "id": "Weapon", "title": "Weapon", "description": "A weapon that can be equipped by a character", "type": "object", "properties": { "_type": { "default": "inventoryWeapon", "const": "inventoryWeapon" }, "name": { "type": "string" }, "trait": { "$ref": "#/$defs/TraitName" }, "range": { "$ref": "#/$defs/Range" }, "damageDice": { "$ref": "#/$defs/DiceType" }, "damageType": { "$ref": "#/$defs/DamageType" }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] }, "burden": { "anyOf": [ { "const": "One-Handed" }, { "const": "Two-Handed" } ] } }, "required": [ "_type", "name", "trait", "range", "damageDice", "damageType", "features", "burden" ], "additionalProperties": false }, "TraitName": { "id": "TraitName", "title": "Trait Name", "description": "The name of a character trait", "examples": [ "Agility", "Strength", "Finesse", "Instinct", "Presence", "Knowledge" ], "anyOf": [ { "const": "Agility" }, { "const": "Strength" }, { "const": "Finesse" }, { "const": "Instinct" }, { "const": "Presence" }, { "const": "Knowledge" } ] }, "Range": { "id": "Range", "title": "Range", "description": "The range of a weapon or ability", "examples": [ "Melee", "Very Close", "Close", "Far", "Very Far" ], "anyOf": [ { "const": "Melee" }, { "const": "Very Close" }, { "const": "Close" }, { "const": "Far" }, { "const": "Very Far" } ] }, "DiceType": { "id": "DiceType", "title": "Dice Type", "description": "The type of dice to roll", "examples": [ "d4", "d6", "d8", "d10", "d12", "d20" ], "anyOf": [ { "const": "d4" }, { "const": "d6" }, { "const": "d8" }, { "const": "d10" }, { "const": "d12" }, { "const": "d20" } ] }, "DamageType": { "id": "DamageType", "title": "Damage Type", "description": "The type of damage a weapon or ability deals", "examples": [ "Physical", "Magical" ], "anyOf": [ { "const": "Physical" }, { "const": "Magical" } ] }, "Armor": { "id": "Armor", "title": "Armor", "description": "A set of armor that can be equipped by a character", "type": "object", "properties": { "_type": { "default": "inventoryArmor", "const": "inventoryArmor" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "baseThresholds": { "$ref": "#/$defs/DamageThresholds" }, "baseScore": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] } }, "required": [ "_type", "name", "description", "baseThresholds", "baseScore", "features" ], "additionalProperties": false }, "DamageThresholds": { "id": "DamageThresholds", "title": "Damage Thresholds", "description": "The damage thresholds of a character", "type": "object", "properties": { "_type": { "default": "damageThresholds", "const": "damageThresholds" }, "major": { "type": "integer", "minimum": 0, "maximum": 100 }, "severe": { "type": "integer", "minimum": 0, "maximum": 100 } }, "required": [ "_type", "major", "severe" ], "additionalProperties": false }, "ReferenceSubclass": { "id": "ReferenceSubclass", "title": "Reference to a Subclass", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/subclass" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } } } ``` *** ## Reference to a Class [Section titled “Reference to a Class”](#reference-to-a-class) ID: `ReferenceClass` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceClass", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/class" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` *** ## Subclass [Section titled “Subclass”](#subclass) ID: `Subclass` A subclass of a class ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Subclass", "type": "object", "properties": { "_type": { "const": "subclass" }, "name": { "type": "string" }, "description": { "type": "string" }, "spellTrait": { "default": null, "anyOf": [ { "$ref": "#/$defs/TraitName" }, { "type": "null" } ] }, "foundationFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } }, "specializationFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } }, "masteryFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } } }, "required": [ "_type", "name", "description", "spellTrait", "foundationFeatures", "specializationFeatures", "masteryFeatures" ], "additionalProperties": false, "$defs": { "TraitName": { "id": "TraitName", "title": "Trait Name", "description": "The name of a character trait", "examples": [ "Agility", "Strength", "Finesse", "Instinct", "Presence", "Knowledge" ], "anyOf": [ { "const": "Agility" }, { "const": "Strength" }, { "const": "Finesse" }, { "const": "Instinct" }, { "const": "Presence" }, { "const": "Knowledge" } ] }, "Feature": { "id": "Feature", "title": "Feature", "description": "A feature for a character to use", "type": "object", "properties": { "_type": { "const": "feature" }, "name": { "type": "string" }, "description": { "type": "string" }, "notes": { "default": null, "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] }, "modifiers": { "default": null, "type": "null" } }, "required": [ "_type", "name", "description", "notes", "modifiers" ], "additionalProperties": false } } } ``` *** ## Reference to a Subclass [Section titled “Reference to a Subclass”](#reference-to-a-subclass) ID: `ReferenceSubclass` ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "ReferenceSubclass", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/subclass" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } ``` # Campaign > A campaign is a collection of characters and rulesets. ## Campaign [Section titled “Campaign”](#campaign) ID: `Campaign` A campaign configuration and homebrew ruleset ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Campaign", "examples": [ { "_type": "campaign", "_meta": { "rulesetUrl": "https://dh-forge.com/schema.json", "rulesetVersion": "0.1.0", "dateCreated": "2025-05-30T12:00:00.000Z", "dateUpdated": "2025-05-30T12:00:00.000Z" }, "homebrew": { "item/armor": {}, "item/weapon": {}, "item/thing": {}, "role/class": {}, "role/subclass": {}, "heritage/ancestry": {}, "heritage/community": {} } } ], "type": "object", "properties": { "$schema": { "type": "string", "format": "uri" }, "_type": { "const": "campaign" }, "_meta": { "type": "object", "properties": { "rulesetVersion": { "$ref": "#/$defs/SchemaVersion" }, "dateCreated": { "type": "string", "format": "date-time", "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$" }, "dateUpdated": { "type": "string", "format": "date-time", "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$" }, "rulesetUrl": { "$ref": "#/$defs/RulesetUrl" } }, "required": [ "rulesetVersion", "dateCreated", "dateUpdated", "rulesetUrl" ], "additionalProperties": false }, "homebrew": { "type": "object", "properties": { "$schema": { "type": "string", "format": "uri" }, "item/armor": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Armor" } }, "item/thing": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Thing" } }, "item/weapon": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Weapon" } }, "role/class": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Class" } }, "role/subclass": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Subclass" } }, "heritage/ancestry": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Ancestry" } }, "heritage/community": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Community" } } }, "additionalProperties": false } }, "required": [ "_type", "_meta", "homebrew" ], "additionalProperties": false, "$defs": { "SchemaVersion": { "id": "SchemaVersion", "title": "Schema Version", "description": "A version number", "examples": [ "0.0.0" ], "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" }, "RulesetUrl": { "id": "RulesetUrl", "title": "Ruleset URL", "description": "The URL of the ruleset", "examples": [ "https://docs.dh-forge.com/schema/0.0.0/ruleset.json", "https://docs.dh-forge.com/schema/1.0.0/ruleset.json" ], "type": "string", "format": "uri" }, "Armor": { "id": "Armor", "title": "Armor", "description": "A set of armor that can be equipped by a character", "type": "object", "properties": { "_type": { "default": "inventoryArmor", "const": "inventoryArmor" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "baseThresholds": { "$ref": "#/$defs/DamageThresholds" }, "baseScore": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] } }, "required": [ "_type", "name", "description", "baseThresholds", "baseScore", "features" ], "additionalProperties": false }, "DamageThresholds": { "id": "DamageThresholds", "title": "Damage Thresholds", "description": "The damage thresholds of a character", "type": "object", "properties": { "_type": { "default": "damageThresholds", "const": "damageThresholds" }, "major": { "type": "integer", "minimum": 0, "maximum": 100 }, "severe": { "type": "integer", "minimum": 0, "maximum": 100 } }, "required": [ "_type", "major", "severe" ], "additionalProperties": false }, "Thing": { "id": "Thing", "title": "Thing", "description": "A thing that can be added to a character's inventory", "type": "object", "properties": { "_type": { "default": "inventoryThing", "const": "inventoryThing" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false }, "Weapon": { "id": "Weapon", "title": "Weapon", "description": "A weapon that can be equipped by a character", "type": "object", "properties": { "_type": { "default": "inventoryWeapon", "const": "inventoryWeapon" }, "name": { "type": "string" }, "trait": { "$ref": "#/$defs/TraitName" }, "range": { "$ref": "#/$defs/Range" }, "damageDice": { "$ref": "#/$defs/DiceType" }, "damageType": { "$ref": "#/$defs/DamageType" }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] }, "burden": { "anyOf": [ { "const": "One-Handed" }, { "const": "Two-Handed" } ] } }, "required": [ "_type", "name", "trait", "range", "damageDice", "damageType", "features", "burden" ], "additionalProperties": false }, "TraitName": { "id": "TraitName", "title": "Trait Name", "description": "The name of a character trait", "examples": [ "Agility", "Strength", "Finesse", "Instinct", "Presence", "Knowledge" ], "anyOf": [ { "const": "Agility" }, { "const": "Strength" }, { "const": "Finesse" }, { "const": "Instinct" }, { "const": "Presence" }, { "const": "Knowledge" } ] }, "Range": { "id": "Range", "title": "Range", "description": "The range of a weapon or ability", "examples": [ "Melee", "Very Close", "Close", "Far", "Very Far" ], "anyOf": [ { "const": "Melee" }, { "const": "Very Close" }, { "const": "Close" }, { "const": "Far" }, { "const": "Very Far" } ] }, "DiceType": { "id": "DiceType", "title": "Dice Type", "description": "The type of dice to roll", "examples": [ "d4", "d6", "d8", "d10", "d12", "d20" ], "anyOf": [ { "const": "d4" }, { "const": "d6" }, { "const": "d8" }, { "const": "d10" }, { "const": "d12" }, { "const": "d20" } ] }, "DamageType": { "id": "DamageType", "title": "Damage Type", "description": "The type of damage a weapon or ability deals", "examples": [ "Physical", "Magical" ], "anyOf": [ { "const": "Physical" }, { "const": "Magical" } ] }, "Class": { "id": "Class", "title": "Class", "description": "A class of a character", "type": "object", "properties": { "_type": { "const": "class" }, "name": { "type": "string" }, "domain": { "$ref": "#/$defs/ReferenceDomain" }, "initialEvasion": { "type": "integer", "minimum": 0, "maximum": 100 }, "initialHitPoints": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "initialInventory": { "type": "array", "items": { "anyOf": [ { "$ref": "#/$defs/Thing" }, { "$ref": "#/$defs/Weapon" }, { "$ref": "#/$defs/Armor" } ] } }, "features": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "hopeFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false }, "subclasses": { "type": "array", "items": { "$ref": "#/$defs/ReferenceSubclass" } } }, "required": [ "_type", "name", "domain", "initialEvasion", "initialHitPoints", "initialInventory", "features", "hopeFeature", "subclasses" ], "additionalProperties": false }, "ReferenceDomain": { "id": "ReferenceDomain", "title": "Reference to a Domain", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/domain" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceSubclass": { "id": "ReferenceSubclass", "title": "Reference to a Subclass", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/subclass" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "Subclass": { "id": "Subclass", "title": "Subclass", "description": "A subclass of a class", "type": "object", "properties": { "_type": { "const": "subclass" }, "name": { "type": "string" }, "description": { "type": "string" }, "spellTrait": { "default": null, "anyOf": [ { "$ref": "#/$defs/TraitName" }, { "type": "null" } ] }, "foundationFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } }, "specializationFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } }, "masteryFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } } }, "required": [ "_type", "name", "description", "spellTrait", "foundationFeatures", "specializationFeatures", "masteryFeatures" ], "additionalProperties": false }, "Feature": { "id": "Feature", "title": "Feature", "description": "A feature for a character to use", "type": "object", "properties": { "_type": { "const": "feature" }, "name": { "type": "string" }, "description": { "type": "string" }, "notes": { "default": null, "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] }, "modifiers": { "default": null, "type": "null" } }, "required": [ "_type", "name", "description", "notes", "modifiers" ], "additionalProperties": false }, "Ancestry": { "id": "Ancestry", "title": "Ancestry", "description": "The ancestry of a character", "type": "object", "properties": { "_type": { "const": "ancestry" }, "name": { "type": "string" }, "description": { "type": "string" }, "primaryFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false }, "secondaryFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "required": [ "_type", "name", "primaryFeature", "secondaryFeature" ], "additionalProperties": false }, "Community": { "id": "Community", "title": "Community", "description": "A community that shaped a characters backstory", "type": "object", "properties": { "_type": { "const": "community" }, "name": { "type": "string" }, "description": { "type": "string" }, "feature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "required": [ "_type", "name", "feature" ], "additionalProperties": false } } } ``` # Character > A character is a player or non-player character in a campaign. ## Character Sheet [Section titled “Character Sheet”](#character-sheet) ID: `Character` A character sheet ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Character", "examples": [ { "_type": "character", "_meta": { "campaignUrl": "https://dh-forge.com/schema.json", "rulesetVersion": "1.0.0", "dateCreated": "2025-05-30T12:00:00.000Z", "dateUpdated": "2025-05-30T12:00:00.000Z" }, "name": "Elara Meadowlight", "nameAlternate": "Ela", "pronouns": { "_type": "pronouns", "subject": "she", "object": "her", "possessive": "hers", "reflexive": "herself" }, "heritage": { "_type": "heritage", "community": { "_type": "reference", "_key": "heritage/community", "value": "seaborne" }, "ancestry": { "_type": "dualAncestry", "primary": { "_type": "reference", "_key": "heritage/ancestry", "value": "elf" }, "secondary": { "_type": "reference", "_key": "heritage/ancestry", "value": "faun" } } }, "roles": [ { "_type": "characterRole", "class": { "_type": "reference", "_key": "role/class", "value": "bard" }, "subclass": { "_type": "reference", "_key": "role/subclass", "value": "troubadour" } }, { "_type": "characterRole", "class": { "_type": "reference", "_key": "role/class", "value": "sorcerer" }, "subclass": { "_type": "reference", "_key": "role/subclass", "value": "pyromancer" } } ], "experiences": [ { "_type": "experience", "name": "Loremaster of the Ancient Texts", "description": "Years spent deciphering forgotten scrolls." }, { "_type": "experience", "name": "Survivor of the Whispering Woods", "description": null } ], "level": 5, "evasion": 14, "armorSlots": { "_type": "dynamicResource", "max": 5, "current": 3 }, "hitPoints": { "_type": "dynamicResource", "max": 8, "current": 7 }, "damageThresholds": { "_type": "damageThresholds", "major": 10, "severe": 15 }, "hope": { "_type": "dynamicResource", "max": 8, "current": 4 }, "stress": { "_type": "dynamicResource", "max": 5, "current": 1 }, "traits": { "Agility": { "_type": "trait", "value": 2, "locked": false }, "Strength": { "_type": "trait", "value": 0, "locked": false }, "Finesse": { "_type": "trait", "value": 3, "locked": true }, "Instinct": { "_type": "trait", "value": 1, "locked": false }, "Presence": { "_type": "trait", "value": 4, "locked": false }, "Knowledge": { "_type": "trait", "value": 1, "locked": true } }, "gold": { "_type": "gold", "handfuls": 15, "bags": 2, "chests": 0 }, "equippedArmor": { "primary": { "_type": "reference", "_key": "item/armor", "value": "enchanted_leather" }, "notes": "Glows faintly in moonlight" }, "equippedWeapon": { "primary": { "_type": "reference", "_key": "item/weapon", "value": "singing_shortbow" }, "secondary": null, "notes": null }, "inventory": [ { "_type": "reference", "_key": "item/weapon", "value": "silvered_dagger" }, { "_type": "reference", "_key": "item/thing", "value": "healing_potion_greater" }, { "_type": "inventoryThing", "name": "Bundle of Strange Herbs", "description": "Found near the Shadowfen, smells of sulfur and roses." }, { "_type": "inventoryThing", "name": "Tarnished Silver Locket", "description": "Opens, but is empty inside." } ] } ], "type": "object", "properties": { "$schema": { "type": "string", "format": "uri" }, "_type": { "const": "character" }, "_meta": { "type": "object", "properties": { "rulesetVersion": { "$ref": "#/$defs/SchemaVersion" }, "dateCreated": { "type": "string", "format": "date-time", "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$" }, "dateUpdated": { "type": "string", "format": "date-time", "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$" }, "campaignUrl": { "$ref": "#/$defs/CampaignUrl" } }, "required": [ "rulesetVersion", "dateCreated", "dateUpdated", "campaignUrl" ], "additionalProperties": false }, "name": { "type": "string" }, "nameAlternate": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "pronouns": { "$ref": "#/$defs/Pronouns" }, "heritage": { "$ref": "#/$defs/Heritage" }, "roles": { "type": "array", "items": { "$ref": "#/$defs/CharacterRole" } }, "experiences": { "type": "array", "items": { "$ref": "#/$defs/Experience" } }, "level": { "$ref": "#/$defs/Level" }, "evasion": { "type": "integer", "minimum": 0, "maximum": 100 }, "armorSlots": { "$ref": "#/$defs/DynamicResource" }, "hitPoints": { "$ref": "#/$defs/DynamicResource" }, "damageThresholds": { "$ref": "#/$defs/DamageThresholds" }, "hope": { "$ref": "#/$defs/DynamicResource" }, "stress": { "$ref": "#/$defs/DynamicResource" }, "traits": { "type": "object", "propertyNames": { "$ref": "#/$defs/TraitName" }, "additionalProperties": { "$ref": "#/$defs/Trait" } }, "gold": { "$ref": "#/$defs/Gold" }, "equippedArmor": { "type": "object", "properties": { "primary": { "anyOf": [ { "$ref": "#/$defs/ReferenceArmor" }, { "type": "null" } ] }, "notes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "primary", "notes" ], "additionalProperties": false }, "equippedWeapon": { "type": "object", "properties": { "primary": { "anyOf": [ { "$ref": "#/$defs/ReferenceWeapon" }, { "type": "null" } ] }, "secondary": { "anyOf": [ { "$ref": "#/$defs/ReferenceWeapon" }, { "type": "null" } ] }, "notes": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "primary", "secondary", "notes" ], "additionalProperties": false }, "inventory": { "type": "array", "items": { "anyOf": [ { "$ref": "#/$defs/ReferenceArmor" }, { "$ref": "#/$defs/ReferenceWeapon" }, { "$ref": "#/$defs/ReferenceThing" }, { "$ref": "#/$defs/Thing" } ] } } }, "required": [ "_type", "_meta", "name", "nameAlternate", "pronouns", "heritage", "roles", "experiences", "level", "evasion", "armorSlots", "hitPoints", "damageThresholds", "hope", "stress", "traits", "gold", "equippedArmor", "equippedWeapon", "inventory" ], "additionalProperties": false, "$defs": { "SchemaVersion": { "id": "SchemaVersion", "title": "Schema Version", "description": "A version number", "examples": [ "0.0.0" ], "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" }, "CampaignUrl": { "id": "CampaignUrl", "title": "Campaign URL", "description": "The URL of the campaign", "examples": [ "https://docs.dh-forge.com/schema/0.0.0/campaign.json", "https://docs.dh-forge.com/schema/1.0.0/campaign.json" ], "type": "string", "format": "uri" }, "Pronouns": { "id": "Pronouns", "title": "Pronouns", "description": "The pronouns of a character", "type": "object", "properties": { "_type": { "const": "pronouns" }, "subject": { "$ref": "#/$defs/PronounsSubject" }, "object": { "$ref": "#/$defs/PronounsObject" }, "possessive": { "$ref": "#/$defs/PronounsPossessive" }, "reflexive": { "$ref": "#/$defs/PronounsReflexive" } }, "required": [ "_type", "subject", "object", "possessive", "reflexive" ], "additionalProperties": false }, "PronounsSubject": { "id": "PronounsSubject", "title": "Subject Pronoun", "description": "A pronoun form used when it performs the verb’s action.", "examples": [ "she", "he", "they" ], "type": "string" }, "PronounsObject": { "id": "PronounsObject", "title": "Object Pronoun", "description": "A pronoun form used when it receives the action or follows a preposition.", "examples": [ "her", "him", "them" ], "type": "string" }, "PronounsPossessive": { "id": "PronounsPossessive", "title": "Possessive Pronoun", "description": "A pronoun form that replaces a noun to show ownership or relationship.", "examples": [ "hers", "his", "theirs" ], "type": "string" }, "PronounsReflexive": { "id": "PronounsReflexive", "title": "Reflexive Pronoun", "description": "A pronoun form ending in “-self” or “-selves” that refers back to the clause’s subject.", "examples": [ "herself", "himself", "themselves" ], "type": "string" }, "Heritage": { "id": "Heritage", "title": "Character Heritage", "description": "A character's heritage", "type": "object", "properties": { "_type": { "default": "heritage", "const": "heritage" }, "community": { "$ref": "#/$defs/ReferenceCommunity" }, "ancestry": { "$ref": "#/$defs/CharacterAncestry" } }, "required": [ "_type", "community", "ancestry" ], "additionalProperties": false }, "ReferenceCommunity": { "id": "ReferenceCommunity", "title": "Reference to a Community", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "heritage/community" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "CharacterAncestry": { "id": "CharacterAncestry", "title": "Character Ancestry", "description": "A character's ancestry", "anyOf": [ { "type": "object", "properties": { "_type": { "default": "singleAncestry", "const": "singleAncestry" }, "ancestry": { "$ref": "#/$defs/ReferenceAncestry" } }, "required": [ "_type", "ancestry" ], "additionalProperties": false }, { "type": "object", "properties": { "_type": { "default": "dualAncestry", "const": "dualAncestry" }, "primary": { "$ref": "#/$defs/ReferenceAncestry" }, "secondary": { "$ref": "#/$defs/ReferenceAncestry" } }, "required": [ "_type", "primary", "secondary" ], "additionalProperties": false } ] }, "ReferenceAncestry": { "id": "ReferenceAncestry", "title": "Reference to an Ancestry", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "heritage/ancestry" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "CharacterRole": { "id": "CharacterRole", "title": "Character Role", "description": "Ruleset references to the class and subclass of a character", "type": "object", "properties": { "_type": { "default": "characterRole", "const": "characterRole" }, "class": { "$ref": "#/$defs/ReferenceClass" }, "subclass": { "$ref": "#/$defs/ReferenceSubclass" } }, "required": [ "_type", "class", "subclass" ], "additionalProperties": false }, "ReferenceClass": { "id": "ReferenceClass", "title": "Reference to a Class", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/class" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceSubclass": { "id": "ReferenceSubclass", "title": "Reference to a Subclass", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/subclass" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "Experience": { "id": "Experience", "title": "Character Experience", "description": "Experience represents a character specialization.", "type": "object", "properties": { "_type": { "default": "experience", "const": "experience" }, "name": { "type": "string" }, "description": { "default": null, "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false }, "Level": { "id": "Level", "title": "Level", "description": "The level of the character", "examples": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], "type": "integer", "minimum": 1, "maximum": 10 }, "DynamicResource": { "id": "DynamicResource", "title": "Dynamic Resource", "description": "A dynamic resource used by a character", "type": "object", "properties": { "_type": { "const": "dynamicResource" }, "max": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "current": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "_type", "max", "current" ], "additionalProperties": false }, "DamageThresholds": { "id": "DamageThresholds", "title": "Damage Thresholds", "description": "The damage thresholds of a character", "type": "object", "properties": { "_type": { "default": "damageThresholds", "const": "damageThresholds" }, "major": { "type": "integer", "minimum": 0, "maximum": 100 }, "severe": { "type": "integer", "minimum": 0, "maximum": 100 } }, "required": [ "_type", "major", "severe" ], "additionalProperties": false }, "TraitName": { "id": "TraitName", "title": "Trait Name", "description": "The name of a character trait", "examples": [ "Agility", "Strength", "Finesse", "Instinct", "Presence", "Knowledge" ], "anyOf": [ { "const": "Agility" }, { "const": "Strength" }, { "const": "Finesse" }, { "const": "Instinct" }, { "const": "Presence" }, { "const": "Knowledge" } ] }, "Trait": { "id": "Trait", "title": "Trait", "description": "The details of a character trait", "examples": [ { "_type": "trait", "value": 2, "locked": true }, { "_type": "trait", "value": -1, "locked": false } ], "type": "object", "properties": { "_type": { "default": "trait", "const": "trait" }, "value": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "locked": { "default": false, "type": "boolean" } }, "required": [ "_type", "value", "locked" ], "additionalProperties": false }, "Gold": { "id": "Gold", "title": "Gold", "description": "The amount of gold held by a character", "type": "object", "properties": { "_type": { "const": "gold" }, "handfuls": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "bags": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "chests": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "required": [ "_type", "handfuls", "bags", "chests" ], "additionalProperties": false }, "ReferenceArmor": { "id": "ReferenceArmor", "title": "Reference to a piece of Armor", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/armor" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceWeapon": { "id": "ReferenceWeapon", "title": "Reference to a Weapon", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/weapon" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceThing": { "id": "ReferenceThing", "title": "Reference to a Thing", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/thing" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "Thing": { "id": "Thing", "title": "Thing", "description": "A thing that can be added to a character's inventory", "type": "object", "properties": { "_type": { "default": "inventoryThing", "const": "inventoryThing" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false } } } ``` # Common > Common schemas are used in multiple models. ## Character Ancestry [Section titled “Character Ancestry”](#character-ancestry) ID: `CharacterAncestry` A character’s ancestry ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "CharacterAncestry", "anyOf": [ { "type": "object", "properties": { "_type": { "default": "singleAncestry", "const": "singleAncestry" }, "ancestry": { "$ref": "#/$defs/ReferenceAncestry" } }, "required": [ "_type", "ancestry" ], "additionalProperties": false }, { "type": "object", "properties": { "_type": { "default": "dualAncestry", "const": "dualAncestry" }, "primary": { "$ref": "#/$defs/ReferenceAncestry" }, "secondary": { "$ref": "#/$defs/ReferenceAncestry" } }, "required": [ "_type", "primary", "secondary" ], "additionalProperties": false } ], "$defs": { "ReferenceAncestry": { "id": "ReferenceAncestry", "title": "Reference to an Ancestry", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "heritage/ancestry" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } } } ``` *** ## Character Role [Section titled “Character Role”](#character-role) ID: `CharacterRole` Ruleset references to the class and subclass of a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "CharacterRole", "type": "object", "properties": { "_type": { "default": "characterRole", "const": "characterRole" }, "class": { "$ref": "#/$defs/ReferenceClass" }, "subclass": { "$ref": "#/$defs/ReferenceSubclass" } }, "required": [ "_type", "class", "subclass" ], "additionalProperties": false, "$defs": { "ReferenceClass": { "id": "ReferenceClass", "title": "Reference to a Class", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/class" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceSubclass": { "id": "ReferenceSubclass", "title": "Reference to a Subclass", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/subclass" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } } } ``` *** ## Damage Thresholds [Section titled “Damage Thresholds”](#damage-thresholds) ID: `DamageThresholds` The damage thresholds of a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "DamageThresholds", "type": "object", "properties": { "_type": { "default": "damageThresholds", "const": "damageThresholds" }, "major": { "type": "integer", "minimum": 0, "maximum": 100 }, "severe": { "type": "integer", "minimum": 0, "maximum": 100 } }, "required": [ "_type", "major", "severe" ], "additionalProperties": false } ``` *** ## Damage Type [Section titled “Damage Type”](#damage-type) ID: `DamageType` The type of damage a weapon or ability deals ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "DamageType", "examples": [ "Physical", "Magical" ], "anyOf": [ { "const": "Physical" }, { "const": "Magical" } ] } ``` *** ## Dice Type [Section titled “Dice Type”](#dice-type) ID: `DiceType` The type of dice to roll ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "DiceType", "examples": [ "d4", "d6", "d8", "d10", "d12", "d20" ], "anyOf": [ { "const": "d4" }, { "const": "d6" }, { "const": "d8" }, { "const": "d10" }, { "const": "d12" }, { "const": "d20" } ] } ``` *** ## Dynamic Resource [Section titled “Dynamic Resource”](#dynamic-resource) ID: `DynamicResource` A dynamic resource used by a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "DynamicResource", "type": "object", "properties": { "_type": { "const": "dynamicResource" }, "max": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "current": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "_type", "max", "current" ], "additionalProperties": false } ``` *** ## Character Experience [Section titled “Character Experience”](#character-experience) ID: `Experience` Experience represents a character specialization. ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Experience", "type": "object", "properties": { "_type": { "default": "experience", "const": "experience" }, "name": { "type": "string" }, "description": { "default": null, "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false } ``` *** ## Gold [Section titled “Gold”](#gold) ID: `Gold` The amount of gold held by a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Gold", "type": "object", "properties": { "_type": { "const": "gold" }, "handfuls": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "bags": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "chests": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 } }, "required": [ "_type", "handfuls", "bags", "chests" ], "additionalProperties": false } ``` *** ## Character Heritage [Section titled “Character Heritage”](#character-heritage) ID: `Heritage` A character’s heritage ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Heritage", "type": "object", "properties": { "_type": { "default": "heritage", "const": "heritage" }, "community": { "$ref": "#/$defs/ReferenceCommunity" }, "ancestry": { "$ref": "#/$defs/CharacterAncestry" } }, "required": [ "_type", "community", "ancestry" ], "additionalProperties": false, "$defs": { "ReferenceCommunity": { "id": "ReferenceCommunity", "title": "Reference to a Community", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "heritage/community" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "CharacterAncestry": { "id": "CharacterAncestry", "title": "Character Ancestry", "description": "A character's ancestry", "anyOf": [ { "type": "object", "properties": { "_type": { "default": "singleAncestry", "const": "singleAncestry" }, "ancestry": { "$ref": "#/$defs/ReferenceAncestry" } }, "required": [ "_type", "ancestry" ], "additionalProperties": false }, { "type": "object", "properties": { "_type": { "default": "dualAncestry", "const": "dualAncestry" }, "primary": { "$ref": "#/$defs/ReferenceAncestry" }, "secondary": { "$ref": "#/$defs/ReferenceAncestry" } }, "required": [ "_type", "primary", "secondary" ], "additionalProperties": false } ] }, "ReferenceAncestry": { "id": "ReferenceAncestry", "title": "Reference to an Ancestry", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "heritage/ancestry" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false } } } ``` *** ## Inventory Item [Section titled “Inventory Item”](#inventory-item) ID: `InventoryItem` An item in a character’s inventory ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "InventoryItem", "anyOf": [ { "$ref": "#/$defs/ReferenceArmor" }, { "$ref": "#/$defs/ReferenceWeapon" }, { "$ref": "#/$defs/ReferenceThing" }, { "$ref": "#/$defs/Thing" } ], "$defs": { "ReferenceArmor": { "id": "ReferenceArmor", "title": "Reference to a piece of Armor", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/armor" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceWeapon": { "id": "ReferenceWeapon", "title": "Reference to a Weapon", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/weapon" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceThing": { "id": "ReferenceThing", "title": "Reference to a Thing", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "item/thing" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "Thing": { "id": "Thing", "title": "Thing", "description": "A thing that can be added to a character's inventory", "type": "object", "properties": { "_type": { "default": "inventoryThing", "const": "inventoryThing" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false } } } ``` *** ## Pronouns [Section titled “Pronouns”](#pronouns) ID: `Pronouns` The pronouns of a character ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Pronouns", "type": "object", "properties": { "_type": { "const": "pronouns" }, "subject": { "$ref": "#/$defs/PronounsSubject" }, "object": { "$ref": "#/$defs/PronounsObject" }, "possessive": { "$ref": "#/$defs/PronounsPossessive" }, "reflexive": { "$ref": "#/$defs/PronounsReflexive" } }, "required": [ "_type", "subject", "object", "possessive", "reflexive" ], "additionalProperties": false, "$defs": { "PronounsSubject": { "id": "PronounsSubject", "title": "Subject Pronoun", "description": "A pronoun form used when it performs the verb’s action.", "examples": [ "she", "he", "they" ], "type": "string" }, "PronounsObject": { "id": "PronounsObject", "title": "Object Pronoun", "description": "A pronoun form used when it receives the action or follows a preposition.", "examples": [ "her", "him", "them" ], "type": "string" }, "PronounsPossessive": { "id": "PronounsPossessive", "title": "Possessive Pronoun", "description": "A pronoun form that replaces a noun to show ownership or relationship.", "examples": [ "hers", "his", "theirs" ], "type": "string" }, "PronounsReflexive": { "id": "PronounsReflexive", "title": "Reflexive Pronoun", "description": "A pronoun form ending in “-self” or “-selves” that refers back to the clause’s subject.", "examples": [ "herself", "himself", "themselves" ], "type": "string" } } } ``` *** ## Range [Section titled “Range”](#range) ID: `Range` The range of a weapon or ability ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Range", "examples": [ "Melee", "Very Close", "Close", "Far", "Very Far" ], "anyOf": [ { "const": "Melee" }, { "const": "Very Close" }, { "const": "Close" }, { "const": "Far" }, { "const": "Very Far" } ] } ``` *** ## Trait [Section titled “Trait”](#trait) ID: `Trait` The details of a character trait ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Trait", "examples": [ { "_type": "trait", "value": 2, "locked": true }, { "_type": "trait", "value": -1, "locked": false } ], "type": "object", "properties": { "_type": { "default": "trait", "const": "trait" }, "value": { "default": 0, "type": "integer", "minimum": -9007199254740991, "maximum": 9007199254740991 }, "locked": { "default": false, "type": "boolean" } }, "required": [ "_type", "value", "locked" ], "additionalProperties": false } ``` *** ## Trait Name [Section titled “Trait Name”](#trait-name) ID: `TraitName` The name of a character trait ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "TraitName", "examples": [ "Agility", "Strength", "Finesse", "Instinct", "Presence", "Knowledge" ], "anyOf": [ { "const": "Agility" }, { "const": "Strength" }, { "const": "Finesse" }, { "const": "Instinct" }, { "const": "Presence" }, { "const": "Knowledge" } ] } ``` # Ruleset > A ruleset is a collection of rules for a campaign. ## Ruleset [Section titled “Ruleset”](#ruleset) ID: `Ruleset` A ruleset of all the things that can be used in the game ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "id": "Ruleset", "examples": [ { "_type": "ruleset", "_meta": { "rulesetUrl": "https://dh-forge.com/schema.json", "rulesetVersion": "0.2.0", "minVersion": "0.0.1", "dateCreated": "2025-05-30T12:00:00.000Z", "dateUpdated": "2025-05-30T12:00:00.000Z" }, "item/armor": {}, "item/weapon": {}, "item/thing": {}, "role/class": {}, "role/subclass": {}, "heritage/ancestry": {}, "heritage/community": {} } ], "type": "object", "properties": { "$schema": { "type": "string", "format": "uri" }, "_type": { "const": "ruleset" }, "_meta": { "type": "object", "properties": { "rulesetVersion": { "$ref": "#/$defs/SchemaVersion" }, "dateCreated": { "type": "string", "format": "date-time", "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$" }, "dateUpdated": { "type": "string", "format": "date-time", "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$" }, "rulesetUrl": { "$ref": "#/$defs/RulesetUrl" }, "minVersion": { "$ref": "#/$defs/SchemaVersion" } }, "required": [ "rulesetVersion", "dateCreated", "dateUpdated", "rulesetUrl", "minVersion" ], "additionalProperties": false }, "item/armor": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Armor" } }, "item/thing": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Thing" } }, "item/weapon": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Weapon" } }, "role/class": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Class" } }, "role/subclass": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Subclass" } }, "heritage/ancestry": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Ancestry" } }, "heritage/community": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "$ref": "#/$defs/Community" } } }, "required": [ "_type", "_meta", "item/armor", "item/thing", "item/weapon", "role/class", "role/subclass", "heritage/ancestry", "heritage/community" ], "additionalProperties": false, "$defs": { "SchemaVersion": { "id": "SchemaVersion", "title": "Schema Version", "description": "A version number", "examples": [ "0.0.0" ], "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" }, "RulesetUrl": { "id": "RulesetUrl", "title": "Ruleset URL", "description": "The URL of the ruleset", "examples": [ "https://docs.dh-forge.com/schema/0.0.0/ruleset.json", "https://docs.dh-forge.com/schema/1.0.0/ruleset.json" ], "type": "string", "format": "uri" }, "Armor": { "id": "Armor", "title": "Armor", "description": "A set of armor that can be equipped by a character", "type": "object", "properties": { "_type": { "default": "inventoryArmor", "const": "inventoryArmor" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "baseThresholds": { "$ref": "#/$defs/DamageThresholds" }, "baseScore": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] } }, "required": [ "_type", "name", "description", "baseThresholds", "baseScore", "features" ], "additionalProperties": false }, "DamageThresholds": { "id": "DamageThresholds", "title": "Damage Thresholds", "description": "The damage thresholds of a character", "type": "object", "properties": { "_type": { "default": "damageThresholds", "const": "damageThresholds" }, "major": { "type": "integer", "minimum": 0, "maximum": 100 }, "severe": { "type": "integer", "minimum": 0, "maximum": 100 } }, "required": [ "_type", "major", "severe" ], "additionalProperties": false }, "Thing": { "id": "Thing", "title": "Thing", "description": "A thing that can be added to a character's inventory", "type": "object", "properties": { "_type": { "default": "inventoryThing", "const": "inventoryThing" }, "name": { "type": "string" }, "description": { "anyOf": [ { "type": "string" }, { "type": "null" } ] } }, "required": [ "_type", "name", "description" ], "additionalProperties": false }, "Weapon": { "id": "Weapon", "title": "Weapon", "description": "A weapon that can be equipped by a character", "type": "object", "properties": { "_type": { "default": "inventoryWeapon", "const": "inventoryWeapon" }, "name": { "type": "string" }, "trait": { "$ref": "#/$defs/TraitName" }, "range": { "$ref": "#/$defs/Range" }, "damageDice": { "$ref": "#/$defs/DiceType" }, "damageType": { "$ref": "#/$defs/DamageType" }, "features": { "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] }, "burden": { "anyOf": [ { "const": "One-Handed" }, { "const": "Two-Handed" } ] } }, "required": [ "_type", "name", "trait", "range", "damageDice", "damageType", "features", "burden" ], "additionalProperties": false }, "TraitName": { "id": "TraitName", "title": "Trait Name", "description": "The name of a character trait", "examples": [ "Agility", "Strength", "Finesse", "Instinct", "Presence", "Knowledge" ], "anyOf": [ { "const": "Agility" }, { "const": "Strength" }, { "const": "Finesse" }, { "const": "Instinct" }, { "const": "Presence" }, { "const": "Knowledge" } ] }, "Range": { "id": "Range", "title": "Range", "description": "The range of a weapon or ability", "examples": [ "Melee", "Very Close", "Close", "Far", "Very Far" ], "anyOf": [ { "const": "Melee" }, { "const": "Very Close" }, { "const": "Close" }, { "const": "Far" }, { "const": "Very Far" } ] }, "DiceType": { "id": "DiceType", "title": "Dice Type", "description": "The type of dice to roll", "examples": [ "d4", "d6", "d8", "d10", "d12", "d20" ], "anyOf": [ { "const": "d4" }, { "const": "d6" }, { "const": "d8" }, { "const": "d10" }, { "const": "d12" }, { "const": "d20" } ] }, "DamageType": { "id": "DamageType", "title": "Damage Type", "description": "The type of damage a weapon or ability deals", "examples": [ "Physical", "Magical" ], "anyOf": [ { "const": "Physical" }, { "const": "Magical" } ] }, "Class": { "id": "Class", "title": "Class", "description": "A class of a character", "type": "object", "properties": { "_type": { "const": "class" }, "name": { "type": "string" }, "domain": { "$ref": "#/$defs/ReferenceDomain" }, "initialEvasion": { "type": "integer", "minimum": 0, "maximum": 100 }, "initialHitPoints": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "initialInventory": { "type": "array", "items": { "anyOf": [ { "$ref": "#/$defs/Thing" }, { "$ref": "#/$defs/Weapon" }, { "$ref": "#/$defs/Armor" } ] } }, "features": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "hopeFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false }, "subclasses": { "type": "array", "items": { "$ref": "#/$defs/ReferenceSubclass" } } }, "required": [ "_type", "name", "domain", "initialEvasion", "initialHitPoints", "initialInventory", "features", "hopeFeature", "subclasses" ], "additionalProperties": false }, "ReferenceDomain": { "id": "ReferenceDomain", "title": "Reference to a Domain", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/domain" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "ReferenceSubclass": { "id": "ReferenceSubclass", "title": "Reference to a Subclass", "type": "object", "properties": { "_type": { "const": "reference" }, "_key": { "const": "role/subclass" }, "value": { "type": "string" } }, "required": [ "_type", "_key", "value" ], "additionalProperties": false }, "Subclass": { "id": "Subclass", "title": "Subclass", "description": "A subclass of a class", "type": "object", "properties": { "_type": { "const": "subclass" }, "name": { "type": "string" }, "description": { "type": "string" }, "spellTrait": { "default": null, "anyOf": [ { "$ref": "#/$defs/TraitName" }, { "type": "null" } ] }, "foundationFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } }, "specializationFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } }, "masteryFeatures": { "type": "array", "items": { "$ref": "#/$defs/Feature" } } }, "required": [ "_type", "name", "description", "spellTrait", "foundationFeatures", "specializationFeatures", "masteryFeatures" ], "additionalProperties": false }, "Feature": { "id": "Feature", "title": "Feature", "description": "A feature for a character to use", "type": "object", "properties": { "_type": { "const": "feature" }, "name": { "type": "string" }, "description": { "type": "string" }, "notes": { "default": null, "anyOf": [ { "type": "array", "items": { "type": "string" } }, { "type": "null" } ] }, "modifiers": { "default": null, "type": "null" } }, "required": [ "_type", "name", "description", "notes", "modifiers" ], "additionalProperties": false }, "Ancestry": { "id": "Ancestry", "title": "Ancestry", "description": "The ancestry of a character", "type": "object", "properties": { "_type": { "const": "ancestry" }, "name": { "type": "string" }, "description": { "type": "string" }, "primaryFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false }, "secondaryFeature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "required": [ "_type", "name", "primaryFeature", "secondaryFeature" ], "additionalProperties": false }, "Community": { "id": "Community", "title": "Community", "description": "A community that shaped a characters backstory", "type": "object", "properties": { "_type": { "const": "community" }, "name": { "type": "string" }, "description": { "type": "string" }, "feature": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": [ "name", "description" ], "additionalProperties": false } }, "required": [ "_type", "name", "feature" ], "additionalProperties": false } } } ``` # DHF Data Specification Work in Progress # DHF Dereference Specification Work in Progress # DHF Typescript API Reference ## The Challenge: [Section titled “The Challenge:”](#the-challenge) You still need to *use* these schemas effectively in your project. This means figuring out how to validate data against the schemas, manage any references or connections between different parts of the schemas (a process often called ‘resolving’), and ensure any new game data you create is correctly structured. Setting all this up is often boilerplate work that can slow you down before you even get to building the unique parts of your tool. ## Why Solve It? [Section titled “Why Solve It?”](#why-solve-it) We want you to hit the ground running when you’re building Daggerheart™ tools with TypeScript or JavaScript! By providing ready-made solutions for common schema-related tasks, we can save you time, reduce initial setup headaches, and let you focus your energy on crafting the unique features and user experiences that will make your application stand out. ## Our Solution: [Section titled “Our Solution:”](#our-solution) To give TypeScript and JavaScript developers this boost, DH-F offers dedicated [TypeScript](https://www.typescriptlang.org/) packages that go well beyond just providing the raw schema files. Think of them as a specialized toolkit for working with DH-F data. Inside, you’ll find: * **Pre-generated TypeScript Types:** Jump-start your project with strong typing and autocompletion in your editor. No need to manually define interfaces to match the schemas – we’ve handled that, helping you catch errors early and understand data structures intuitively. * **Validation Tools:** Easily check if character data, homebrew content, or any other game information conforms to the DH-F schemas directly within your JavaScript or TypeScript code. This helps ensure data integrity throughout your application. * **Schema Resolution Utilities:** If you’re working with more complex data that references other parts of the Daggerheart™ schemas (using `$ref` for example), these tools will help manage and correctly interpret those relationships. * **Data Creation Helpers:** Functions and utilities to simplify the creation of new, schema-compliant data instances (like new characters, items, or other game elements). This makes it easier to build data that you know will be valid. * **Other Handy Utilities:** A collection of smaller tools and functions to streamline common tasks when working with DH-F data. Essentially, if you’re building with TypeScript or JavaScript, these packages are designed to handle a lot of the foundational schema plumbing for you. This means a faster, more robust start, allowing you to focus on building something amazing for the Daggerheart™ community. # DH-Forge Docs > DH-F is an open-source system for defining, structuring, and sharing character and game data for the Daggerheart™ TTRPG. It aims to create a common language for digital tools, allowing seamless interoperability. DH-Forge (DH-F) is an open-source toolkit for wrangling character and game data for the Daggerheart™ TTRPG. You can think of it as a common language that helps all sorts of digital tools—like character builders, virtual tabletops, and more—speak to each other seamlessly. Ultimately, this means your Daggerheart character information can move between different apps without details getting lost or mixed up, so you spend less time re-entering data and more time playing. Disclaimer This project is an **unofficial** fan creation and is *not* affiliated with, or endorsed by, Darrington Press LLC. It uses names and concepts related to [Daggerheart™](%22https://www.daggerheart.com/%22) under fair use principles in line with their [community gaming license](https://darringtonpress.com/license/). ## Our Mission [Section titled “Our Mission”](#our-mission) TTRPG communities are bursting with creativity, not just in the thrilling tales we tell, but also in the tools we build to bring those stories to life. Imagine a Daggerheart experience where all your tools work seamlessly together - your favorite character sheet app talking directly to your VTT, and sharing your homebrew creations digitally feeling like a natural extension of your game, rather than a side quest. Currently, disconnected tools often form “data islands” that can slow down the fun. DH-Forge is here to bridge those islands and empower the Daggerheart™ community by offering: Interoperability, Homebrew Support, Openness, and Flexibility. ### Interoperable: [Section titled “Interoperable:”](#interoperable) A shared way of understanding game data. This means you can (eventually!) move your character from a character builder app straight into your virtual tabletop session, smooth as silk. ### Homebrew-able: [Section titled “Homebrew-able:”](#homebrew-able) A solid but flexible system designed to welcome your unique homebrew classes, legendary items, and terrifying monsters right alongside the core game elements. ### Open-Source: [Section titled “Open-Source:”](#open-source) A completely free and permissive (that’s MIT licensed, for the curious) standard. Anyone can use it, build with it, and share their creations, whether it’s a passion project or a commercial one. ### Flexible [Section titled “Flexible”](#flexible) A system that expertly handles all the core game data you’d expect, but is also designed to let you add your own extensions and features. ## Capabilities [Section titled “Capabilities”](#capabilities) So what Adventures Can This Unlock? When our tools speak the same language using DH-F, developers like you can craft a richer, more connected universe of Daggerheart™ experiences, like: * **Character Generators:** Instantly roll up new Daggerheart characters. * **Living Character Sheets:** Web or mobile apps that can beautifully display any character built with DH-F. * **Streamer-Friendly Overlays:** Automatically flash player stats on screen during your live games. * **Virtual Tabletops (VTTs):** Effortlessly import and export characters, beasties, and game elements. * **Digital Companions for Live Play:** Slick tablet apps for quick rule lookups and tracking initiative at the table. * **AI Story Weavers & Game Masters:** Feed structured data to AI tools to help generate new adventures or even assist the GM. * **And a Whole Realm More…:** Seriously, with a common way to handle data, the possibilities are extensive! ## Ready to Forge? [Section titled “Ready to Forge?”](#ready-to-forge) We invite you to **explore the DH-F data models** or dive into **getting started with the JSON Schemas**! # DH-Forge Concepts > Tool compatibility and homebrew support, powered by JSON Schemas, solves key digital challenges for the community. This framework is built upon two core conceptual pillars: fostering [Compatibility](https://www.google.com/search?q=%23compatibility) across applications and enabling extensive [Homebrew](https://www.google.com/search?q=%23homebrew) content integration. ## Compatibility [Section titled “Compatibility”](#compatibility) ### The Challenge: [Section titled “The Challenge:”](#the-challenge) Digital tools for games often don’t share data, and without common data structures, integrations are a major hurdle. This leads to data silos and forces users into manual data entry. With Daggerheart™ being new, we have the chance to build in this interoperability from the start. ### Why Solve It? [Section titled “Why Solve It?”](#why-solve-it) We envision a Daggerheart™ ecosystem where data moves freely between tools. **Imagine creating a character in your preferred builder and having it instantly usable in a VTT**, or seamlessly sharing your custom monster library with a friend, regardless of the specific apps you each use. Solving this “data silo” problem means less repetitive data entry for users, more powerful and interconnected tools for players, and a more vibrant development community. ### Our Solution: [Section titled “Our Solution:”](#our-solution) Since most developers are already familiar with JSON as a lightweight data-interchange format, we’ve chosen [JSON Schemas](https://json-schema.org/) as the backbone for DH-F. what are JSON Schemas? If JSON is how you *write down* your data (like character stats), **JSON Schema defines the *rules* for that data.** Think of it as a blueprint: it specifies the expected structure—field names (e.g., `name`, `health`), their data types (string, number), what’s required, and how data relates. For those familiar with strongly-typed languages, it’s a bit like adding types to your JSON. Ultimately, JSON Schemas provide a clear, machine-readable specification for valid Daggerheart™ data. ### Why is this a great foundation? [Section titled “Why is this a great foundation?”](#why-is-this-a-great-foundation) Because JSON is already universally understood, and JSON Schema builds on that by providing a standardized way to validate and describe JSON structures. This means developers working with almost any programming language can easily leverage these schemas, as there’s widespread tooling support. For example: * Node.js (with libraries like [ajv](https://github.com/ajv-validator/ajv)) * Python (check out [jsonschema](https://github.com/python-jsonschema/jsonschema)) * PHP (using tools like [json-schema](https://github.com/justinrainbow/json-schema)) * Java (powered by [json-schema-validator](https://github.com/networknt/json-schema-validator)) * .NET (with [Newtonsoft.Json.Schema](https://github.com/JamesNK/Newtonsoft.Json.Schema), for example) * Go (utilizing [gojsonschema](https://github.com/invopop/gojsonschema)) * Ruby (thanks to [json-schema](https://github.com/ruby-json-schema/json-schema)) * Rust (with crates like [jsonschema](https://github.com/Stranger6667/jsonschema)) * …and many others. By establishing this common, schema-defined structure for Daggerheart™ data, developers can build their tools with greater confidence, knowing they’ll be able to communicate effectively with other parts of the ecosystem. DH-F offers this shared foundation to foster a rich and interconnected world of player-focused applications. ## Homebrew [Section titled “Homebrew”](#homebrew) ### The Challenge: [Section titled “The Challenge:”](#the-challenge-1) Daggerheart™ is all about making the game your own! But how do you make sure your custom-brewed Ancestries, Communities, or that new monster you designed can be understood by digital tools alongside the core ruleset? ### Why Solve It? [Section titled “Why Solve It?”](#why-solve-it-1) Homebrew is the lifeblood of many campaigns. Making it easy to integrate custom content digitally means more creativity, more sharing, and tools that truly reflect *your* version of Daggerheart™. ### Our Solution: [Section titled “Our Solution:”](#our-solution-1) While rules and structure are what make shared systems like DH-F useful, we’ve designed it with a careful balance. DH-F isn’t just about the core [Daggerheart™](https://www.daggerheart.com/) game elements; it’s built with the flexibility to robustly incorporate **your homebrew content**. This means your custom classes, spells, items, and more can be defined in a way that other DH-F compatible tools can understand, opening up rich, interoperable experiences for character builders, VTTs, streaming overlays, and all sorts of community-made apps. # Docs for LLMs > Discover how DH-Forge structures its documentation for Large Language Models (LLMs) using the llms.txt convention. This page details the specialized text files provided to improve AI data accuracy and integration. Just like any adventurer needs a good map, LLMs (Large Language Models) need clear directions to find the best and most accurate information on the web. Sometimes, standard websites aren’t the easiest for them to read perfectly. The [`llms.txt`](https://llmstxt.org) convention is a community effort to solve this. It’s like providing a special, clearly marked trail map for LLMs, guiding them directly to high-quality, structured content tailored for them. ## How it works [Section titled “How it works”](#how-it-works) We want to make sure that when you (or an AI you’re using) ask about Daggerheart™ Forge Schemas, you get the best possible information. That’s why DH-F supports the `llms.txt` convention by providing a few dedicated files: * **[`/llms.txt`](/llms.txt)**: This is the main “signpost” file. When an LLM-powered tool visits our site and looks for this file, it finds a list pointing to our specialized documentation formats designed for AI consumption. * **[`/llms-full.txt`](/llms-full.txt)**: Think of this as the complete spell-book! It contains our full documentation, offering a comprehensive source of information for LLMs that can process a larger volume of text. This helps them get a deep understanding of DH-F. * **[`/llms-small.txt`](/llms-small.txt)**: This is a more compact version of our documentation. It’s highly compressed (like a scroll with only the essential runes!) and is perfect for LLMs or applications that have smaller “context windows” (meaning they can only ‘read’ or remember a limited amount of text at one time). # Getting Started with DH-F Schemas > Learn to integrate DH-F JSON Schemas into your Daggerheart™ development workflow. This guide explains how to use schemas for editor autocompletion and programmatic data validation, with practical examples. Welcome, adventurer, to the world of JSON Schemas! This page is your quick start guide to understanding and using the raw DH-F Schemas that define Daggerheart™ game data. Whether you’re building a character manager, a VTT integration, or just curious, you’re in the right place. We’ll explore two main ways you can get a feel for these schemas: 1. **[Autocomplete in Your Editor](#in-your-editor):** See how schemas provide autocompletion and validation as you type. 2. **[Programmatic Validation](#programmatic-validation):** Understand how your code can use schemas to check if data is structured correctly. Let’s dive in! ## In your editor: [Section titled “In your editor:”](#in-your-editor) One of the neatest immediate benefits of JSON Schemas is how they can power up your code editor, giving you helpful hints and checks as you work with your Daggerheart™ JSON data. Most modern JSON files can include a special line at the top: `"$schema": "URL_to_your_schema.json"`. This little line tells your editor (and other tools) where to find the “rulebook” (the JSON Schema) for this particular JSON file. ### Autocomplete Demo: [Section titled “Autocomplete Demo:”](#autocomplete-demo) 1. Open your favorite code editor that has good JSON Schema support. We recommend [Cursor](https://www.cursor.com/), or [Visual Studio Code](https://code.visualstudio.com/). 2. Create a new file, let’s call it `my_character.json`. 3. Paste the following into your new file: my\_character.json ```json { "$schema": "https://www.dh-forge.com/schema/0.0.0/character.json", "_type": "character", "_meta": { "campaignUrl": "https://www.example.com/campaign/misty-mountains.json", "dateCreated": "2025-04-24T00:00:00.000Z", "dateUpdated": "2025-06-01T17:57:26.353Z", "rulesetVersion": "1.0.0" }, "name": "John Doe", "level": 1 } ``` Note The `$schema` URL includes a version number, like `1.0.0`. You’ll ideally replace this with the current version you intend to use from the [Available Schemas](#available-schema-versions) list below. **What You Should See (Fingers Crossed!):** * **Autocompletion:** Try typing a new property. As you type, your editor might suggest valid property names defined in the `character.json` schema (e.g., if you start typing `"level":` it should recognize if it’s a valid field, and the type of value). * **Descriptions:** Hover over a property name like `"name"` or `"ancestry"`. The editor might show you a description of what that field is for, straight from the schema. * **Validation:** Try changing `"level": 1` to `"level": "boss"`. Your editor should flag this as an error because the schema expects `level` to be a number, not a string. Or, try deleting a required field – you might get a warning. ### Why This is Cool: [Section titled “Why This is Cool:”](#why-this-is-cool) This immediate feedback loop is super helpful! It helps you: * Write valid Daggerheart™ data from the start. * Discover what properties are available and what they mean. * Catch typos and structural errors quickly, without needing to run any code. Heads-Up: While most popular editors support this, your editor might require specific plugins or configuration to get it working smoothly with remote URLs. If it doesn’t work out of the box, a quick search for “\[Your Editor Name] JSON Schema support” might guide you. ## Programmatic Validation: [Section titled “Programmatic Validation:”](#programmatic-validation) Editor assistance is great for when you’re *writing* JSON, but what about when you need to handle JSON data in your code? That’s where programmatic validation comes in. ### How it works: [Section titled “How it works:”](#how-it-works) Imagine you have a rest endpoint that returns a Daggerheart™ character as a JSON object. You also have the DH-F `character.json` schema. How can your program check if your character data actually follows all the rules set out in the schema? That’s the job of a JSON Schema validator library. You pick one for your favorite programming language, feed it: 1. The DH-F schema (the rules). 2. Your JSON data (e.g., the data you want to check). The library then compares your data against the schema and tells you if it’s valid. If not, it will usually provide a list of errors explaining what went wrong (e.g., “property ‘level’ is missing” or “property ‘gold’ should be a number but it was a string”). This is incredibly useful for: * Validating data submitted by users. * Checking data coming from external APIs or files. * Ensuring data is correct before saving it to a database or sending it to another system. ### Example with `ajv` and Javascript [Section titled “Example with ajv and Javascript”](#example-with-ajv-and-javascript) For developers working in JavaScript (Node.js or the browser), [ajv](https://ajv.js.org/) is a very popular and powerful JSON Schema validator. Here’s a simple example of how you might use it. 1. **Install `ajv`** (if you’re in a Node.js project): ```bash npm install ajv ``` 2. **Basic Validation Example:** ```javascript // Import Ajv import Ajv from "ajv"; // Define the URL for the DH-F character schema const DHF_CHARACTER_SCHEMA_URL = "https://www.dh-forge.com/schema/0.0.0/character.json"; // Main logic in an async function to use 'await' async function validateCharacterData() { console.log(`Fetching schema from ${DHF_CHARACTER_SCHEMA_URL}...`); let characterSchema; let validate; try { // --- Step 1: Fetch and Parse the Schema --- // Fetches the schema and parses it from JSON text into a JavaScript object. characterSchema = await fetch(DHF_CHARACTER_SCHEMA_URL).then(res => res.json()); console.log("Schema fetched and parsed."); // --- Step 2: Initialize Ajv and Compile the Schema --- const ajv = new Ajv(); // Create an instance of the Ajv validator validate = ajv.compile(characterSchema); // Prepares the schema for efficient validation console.log("Schema compiled."); } catch (error) { console.error("Failed to load or compile schema:", error.message); // Can't proceed if schema loading/compilation fails return; } // --- Step 3: Prepare Your Data --- // This data should be valid according to the 0.0.0/character.json schema. // (Actual fields depend on the specific 0.0.0 schema definition) const goodCharacterData = { name: "Hero Name", // Assuming 'name' is a required string // Add other fields as required by the 0.0.0 schema, e.g.: // concept: "A brave warrior", // ancestryId: "human_01" }; // This data has intentional errors (e.g., wrong type for 'name') const badCharacterData = { name: 123, // 'name' should be a string // Other required fields might also be missing here }; // --- Step 4: Validate Your Data --- console.log("\nValidating goodCharacterData..."); if (validate(goodCharacterData)) { console.log("✅ Data is valid!"); } else { // 'validate.errors' contains details about what's wrong console.log("❌ Data is invalid. Errors:", validate.errors); } console.log("\nValidating badCharacterData..."); if (validate(badCharacterData)) { console.log("✅ Data is valid? (This is unexpected)"); } else { console.log("❌ Data is invalid. Errors:", validate.errors); } } // Run the validation validateCharacterData(); ``` #### Key Things to Note in This Example: [Section titled “Key Things to Note in This Example:”](#key-things-to-note-in-this-example) * **Simplified Fetch:** The schema is fetched and parsed in a single line. * **Core Logic:** The example focuses on fetching, compiling the schema with `ajv`, and then validating data. * **Sample Data:** `goodCharacterData` and `badCharacterData` are illustrative. For the example to work correctly against the *actual* `0.0.0/character.json`, you’d need to ensure `goodCharacterData` provides all required fields with correct types as defined in that specific schema version. * **Error Info:** If validation fails, `validate.errors` is where `ajv` reports the issues. #### Important Notes for Real-World Use: [Section titled “Important Notes for Real-World Use:”](#important-notes-for-real-world-use) * **Schema Details:** The exact structure of `0.0.0/character.json` will determine what makes data “good” or “bad.” Check the schema itself! * **Error Handling & Caching:** Production code would need more robust error handling and likely schema caching. * **Consult Docs:** `ajv` and other validation libraries have many more features. Their official documentation is the best resource for advanced use. The key takeaway is that JSON Schemas, combined with a validator library, give you a robust way to ensure data quality in any application, regardless of the programming language. ## What’s Next? [Section titled “What’s Next?”](#whats-next) Hopefully, this gives you a good starting point! We encourage you to: * Try the `$schema` trick in your editor with one of the character schemas. * Browse the list of [available schemas](/json-schema/versions) to see what data structures are defined. * If you’re building something, think about how [schema validation](/json-schema/programmatic) could help your project. Happy forging! # Schema Versions > View a complete list of all published DH-F JSON Schema versions for Daggerheart™. ## Version 0 * ### 0.0.x * ##### 0.0.0 * [**campaign**.json](/schema/0.0.0/campaign.json) * [**character**.json](/schema/0.0.0/character.json) * [**ruleset**.json](/schema/0.0.0/ruleset.json)