Remove base slug in permalinks of hierarchical custom post type

This will allow you to use the post name without the slug. Essentially anytime the link is requested it can be altered to exclude the base post type. And any time a query runs with just a name, the available post types used in the search are altered to include your post type.

function wpse_remove_cpt_slug( $post_link, $post, $leavename ) {

    // leave these CPT alone
    $whitelist = array ('project');

    if ( ! in_array( $post->post_type, $whitelist ) || 'publish' != $post->post_status )
        return $post_link;

    if( isset($GLOBALS['wp_post_types'][$post->post_type],
             $GLOBALS['wp_post_types'][$post->post_type]->rewrite['slug'])){
        $slug = $GLOBALS['wp_post_types'][$post->post_type]->rewrite['slug'];
    } else {
        $slug = $post->post_type;
    }

    // remove post slug from url
    $post_link = str_replace( "https://wordpress.stackexchange.com/" . $slug  . "https://wordpress.stackexchange.com/", "https://wordpress.stackexchange.com/", $post_link );

    return $post_link;
}
add_filter( 'post_type_link', 'wpse_remove_cpt_slug', 10, 3 );
add_filter( 'post_link', 'wpse_remove_cpt_slug', 10, 3 );

function wpse_parse_request( $query ) {

    // Only noop the main query
    if ( ! $query->is_main_query() )
        return;

    // Only noop our very specific rewrite rule match
    if ( 2 != count( $query->query )
         || ! isset( $query->query['page'] ) )
        return;

    // 'name' will be set if post permalinks are just post_name, otherwise the page rule will match
    if ( ! empty( $query->query['name'] ) )
        $query->set( 'post_type', array( 'post', 'project', 'page' ) );
}
add_action( 'pre_get_posts', 'wpse_parse_request' );

Reference

post_type_link is a filter applied to the permalink URL for a post or custom post type prior to printing by the function get_post_permalink.

post_link is a filter applied to the permalink URL for a post prior to returning the processed url by the function get_permalink.

This hook is called after the query variable object is created, but before the actual query is run. The pre_get_posts action gives developers access to the $query object by reference (any changes you make to $query are made directly to the original object – no return value is necessary).