docs: function validateNode(node, path, ancestors) {
    let errors = [];
  
    if (!node.type) {
      return [{ path, error: 'Node is missing the type property' }];
    }
  
    if (ancestors.length && node.type === 'Page') {
      errors = [...errors, { path, error: 'Encountered a nested page. Page is only allowed at the top level' }];
    }
  
    errors = [
      ...errors,
      ...assertProperties(node, path, requiredProperties[node.type]),
      ...assertDeprecations(node, path, deprecatedProperties[node.type]),
    ];
  
    // Parse logical expressions
    ['hidden', 'disabled', 'test'].forEach((field) => {
      if (!node[field]) {
        return;
      }
  
      try {
        parseExpression(node[field]);
      } catch (e) {
        errors = [...errors, { path: [...path, field], error: e.message }];
      }
    });
  
    // Recurse through children
    if (node.children) {
      node.children.forEach((child, index) => {
        errors = [
          ...errors,
          ...validateNode(child, [...path, 'children', index], [...ancestors, node]),
        ];
      });
    }
  
    // Check and recurse through branches
    if (node.branches) {
      node.branches.forEach((branch, branchIndex) => {
        errors = [
          ...errors,
          ...assertProperties(
            branch,
            [...path, 'branches', branchIndex],
            ['test', 'children'],
          ),
        ];
  
        // Validate the text expression
        if (branch.test) {
          try {
            parseExpression(branch.test);
          } catch (e) {
            errors = [...errors, { path: [...path, 'branches', branchIndex, 'test'], error: e.message }];
          }
        }
  
        // Recurse through the branch children
        if (branch.children) {
          branch.children.forEach((child, index) => {
            errors = [
              ...errors,
              ...validateNode(child, [...path, 'branches', branchIndex, 'children', index], [...ancestors, node]),
            ];
          });
        }
      });
    }
  
    // Recurse over the options
    if (node.options) {
      node.options.forEach((option, index) => {
        errors = [
          ...errors,
          ...validateNode(option, [...path, 'options', index], [...ancestors, node]),
        ];
      });
    }
  
    // Check image
    if (node.image) {
      if (typeof node.image !== 'object') {
        errors = [
          ...errors,
          { path, error: `an object was expected for the image property. Got ${typeof node.image}` },
        ];
      }
  
      errors = [
        ...errors,
        ...assertProperties(
          { ...node.image, type: 'Image' },
          [...path, 'image'],
          ['url', 'alt'],
        ),
      ];
    }
  
    return errors;
  }