How to set page variable from custom module In Drupal 8:

I have custom module code that declares its own theme can twig template.  How do I make module variables available to my Drupal theme's page.html.twig?

I have tried various preprocess_page* functions; however, those functions don't see the variables the module is passing to it's own themed twig templates.

Can the module's controller inject something into the page variables?

Can a Drupal theme's preprocess functions access some variables flowing from a custom module to the module's twig templates?

The controller file:

class PromtController extends ControllerBase
{
    public function program($id)
    {
        $program = PromtService::program((int)$id);

        return [
            '#theme'   =&gt; 'promt_program',
            '#program' =&gt; $program,
            '#title'   =&gt; $program['title']
        ];
    }
}


The module code:

function promt_theme()
{
    return [
        'promt_program' =&gt; [
            'template' =&gt; 'promt_program',
            'variables' =&gt; [
                'program' =&gt; null
            ]
        ]
    ];
}
As far as I can tell, this should be handled in the custom theme, not in the custom module.  This is because the module really has no idea how a custom theme wants to render stuff.

In any case, in the custom theme, the only way I can figure out how to make the data available is to register a hook_preprocess() function in the theme, check the hook that's called, and declare a static variable that sticks around until it can be injected later on.

The custom module's "promt_program" hook will be called earlier than the theme's "page" hook. I'm pretty sure that will always be true.  So, we grab the location_id and then inject it later on.

This preprocess function will get called many, many times, so it seems important to make it thin.

function cob_preprocess(&amp;$vars, $hook)
{
    static $location_id = null;

    switch ($hook) {
        case 'promt_program':
            if (!empty($vars['program']['location_id'])) { $location_id = $vars['program']['location_id']; }
        break;

        case 'page':
            if ($location_id) {
                $query = \Drupal::entityQuery('node')
                    -&gt;condition('status', 1)
                    -&gt;condition('type', 'location')
                    -&gt;condition('field_promt_id', $location_id);
                $nids  = $query-&gt;execute();
                if ($nids) {
                    $vars['node'] = \Drupal::entityTypeManager()-&gt;getStorage('node')-&gt;load(current($nids));
                }
            }
        break;
    }
}