How do I set a specific image header for each page? I am trying to have a header with a different image for each page of my site. I believe I should be creating a block. I don't want to create x blocks for x pages, and I prefer to do it programmatically.

So I developped a block using in SubheaderBlock.php.

/**
 * Provides a 'SLS Block' Block
 *
 * @Block(
 *   id = "subheader",
 *   admin_label = @Translation("slssubheader"),
 *   category = "custom",
 * )
 */

namespace Drupal\subheader\Plugin\Block;

use Drupal\Core\Block\BlockBase;

class SubheaderBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() { 
    $node = \Drupal::routeMatch()-&gt;getParameter('node');
    if ($node) {
      $nid = $node-&gt;id();
    }

    return array(
      '#title' =&gt; '',
      '#description' =&gt; '',
      '#nid' =&gt; $nid,
    );
  }
}


Then, I can use the node ID in the Twig template and change the picture accordingly.
The node ID is well passed to the Twig template, but it is cached! So, whenever the page change, {{ #nid }} outputs the same ID.

I have also tried to change Twig template suggestion and have a Twig template for each page, but still there are same caching problem. 

The code below is probably not the perfect one.

/**
* @file
* Code for the example module.
*/

/**
 * Theme hook
 */
function subheader_theme_suggestions_alter(array &amp;$suggestions, array $variables, $hook) {
    $twig = 0;
    // change the suggestion only for the block_id 'subheader'
    if(isset($variables['elements']['#plugin_id'])){
        if  ($variables['elements']['#plugin_id']=== "subheader"){
            // give the twig template the same ID as the NID 
            $node = \Drupal::routeMatch()-&gt;getParameter('node');
                if ($node) {
                $twig = $node-&gt;id();
                }
    // suggestion pattern is 'block__subheaderID 
    $suggestions[] = $hook . '__' .'subheader'.$twig;
}}
}


A
After some many headache...
I believe I got what I wanted, thanks to Ivan.


  SubheaderBlock.php


&lt;?php
/**
 * Provides a 'Subheader' Block
 *
 * @Block(
 *   id = "slssubheader",
 *   admin_label = @Translation("slssubheader"),
 * )
 */

namespace Drupal\subheader\Plugin\Block;
use Drupal\Core\Block\BlockBase;

class SubheaderBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */
  public function build() {

   // get the node id if exist
   $node = \Drupal::routeMatch()-&gt;getParameter('node');
   $nid = $node ? $node-&gt;id() : 0 ;


   $outpout['id'] = array(
           '#markup' =&gt; $nid,
           '#cache'=&gt;[
                 'contexts' =&gt; ['url:pager_id' ],
                 ]

       );

    return $outpout;
  }
}
?&gt;


I get the id in twig with

{{ content.id }}


I checked with a a random number rand(1,100) it works perfect. There is one different cache per nid.

althought it works, I am not sure about the best practice for #markup and url:pager_id