I created a custom field in the user profile to store a custom avatar image called author_avatar (imaginative), but then I needed to expose it in the Etch data as an object. This code will add the author avatar to the user query and to any post-type query. Now I can simply add {this.author_avatar.url} or {this.author_avatar.id} to my template or a loop (item.).

<?php
/**
 * Expose Meta Box user field `author_avatar` to Etch dynamic data.
 *
 * Structure returned to Etch:
 * author_avatar: {
 *   id: 147424,
 *   url: "https://example.com/avatar.webp"
 * }
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Build avatar object.
 */
function fw_get_author_avatar( $user_id ) {

	$avatar_id = absint( get_user_meta( $user_id, 'author_avatar', true ) );

	if ( ! $avatar_id ) {
		return [
			'author_avatar' => [
				'id'  => 0,
				'url' => '',
			],
		];
	}

	return [
		'author_avatar' => [
			'id'  => $avatar_id,
			'url' => esc_url_raw(
				wp_get_attachment_image_url( $avatar_id, 'medium' )
			),
		],
	];
}

/**
 * User dynamic data
 * Usage: {user.author_avatar.url}
 */
add_filter( 'etch/dynamic_data/user', function( $data, $user_id ) {

	return array_merge(
		$data,
		fw_get_author_avatar( $user_id )
	);

}, 10, 2 );


/**
 * Post dynamic data
 * Usage: {this.author_avatar.url}
 */
add_filter( 'etch/dynamic_data/post', function( $data, $post_id ) {

	$author_id = (int) get_post_field( 'post_author', $post_id );

	if ( ! $author_id ) {
		return $data;
	}

	return array_merge(
		$data,
		fw_get_author_avatar( $author_id )
	);

}, 10, 2 );