I was experimenting with displaying custom post types on the front page of a wordpress site using various methods.

I had first tried using get_posts(), but it couldn’t deal with pagination.

The next alternative was to use WP_Query(). At first I had tried to implement this in the home.php template, but next_posts_link() returned an error 404. It had teh same result when I tried in on front-page.php.

My last try was to implement this as a page template, and in the “Reading Settings” of the WordPress admin, selected to display a static page that used the page template.

static_front_page_setting

This made a difference, and it worked. So I’ve come to the conclusion that when implementing a solution to display custom post types with pagination on a website’s home page, using WP_Query() through a page template is the optimal way to do so.

Here’s the final code:

//get the correct paged figure on a static page - see related note (a)
if ( get_query_var('paged') ) {
   $paged = get_query_var('paged');
}
elseif ( get_query_var('page') ) {
   $paged = get_query_var('page');
}
else {
   $paged = 1;
}

// Query Custom Post Type posts. WP_query instead of get_posts for pagination purposes
$custom_posts = new WP_Query(
   array(
      'post_type' => 'my_custom_post_type',
      'paged' => $paged
   )
);

// Start the loop
if ( $custom_posts->have_posts() ) :
   while ( $custom_posts->have_posts() ) :
      $custom_posts->the_post();
      get_template_part( 'content-archive', get_post_type() );
   endwhile;
   wp_reset_postdata();
endif;

// next_posts_link() usage with max_num_pages - see related note (b)
next_posts_link( 'Older Entries', $custom_posts->max_num_pages );
previous_posts_link( 'Newer Entries' );

Related notes:
(a) https://codex.wordpress.org/Pagination
(b) https://codex.wordpress.org/Function_Reference/next_posts_link