Views, group by first letter as rest export (Alphabet/Glossary listing?)
I am not sure if this is the best solution, but I came up with this:

/**
 * The style plugin for serialized output formats.
 *
 * @ingroup views_style_plugins
 *
 * @ViewsStyle(
 *   id = "serializer_glossary",
 *   title = @Translation("Serializer Glossary"),
 *   help = @Translation("Serializes results and groups them by first letter, for small result lists only."),
 *   display_types = {"data"}
 * )
 */
class SerializerGlossary extends Serializer {

  /**
   * {@inheritdoc}
   */
  public function render() {
    $rows = [];

    foreach ($this-&gt;view-&gt;result as $row) {
      $entity = $this-&gt;view-&gt;rowPlugin-&gt;render($row);
      $title = $entity-&gt;label();
      $first_letter = Unicode::strtoupper($title[0]);
      $rows[$first_letter][] = $this-&gt;view-&gt;rowPlugin-&gt;render($row);
    }

    // Get the content type configured in the display or fallback to the
    // default.
    if ((empty($this-&gt;view-&gt;live_preview))) {
      $content_type = $this-&gt;displayHandler-&gt;getContentType();
    }
    else {
      $content_type = !empty($this-&gt;options['formats']) ? reset($this-&gt;options['formats']) : 'json';
    }

    return $this-&gt;serializer-&gt;serialize(['results' =&gt; ['items' =&gt; $rows, 'totalCount' =&gt; count($this-&gt;view-&gt;result)]], $content_type);
  }
}




I am open to other answers if there is a better way.

The frontend is processing this via ReactJS to do the screenshot in the original question. The reason it is wrapped with 'results' and then 'items' is from a request from the frontend developer to have it structured that way.