Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.dottxt.ai/llms.txt

Use this file to discover all available pages before exploring further.

When the same structure appears in multiple places, such as billing and shipping addresses, home and work phone numbers, or primary and secondary contacts, copy-pasting the definition is fragile. Change one copy and forget the other, and you have two subtly different schemas that should be identical. $defs and $ref solve this. You define the structure once in $defs and reference it wherever it’s needed. Updates happen in one place, and every reference stays in sync.

Use case

An order output with billing_address and shipping_address that must follow exactly the same structure: the same fields, the same constraints, and the same required list.

Schema pattern

{
  "type": "object",
  "$defs": {
    "address": {
      "type": "object",
      "properties": {
        "line1": { "type": "string", "minLength": 1, "maxLength": 120 },
        "line2": { "type": "string", "maxLength": 120 },
        "city": { "type": "string", "minLength": 1, "maxLength": 80 },
        "postal_code": { "type": "string", "minLength": 3, "maxLength": 20 },
        "country": { "type": "string", "pattern": "^[A-Z]{2}$" }
      },
      "required": ["line1", "city", "postal_code", "country"],
      "additionalProperties": false
    }
  },
  "properties": {
    "order_id": { "type": "string", "pattern": "^ORD-[0-9]{4,10}$" },
    "billing_address": { "$ref": "#/$defs/address" },
    "shipping_address": { "$ref": "#/$defs/address" }
  },
  "required": ["order_id", "billing_address", "shipping_address"],
  "additionalProperties": false
}

Example output

{
  "order_id": "ORD-8391",
  "billing_address": {
    "line1": "10 Main St",
    "city": "Austin",
    "postal_code": "78701",
    "country": "US"
  },
  "shipping_address": {
    "line1": "55 River Rd",
    "city": "Austin",
    "postal_code": "78702",
    "country": "US"
  }
}

Why this works

Both billing_address and shipping_address resolve to the same $defs/address definition. If you later need to add a state field or change postal_code to zip, you change it once and both addresses update. This also improves readability. A schema with ten $ref references to a well-named definition is easier to review than ten inlined copies of the same 15-line object. Reviewers can focus on the top-level structure and drill into definitions only when needed. In Zod 4, reuse in code does not automatically become $defs reuse in generated JSON Schema. Pass reused: "ref" to toJSONSchema(...) to extract repeated schemas into $defs, and add metadata like .meta({ id: "addressSchema" }) if you want a stable definition name instead of an auto-generated one.