Category page only displaying the posts from a custom type

Ok I found a solution by following the recommandation of s_ha_dum to use pre_gets_posts.

All the following code goes to functions.php

1 Create a new rewrite rule

function rewrite_clean()
{
  // my CPTs
  $types = array('projects', 'works');
  foreach($types as $type)
  {
    add_rewrite_rule('^'.$type.'/([^/]*)/?$', 'index.php?post_type=".$type."&term=$matches[1]','top');
  }
}

add_action('init', 'rewrite_clean');

transform the following format

?post_type=projects&term=architecture

to the following format

projects/architecture

2 Overwrite the post query

// check the vars in url and if there is term then only display from this term
function add_cat_cpt_filter($query)
{
  if($query->is_archive() && get_query_var( 'term' )  && get_query_var( 'post_type' ))
  {
    // get the id of the category by using the slug
    $id = get_category_by_slug(get_query_var( 'term' ))->term_id;
    if($id){
      // add a filter to the query
      $query->set('cat', $id);
    }
    else{
      // redirect if the term doesn't exist
      wp_redirect( "https://wordpress.stackexchange.com/".get_query_var( 'post_type' ));
      exit;
    }
    return;
  }
}
add_action( 'pre_get_posts', 'add_cat_cpt_filter' );

The code above will filter the current archive page with the term used in the URL.

Gotcha

Then I got an issue due to Custom Post Type Permalinks plugin, it kept displaying a category template while I wanted to keep my CPT archive template and just add a filter on it.

The solution is simply to disable and reenable the plugin, it did the trick for me.