How to support chained Element queries with Twig tags The craft variable allows you to chain queries for your Elements. For example, you can query the first Entry in a section with either of the following syntaxes:

{% set entry = craft.entries({ section: 'news' }).one() %}
{% set entry = craft.entries.section('news').one() %}


How do we support both of these syntaxes in a Custom Element type?

The Craft Variable defines the entries tag like so:

public function entries(array $criteria = []): EntryQuery
{
  $query = Entry::find();
  Craft::configure($query, $criteria);

  return $query;
}


And, within the EntryQuery class, a public section method is defined:

public function section($value)
{
  if ($value instanceof Section) {
    $this-&gt;structureId = ($value-&gt;structureId ?: false);
    $this-&gt;sectionId = $value-&gt;id;
  } else if ($value !== null) {
    $this-&gt;sectionId = (new Query())
      -&gt;select(['id'])
      -&gt;from([Table::SECTIONS])
      -&gt;where(Db::parseParam('handle', $value))
      -&gt;column();
  } else {
    $this-&gt;sectionId = null;
  }

  return $this;
}


And there appears to be a __set method on the EntryQuery that also references the section method:

public function __set($name, $value)
{
  switch ($name) {
    case 'section':
      $this-&gt;section($value);
      break;
    case 'type':
      $this-&gt;type($value);
      break;
    case 'authorGroup':
      $this-&gt;authorGroup($value);
      break;
    default:
      parent::__set($name, $value);
  }
}


I've experimented with all of those and still only seem to be able to support the first syntax:

{% set entry = craft.entries({ section: 'news' }).one() %}


But can't seem to find a way to support the second syntax:

{% set entry = craft.entries.section('news').one() %}


What am I overlooking? What does a custom Element Type need to add to support the chained syntax for an Element Query via a Twig variable?
You need to return the instance in every single set call. As you noticed correctly the last line in every function that changes properties of your query is return $this which allows you to chain another function after the call. Simple as that.

Always return the query until you execute it with all() or another function like that is enough