Show only public custom posts in home page

Not to be rude, but you’ve missed everything here

Firstly, you should never use query_posts to construct custom queries. This is not just my emphasis, but the codex as well. The one big problem with query_posts is, it many circumstances, pagination fails

Note: This function isn’t meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).

Secondly, you are on the homepage, which I believe is just a normal homepage by default. Why are you running an unnecessary custom query, when you can simply use the main query and modify that with pre_get_posts. It is faster and also doesn’t do any extra db queries.

All this said, go back to the default loop, which should be

<?php 
if(have_posts()) : 
    while(have_posts()) : the_post(); 

        get_template_part( 'content', get_post_format() ); 

    endwhile; 

else : 
?>

    <div class="page-info">
    <h1 style="font-family: <?php echo $options['heading_choise']; ?>"><?php _e('No items found', 'persona') ?></h1>
    </div>

<?php 
endif; 
?>

Replace everything. Then use the following in your functions.php

function posts_on_homepage( $query ) {

    $args = array(
       'public'   => true,
       '_builtin' => false
    );

    $post_types = get_post_types( $args ); 

    if ( $query->is_main_query() && $query->is_home()) {
        $query->set( 'post_type', $post_types );
    }
}
add_action( 'pre_get_posts', 'posts_on_homepage' );

EDIT 1

I just want to add a couple of extra info here, purely for informational purposes. Was is a hurry to post as dinner was waiting 🙂

I just want to come back to your code, if you had debug set to true you would have seen these problems

$post_type only lives inside your foreach loop. What you have done is to close your foreach before the loop, so by the time you add that to your query_posts arguments, $post_type doesn’t exist anymore. So you are now passing an undefined variable to query_posts, causing your query to fail, and you get the NO ITEMS FOUND message

You should have your custom query inside your foreach loop for your query to work. For as long as you are in the foreach loop, $post_type exists and passes a valid value to your custom query

EDIT 2 and 3 SCRAPPED

EDIT 4

It seems that you might have a front page set, as you say my code is not working. If you have a front page set, then pre_get_posts won’t work. Here you will need to run a custom query. Use WP_Query to do that. Change your query to something like

<?php
$args = array(
   'public'   => true,
   '_builtin' => false
);

$post_types = get_post_types( $args ); 

$query = new WP_Query(array('post_type' => $post_types )); 

if($query->have_posts()) : 
    while($query->have_posts()) : $query->the_post(); 

        get_template_part( 'content', get_post_format() ); 

    endwhile; 

    wp_reset_postdata();

else : 
?>

    <div class="page-info">
    <h1 style="font-family: <?php echo $options['heading_choise']; ?>"><?php _e('No items found', 'persona') ?></h1>
    </div>

<?php 
endif; 
?>