8 - Caching for custom blocks doesn't work on
The issue I had is the front page always returns the first visited city. Which is normal because the cache was invalidated by url OR node and the homepage has 1 URL. So unless I create/update/delete a node the cache would not be invalidated.

The solution was to create my own cache context, i.e city and merge it with the url context. This would invalidate the cache per url per city and create a combination of the different possibilities.

Here is the code :

city/city.services.yml

cache_context.cw_city:
    class: Drupal\city\CacheContext\CityCacheContext
    arguments: []
    tags:
      - { name: cache.context }


city/src/CacheContext/CityCacheContext.php

&lt;?php   
namespace Drupal\city\CacheContext;

use Drupal\Core\Cache\Context\CacheContextInterface;
use Drupal\Core\Cache\CacheableMetadata;

class CityCacheContext implements CacheContextInterface {

  /**
   * {@inheritdoc}
   */
  public static function getLabel() {

    return t('some label');
  }
  /**
   * {@inheritdoc}
   */
  public function getContext() {
    // The logic goes here
  }
  /**
   * {@inheritdoc}
   */
  public function getCacheableMetadata() {
    return new CacheableMetadata();
  }
}


And on the block I merged the new context with the parent contexts like this :

/**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    return Cache::mergeContexts(
      parent::getCacheContexts(),
      ['city']
    );
  }


For more information please check this post