I’ll build this as a reusable WordPress theme layout-builder file, with safe defaults, hooks, sections, wrappers, sidebars, breadcrumbs, schema attributes, accessibility, and extensible filters so you can expand it later.
Below is an advanced inc/builders/layout-builder.php file for your rx theme.
It is designed to control site layout, wrappers, container width, sidebar logic, post layout, archive layout, page layout, breadcrumbs area, schema attributes, accessibility skip areas, hooks, and future extension options.
Create this file:
rx-theme/inc/builders/layout-builder.php
Then paste this code:
<?php
/**
* RX Theme Layout Builder
*
* File: inc/builders/layout-builder.php
*
* This file controls the global layout structure of the RX Theme.
* It provides:
*
* - Global site wrapper
* - Main content wrapper
* - Container system
* - Sidebar layout engine
* - Page layout logic
* - Post layout logic
* - Archive layout logic
* - Search layout logic
* - 404 layout logic
* - WooCommerce layout support
* - Breadcrumb area support
* - Schema.org attributes
* - Accessibility helpers
* - Layout hooks
* - Body classes
* - Content classes
* - Sidebar classes
* - Future-ready filter system
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'RX_Layout_Builder' ) ) :
final class RX_Layout_Builder {
/**
* Single instance.
*
* @var RX_Layout_Builder|null
*/
private static $instance = null;
/**
* Theme prefix.
*
* @var string
*/
private $prefix = 'rx';
/**
* Default layout settings.
*
* @var array
*/
private $defaults = array();
/**
* Get instance.
*
* @return RX_Layout_Builder
*/
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*/
private function __construct() {
$this->set_defaults();
$this->hooks();
}
/**
* Set default layout options.
*
* @return void
*/
private function set_defaults() {
$this->defaults = array(
'site_layout' => 'full-width',
'container_type' => 'contained',
'container_width' => 1200,
'content_width' => 760,
'sidebar_width' => 320,
'gap_width' => 32,
'default_sidebar_position' => 'right',
'single_sidebar_position' => 'right',
'page_sidebar_position' => 'none',
'archive_sidebar_position' => 'right',
'search_sidebar_position' => 'right',
'home_sidebar_position' => 'right',
'404_sidebar_position' => 'none',
'enable_breadcrumbs' => true,
'enable_page_header' => true,
'enable_archive_header' => true,
'enable_post_header' => true,
'enable_featured_image' => true,
'enable_author_box' => true,
'enable_related_posts' => true,
'enable_post_nav' => true,
'enable_comments_area' => true,
'enable_schema' => true,
'enable_skip_link' => true,
'enable_print_classes' => true,
'enable_dark_mode_class' => true,
'archive_columns' => 1,
'search_columns' => 1,
'related_posts_columns' => 3,
'content_card_style' => 'default',
'archive_card_style' => 'default',
'post_card_style' => 'default',
'sticky_sidebar' => true,
'lazy_layout_classes' => true,
'rtl_support' => true,
);
$this->defaults = apply_filters( 'rx_layout_builder_defaults', $this->defaults );
}
/**
* Register hooks.
*
* @return void
*/
private function hooks() {
add_filter( 'body_class', array( $this, 'body_classes' ) );
add_action( 'rx_before_site', array( $this, 'skip_link' ), 5 );
add_action( 'rx_before_site', array( $this, 'site_open' ), 10 );
add_action( 'rx_after_site', array( $this, 'site_close' ), 10 );
add_action( 'rx_before_main', array( $this, 'main_open' ), 10 );
add_action( 'rx_after_main', array( $this, 'main_close' ), 10 );
add_action( 'rx_before_content_area', array( $this, 'content_area_open' ), 10 );
add_action( 'rx_after_content_area', array( $this, 'content_area_close' ), 10 );
add_action( 'rx_before_primary_content', array( $this, 'primary_content_open' ), 10 );
add_action( 'rx_after_primary_content', array( $this, 'primary_content_close' ), 10 );
add_action( 'rx_before_sidebar', array( $this, 'sidebar_open' ), 10 );
add_action( 'rx_after_sidebar', array( $this, 'sidebar_close' ), 10 );
add_action( 'rx_before_loop', array( $this, 'maybe_page_header' ), 10 );
add_action( 'rx_before_loop', array( $this, 'maybe_breadcrumbs' ), 8 );
add_action( 'wp_head', array( $this, 'layout_css_variables' ), 20 );
}
/**
* Get layout option.
*
* @param string $key Option key.
* @param mixed $fallback Fallback value.
* @return mixed
*/
public function get_option( $key, $fallback = null ) {
$default = array_key_exists( $key, $this->defaults ) ? $this->defaults[ $key ] : $fallback;
/**
* You can connect this with Customizer later:
*
* get_theme_mod( 'rx_' . $key, $default );
*/
$value = get_theme_mod( 'rx_' . $key, $default );
return apply_filters( "rx_layout_option_{$key}", $value, $key, $default );
}
/**
* Check if option is enabled.
*
* @param string $key Option key.
* @return bool
*/
public function is_enabled( $key ) {
return (bool) $this->get_option( $key, false );
}
/**
* Add body classes.
*
* @param array $classes Body classes.
* @return array
*/
public function body_classes( $classes ) {
$layout = $this->get_current_layout();
$sidebar_position = $this->get_sidebar_position();
$container_type = $this->get_option( 'container_type', 'contained' );
$classes[] = 'rx-theme';
$classes[] = 'rx-layout-' . sanitize_html_class( $layout );
$classes[] = 'rx-sidebar-' . sanitize_html_class( $sidebar_position );
$classes[] = 'rx-container-' . sanitize_html_class( $container_type );
$classes[] = is_singular() ? 'rx-view-singular' : 'rx-view-listing';
if ( $this->has_sidebar() ) {
$classes[] = 'rx-has-sidebar';
} else {
$classes[] = 'rx-no-sidebar';
}
if ( $this->is_enabled( 'sticky_sidebar' ) ) {
$classes[] = 'rx-sticky-sidebar-enabled';
}
if ( $this->is_enabled( 'enable_dark_mode_class' ) ) {
$classes[] = 'rx-color-scheme-ready';
}
if ( is_rtl() && $this->is_enabled( 'rtl_support' ) ) {
$classes[] = 'rx-rtl';
}
if ( is_front_page() ) {
$classes[] = 'rx-front-page';
}
if ( is_home() ) {
$classes[] = 'rx-blog-home';
}
if ( is_archive() ) {
$classes[] = 'rx-archive-page';
}
if ( is_search() ) {
$classes[] = 'rx-search-page';
}
if ( is_404() ) {
$classes[] = 'rx-error-404-page';
}
if ( function_exists( 'is_woocommerce' ) && is_woocommerce() ) {
$classes[] = 'rx-woocommerce-page';
}
return array_unique( apply_filters( 'rx_layout_body_classes', $classes, $this ) );
}
/**
* Print skip link.
*
* @return void
*/
public function skip_link() {
if ( ! $this->is_enabled( 'enable_skip_link' ) ) {
return;
}
echo '<a class="rx-skip-link screen-reader-text" href="#rx-primary-content">';
echo esc_html__( 'Skip to content', 'rx-theme' );
echo '</a>';
}
/**
* Open site wrapper.
*
* @return void
*/
public function site_open() {
$attrs = array(
'id' => 'rx-page',
'class' => 'rx-site',
);
echo '<div ' . $this->render_attrs( $attrs ) . '>';
do_action( 'rx_site_inside_top' );
}
/**
* Close site wrapper.
*
* @return void
*/
public function site_close() {
do_action( 'rx_site_inside_bottom' );
echo '</div><!-- #rx-page -->';
}
/**
* Open main wrapper.
*
* @return void
*/
public function main_open() {
$attrs = array(
'id' => 'rx-main',
'class' => $this->get_main_classes(),
'role' => 'main',
'itemscope' => $this->schema_enabled() ? 'itemscope' : null,
'itemtype' => $this->schema_enabled() ? $this->get_main_schema_type() : null,
);
echo '<main ' . $this->render_attrs( $attrs ) . '>';
do_action( 'rx_main_inside_top' );
}
/**
* Close main wrapper.
*
* @return void
*/
public function main_close() {
do_action( 'rx_main_inside_bottom' );
echo '</main><!-- #rx-main -->';
}
/**
* Open content area.
*
* @return void
*/
public function content_area_open() {
$attrs = array(
'id' => 'rx-content-area',
'class' => $this->get_content_area_classes(),
);
echo '<div ' . $this->render_attrs( $attrs ) . '>';
do_action( 'rx_content_area_inside_top' );
}
/**
* Close content area.
*
* @return void
*/
public function content_area_close() {
do_action( 'rx_content_area_inside_bottom' );
echo '</div><!-- #rx-content-area -->';
}
/**
* Open primary content.
*
* @return void
*/
public function primary_content_open() {
$attrs = array(
'id' => 'rx-primary-content',
'class' => $this->get_primary_content_classes(),
'itemscope' => $this->schema_enabled() ? 'itemscope' : null,
'itemtype' => $this->schema_enabled() ? $this->get_content_schema_type() : null,
);
echo '<div ' . $this->render_attrs( $attrs ) . '>';
do_action( 'rx_primary_content_inside_top' );
}
/**
* Close primary content.
*
* @return void
*/
public function primary_content_close() {
do_action( 'rx_primary_content_inside_bottom' );
echo '</div><!-- #rx-primary-content -->';
}
/**
* Open sidebar.
*
* @return void
*/
public function sidebar_open() {
if ( ! $this->has_sidebar() ) {
return;
}
$attrs = array(
'id' => 'rx-sidebar',
'class' => $this->get_sidebar_classes(),
'role' => 'complementary',
'aria-label'=> esc_attr__( 'Sidebar', 'rx-theme' ),
'itemscope' => $this->schema_enabled() ? 'itemscope' : null,
'itemtype' => $this->schema_enabled() ? 'https://schema.org/WPSideBar' : null,
);
echo '<aside ' . $this->render_attrs( $attrs ) . '>';
do_action( 'rx_sidebar_inside_top' );
}
/**
* Close sidebar.
*
* @return void
*/
public function sidebar_close() {
if ( ! $this->has_sidebar() ) {
return;
}
do_action( 'rx_sidebar_inside_bottom' );
echo '</aside><!-- #rx-sidebar -->';
}
/**
* Get current layout.
*
* @return string
*/
public function get_current_layout() {
$layout = $this->get_option( 'site_layout', 'full-width' );
if ( is_singular() ) {
$post_id = get_queried_object_id();
if ( $post_id ) {
$meta_layout = get_post_meta( $post_id, '_rx_site_layout', true );
if ( ! empty( $meta_layout ) ) {
$layout = $meta_layout;
}
}
}
if ( is_404() ) {
$layout = 'full-width';
}
return sanitize_key( apply_filters( 'rx_current_layout', $layout, $this ) );
}
/**
* Get sidebar position.
*
* @return string
*/
public function get_sidebar_position() {
$position = $this->get_option( 'default_sidebar_position', 'right' );
if ( is_single() ) {
$position = $this->get_option( 'single_sidebar_position', 'right' );
} elseif ( is_page() ) {
$position = $this->get_option( 'page_sidebar_position', 'none' );
} elseif ( is_archive() ) {
$position = $this->get_option( 'archive_sidebar_position', 'right' );
} elseif ( is_search() ) {
$position = $this->get_option( 'search_sidebar_position', 'right' );
} elseif ( is_home() ) {
$position = $this->get_option( 'home_sidebar_position', 'right' );
} elseif ( is_404() ) {
$position = $this->get_option( '404_sidebar_position', 'none' );
}
if ( is_singular() ) {
$post_id = get_queried_object_id();
if ( $post_id ) {
$meta_position = get_post_meta( $post_id, '_rx_sidebar_position', true );
if ( ! empty( $meta_position ) ) {
$position = $meta_position;
}
}
}
$allowed = array( 'left', 'right', 'none' );
if ( ! in_array( $position, $allowed, true ) ) {
$position = 'right';
}
return apply_filters( 'rx_sidebar_position', $position, $this );
}
/**
* Check if page has sidebar.
*
* @return bool
*/
public function has_sidebar() {
$position = $this->get_sidebar_position();
if ( 'none' === $position ) {
return false;
}
if ( ! is_active_sidebar( 'sidebar-1' ) ) {
return false;
}
if ( is_404() ) {
return false;
}
return (bool) apply_filters( 'rx_has_sidebar', true, $position, $this );
}
/**
* Get main classes.
*
* @return string
*/
public function get_main_classes() {
$classes = array(
'rx-main',
'rx-main-layout-' . $this->get_current_layout(),
);
if ( is_singular() ) {
$classes[] = 'rx-main-singular';
}
if ( is_archive() || is_home() || is_search() ) {
$classes[] = 'rx-main-listing';
}
return esc_attr( implode( ' ', array_unique( apply_filters( 'rx_main_classes', $classes, $this ) ) ) );
}
/**
* Get content area classes.
*
* @return string
*/
public function get_content_area_classes() {
$classes = array(
'rx-content-area',
'rx-container',
'rx-container-' . sanitize_html_class( $this->get_option( 'container_type', 'contained' ) ),
'rx-sidebar-position-' . sanitize_html_class( $this->get_sidebar_position() ),
);
if ( $this->has_sidebar() ) {
$classes[] = 'rx-grid';
$classes[] = 'rx-grid-with-sidebar';
} else {
$classes[] = 'rx-grid-no-sidebar';
}
if ( 'left' === $this->get_sidebar_position() ) {
$classes[] = 'rx-sidebar-left-layout';
}
if ( 'right' === $this->get_sidebar_position() ) {
$classes[] = 'rx-sidebar-right-layout';
}
return esc_attr( implode( ' ', array_unique( apply_filters( 'rx_content_area_classes', $classes, $this ) ) ) );
}
/**
* Get primary content classes.
*
* @return string
*/
public function get_primary_content_classes() {
$classes = array(
'rx-primary-content',
'rx-content',
);
if ( is_singular() ) {
$classes[] = 'rx-content-singular';
$classes[] = 'rx-content-type-' . sanitize_html_class( get_post_type() );
}
if ( is_archive() || is_home() || is_search() ) {
$classes[] = 'rx-content-archive';
$classes[] = 'rx-archive-columns-' . absint( $this->get_archive_columns() );
}
if ( ! $this->has_sidebar() ) {
$classes[] = 'rx-content-full-width';
}
return esc_attr( implode( ' ', array_unique( apply_filters( 'rx_primary_content_classes', $classes, $this ) ) ) );
}
/**
* Get sidebar classes.
*
* @return string
*/
public function get_sidebar_classes() {
$classes = array(
'rx-sidebar',
'rx-widget-area',
'rx-sidebar-' . sanitize_html_class( $this->get_sidebar_position() ),
);
if ( $this->is_enabled( 'sticky_sidebar' ) ) {
$classes[] = 'rx-sticky-sidebar';
}
return esc_attr( implode( ' ', array_unique( apply_filters( 'rx_sidebar_classes', $classes, $this ) ) ) );
}
/**
* Get archive columns.
*
* @return int
*/
public function get_archive_columns() {
$columns = is_search()
? absint( $this->get_option( 'search_columns', 1 ) )
: absint( $this->get_option( 'archive_columns', 1 ) );
if ( $columns < 1 ) {
$columns = 1;
}
if ( $columns > 4 ) {
$columns = 4;
}
return apply_filters( 'rx_archive_columns', $columns, $this );
}
/**
* Maybe output page header.
*
* @return void
*/
public function maybe_page_header() {
if ( is_singular() && ! $this->is_enabled( 'enable_post_header' ) ) {
return;
}
if ( is_page() && ! $this->is_enabled( 'enable_page_header' ) ) {
return;
}
if ( ( is_archive() || is_home() || is_search() ) && ! $this->is_enabled( 'enable_archive_header' ) ) {
return;
}
if ( is_404() ) {
return;
}
do_action( 'rx_before_page_header' );
echo '<header class="rx-page-header">';
if ( is_home() && ! is_front_page() ) {
$page_for_posts = get_option( 'page_for_posts' );
$title = $page_for_posts ? get_the_title( $page_for_posts ) : __( 'Blog', 'rx-theme' );
echo '<h1 class="rx-page-title">' . esc_html( $title ) . '</h1>';
} elseif ( is_archive() ) {
the_archive_title( '<h1 class="rx-page-title">', '</h1>' );
the_archive_description( '<div class="rx-archive-description">', '</div>' );
} elseif ( is_search() ) {
echo '<h1 class="rx-page-title">';
printf(
esc_html__( 'Search Results for: %s', 'rx-theme' ),
'<span>' . esc_html( get_search_query() ) . '</span>'
);
echo '</h1>';
} elseif ( is_singular() ) {
echo '<h1 class="rx-page-title" itemprop="headline">';
the_title();
echo '</h1>';
if ( is_single() ) {
$this->post_meta();
}
}
echo '</header>';
do_action( 'rx_after_page_header' );
}
/**
* Output breadcrumbs placeholder.
*
* @return void
*/
public function maybe_breadcrumbs() {
if ( ! $this->is_enabled( 'enable_breadcrumbs' ) ) {
return;
}
if ( is_front_page() ) {
return;
}
do_action( 'rx_before_breadcrumbs' );
echo '<nav class="rx-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'rx-theme' ) . '">';
if ( function_exists( 'yoast_breadcrumb' ) ) {
yoast_breadcrumb( '<div class="rx-breadcrumbs-inner">', '</div>' );
} elseif ( function_exists( 'rank_math_the_breadcrumbs' ) ) {
echo '<div class="rx-breadcrumbs-inner">';
rank_math_the_breadcrumbs();
echo '</div>';
} elseif ( function_exists( 'bcn_display' ) ) {
echo '<div class="rx-breadcrumbs-inner">';
bcn_display();
echo '</div>';
} else {
$this->simple_breadcrumbs();
}
echo '</nav>';
do_action( 'rx_after_breadcrumbs' );
}
/**
* Simple fallback breadcrumbs.
*
* @return void
*/
private function simple_breadcrumbs() {
echo '<ol class="rx-breadcrumb-list">';
echo '<li class="rx-breadcrumb-item"><a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Home', 'rx-theme' ) . '</a></li>';
if ( is_category() || is_single() ) {
$categories = get_the_category();
if ( ! empty( $categories ) ) {
$category = $categories[0];
echo '<li class="rx-breadcrumb-item"><a href="' . esc_url( get_category_link( $category->term_id ) ) . '">' . esc_html( $category->name ) . '</a></li>';
}
if ( is_single() ) {
echo '<li class="rx-breadcrumb-item rx-current">' . esc_html( get_the_title() ) . '</li>';
}
} elseif ( is_page() ) {
$post = get_post();
if ( $post && $post->post_parent ) {
$parents = array_reverse( get_post_ancestors( $post->ID ) );
foreach ( $parents as $parent_id ) {
echo '<li class="rx-breadcrumb-item"><a href="' . esc_url( get_permalink( $parent_id ) ) . '">' . esc_html( get_the_title( $parent_id ) ) . '</a></li>';
}
}
echo '<li class="rx-breadcrumb-item rx-current">' . esc_html( get_the_title() ) . '</li>';
} elseif ( is_search() ) {
echo '<li class="rx-breadcrumb-item rx-current">' . esc_html__( 'Search', 'rx-theme' ) . '</li>';
} elseif ( is_archive() ) {
echo '<li class="rx-breadcrumb-item rx-current">' . esc_html( get_the_archive_title() ) . '</li>';
} elseif ( is_404() ) {
echo '<li class="rx-breadcrumb-item rx-current">' . esc_html__( '404', 'rx-theme' ) . '</li>';
}
echo '</ol>';
}
/**
* Output post meta.
*
* @return void
*/
public function post_meta() {
if ( ! is_single() ) {
return;
}
echo '<div class="rx-post-meta">';
echo '<span class="rx-post-meta-item rx-post-date">';
echo '<time datetime="' . esc_attr( get_the_date( DATE_W3C ) ) . '" itemprop="datePublished">';
echo esc_html( get_the_date() );
echo '</time>';
echo '</span>';
echo '<span class="rx-post-meta-item rx-post-author" itemprop="author" itemscope itemtype="https://schema.org/Person">';
echo esc_html__( 'By ', 'rx-theme' );
echo '<a href="' . esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '" itemprop="url">';
echo '<span itemprop="name">' . esc_html( get_the_author() ) . '</span>';
echo '</a>';
echo '</span>';
$categories = get_the_category();
if ( ! empty( $categories ) ) {
echo '<span class="rx-post-meta-item rx-post-category">';
the_category( ', ' );
echo '</span>';
}
if ( comments_open() || get_comments_number() ) {
echo '<span class="rx-post-meta-item rx-post-comments">';
comments_popup_link(
esc_html__( 'No Comments', 'rx-theme' ),
esc_html__( '1 Comment', 'rx-theme' ),
esc_html__( '% Comments', 'rx-theme' )
);
echo '</span>';
}
echo '</div>';
}
/**
* Render featured image.
*
* @param string $size Image size.
* @return void
*/
public function featured_image( $size = 'large' ) {
if ( ! $this->is_enabled( 'enable_featured_image' ) ) {
return;
}
if ( ! has_post_thumbnail() ) {
return;
}
$size = apply_filters( 'rx_featured_image_size', $size );
echo '<div class="rx-featured-image">';
the_post_thumbnail(
$size,
array(
'class' => 'rx-post-thumbnail',
'loading' => is_singular() ? 'eager' : 'lazy',
'decoding' => 'async',
'itemprop' => 'image',
)
);
echo '</div>';
}
/**
* Render post content.
*
* @return void
*/
public function post_content() {
echo '<div class="rx-entry-content" itemprop="articleBody">';
the_content();
wp_link_pages(
array(
'before' => '<div class="rx-page-links">' . esc_html__( 'Pages:', 'rx-theme' ),
'after' => '</div>',
)
);
echo '</div>';
}
/**
* Render excerpt.
*
* @return void
*/
public function post_excerpt() {
echo '<div class="rx-entry-summary">';
the_excerpt();
echo '</div>';
}
/**
* Render read more button.
*
* @return void
*/
public function read_more_button() {
echo '<a class="rx-read-more" href="' . esc_url( get_permalink() ) . '" aria-label="' . esc_attr( sprintf( __( 'Read more about %s', 'rx-theme' ), get_the_title() ) ) . '">';
echo esc_html__( 'Read More', 'rx-theme' );
echo '</a>';
}
/**
* Render article open.
*
* @return void
*/
public function article_open() {
$classes = get_post_class( $this->get_article_classes() );
$attrs = array(
'id' => 'post-' . get_the_ID(),
'class' => implode( ' ', $classes ),
'itemscope' => $this->schema_enabled() ? 'itemscope' : null,
'itemtype' => $this->schema_enabled() ? $this->get_article_schema_type() : null,
);
echo '<article ' . $this->render_attrs( $attrs ) . '>';
}
/**
* Render article close.
*
* @return void
*/
public function article_close() {
echo '</article>';
}
/**
* Get article classes.
*
* @return array
*/
public function get_article_classes() {
$classes = array(
'rx-entry',
);
if ( is_singular() ) {
$classes[] = 'rx-single-entry';
$classes[] = 'rx-card-style-' . sanitize_html_class( $this->get_option( 'post_card_style', 'default' ) );
} else {
$classes[] = 'rx-archive-entry';
$classes[] = 'rx-card-style-' . sanitize_html_class( $this->get_option( 'archive_card_style', 'default' ) );
}
if ( has_post_thumbnail() ) {
$classes[] = 'rx-has-thumbnail';
} else {
$classes[] = 'rx-no-thumbnail';
}
return apply_filters( 'rx_article_classes', $classes, $this );
}
/**
* Render archive article.
*
* @return void
*/
public function archive_article() {
$this->article_open();
do_action( 'rx_archive_article_top' );
$this->featured_image( 'medium_large' );
echo '<div class="rx-entry-card-content">';
echo '<header class="rx-entry-header">';
echo '<h2 class="rx-entry-title" itemprop="headline">';
echo '<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">';
the_title();
echo '</a>';
echo '</h2>';
$this->post_meta();
echo '</header>';
$this->post_excerpt();
$this->read_more_button();
echo '</div>';
do_action( 'rx_archive_article_bottom' );
$this->article_close();
}
/**
* Render single article.
*
* @return void
*/
public function single_article() {
$this->article_open();
do_action( 'rx_single_article_top' );
$this->featured_image( 'large' );
$this->post_content();
if ( has_tag() ) {
echo '<footer class="rx-entry-footer">';
the_tags( '<div class="rx-post-tags">', '', '</div>' );
echo '</footer>';
}
do_action( 'rx_single_article_bottom' );
$this->article_close();
$this->post_navigation();
$this->author_box();
$this->related_posts();
$this->comments_area();
}
/**
* Render post navigation.
*
* @return void
*/
public function post_navigation() {
if ( ! $this->is_enabled( 'enable_post_nav' ) ) {
return;
}
if ( ! is_single() ) {
return;
}
the_post_navigation(
array(
'prev_text' => '<span class="rx-nav-subtitle">' . esc_html__( 'Previous:', 'rx-theme' ) . '</span> <span class="rx-nav-title">%title</span>',
'next_text' => '<span class="rx-nav-subtitle">' . esc_html__( 'Next:', 'rx-theme' ) . '</span> <span class="rx-nav-title">%title</span>',
)
);
}
/**
* Render author box.
*
* @return void
*/
public function author_box() {
if ( ! $this->is_enabled( 'enable_author_box' ) ) {
return;
}
if ( ! is_single() ) {
return;
}
$description = get_the_author_meta( 'description' );
if ( empty( $description ) ) {
return;
}
echo '<section class="rx-author-box" itemscope itemtype="https://schema.org/Person">';
echo '<div class="rx-author-avatar">';
echo get_avatar( get_the_author_meta( 'ID' ), 96 );
echo '</div>';
echo '<div class="rx-author-content">';
echo '<h2 class="rx-author-title">';
echo esc_html__( 'About ', 'rx-theme' );
echo '<span itemprop="name">' . esc_html( get_the_author() ) . '</span>';
echo '</h2>';
echo '<p class="rx-author-description" itemprop="description">';
echo esc_html( $description );
echo '</p>';
echo '<a class="rx-author-link" href="' . esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '" itemprop="url">';
echo esc_html__( 'View all posts', 'rx-theme' );
echo '</a>';
echo '</div>';
echo '</section>';
}
/**
* Render related posts.
*
* @return void
*/
public function related_posts() {
if ( ! $this->is_enabled( 'enable_related_posts' ) ) {
return;
}
if ( ! is_single() ) {
return;
}
$post_id = get_the_ID();
$categories = wp_get_post_categories( $post_id );
if ( empty( $categories ) ) {
return;
}
$query = new WP_Query(
array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => absint( $this->get_option( 'related_posts_columns', 3 ) ),
'post__not_in' => array( $post_id ),
'category__in' => $categories,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
)
);
if ( ! $query->have_posts() ) {
wp_reset_postdata();
return;
}
echo '<section class="rx-related-posts">';
echo '<h2 class="rx-related-posts-title">' . esc_html__( 'Related Posts', 'rx-theme' ) . '</h2>';
echo '<div class="rx-related-posts-grid rx-columns-' . absint( $this->get_option( 'related_posts_columns', 3 ) ) . '">';
while ( $query->have_posts() ) {
$query->the_post();
echo '<article class="rx-related-post-card">';
if ( has_post_thumbnail() ) {
echo '<a class="rx-related-post-thumbnail" href="' . esc_url( get_permalink() ) . '">';
the_post_thumbnail(
'medium',
array(
'loading' => 'lazy',
'decoding' => 'async',
)
);
echo '</a>';
}
echo '<h3 class="rx-related-post-title">';
echo '<a href="' . esc_url( get_permalink() ) . '">';
the_title();
echo '</a>';
echo '</h3>';
echo '</article>';
}
echo '</div>';
echo '</section>';
wp_reset_postdata();
}
/**
* Render comments area.
*
* @return void
*/
public function comments_area() {
if ( ! $this->is_enabled( 'enable_comments_area' ) ) {
return;
}
if ( ! is_single() && ! is_page() ) {
return;
}
if ( comments_open() || get_comments_number() ) {
comments_template();
}
}
/**
* Get schema status.
*
* @return bool
*/
private function schema_enabled() {
return (bool) $this->is_enabled( 'enable_schema' );
}
/**
* Get main schema type.
*
* @return string
*/
private function get_main_schema_type() {
if ( is_search() ) {
return 'https://schema.org/SearchResultsPage';
}
if ( is_archive() || is_home() ) {
return 'https://schema.org/CollectionPage';
}
if ( is_404() ) {
return 'https://schema.org/WebPage';
}
return 'https://schema.org/WebPage';
}
/**
* Get content schema type.
*
* @return string
*/
private function get_content_schema_type() {
if ( is_single() ) {
return 'https://schema.org/BlogPosting';
}
if ( is_page() ) {
return 'https://schema.org/WebPage';
}
return 'https://schema.org/ItemList';
}
/**
* Get article schema type.
*
* @return string
*/
private function get_article_schema_type() {
if ( is_single() ) {
return 'https://schema.org/Article';
}
return 'https://schema.org/BlogPosting';
}
/**
* Render attributes safely.
*
* @param array $attrs Attributes.
* @return string
*/
public function render_attrs( $attrs ) {
$output = '';
foreach ( $attrs as $key => $value ) {
if ( null === $value || false === $value || '' === $value ) {
continue;
}
if ( true === $value ) {
$output .= ' ' . esc_attr( $key );
} else {
$output .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
}
}
return trim( $output );
}
/**
* Print CSS variables.
*
* @return void
*/
public function layout_css_variables() {
$container_width = absint( $this->get_option( 'container_width', 1200 ) );
$content_width = absint( $this->get_option( 'content_width', 760 ) );
$sidebar_width = absint( $this->get_option( 'sidebar_width', 320 ) );
$gap_width = absint( $this->get_option( 'gap_width', 32 ) );
?>
<style id="rx-layout-builder-vars">
:root {
--rx-container-width: <?php echo esc_html( $container_width ); ?>px;
--rx-content-width: <?php echo esc_html( $content_width ); ?>px;
--rx-sidebar-width: <?php echo esc_html( $sidebar_width ); ?>px;
--rx-layout-gap: <?php echo esc_html( $gap_width ); ?>px;
}
.rx-container {
width: min(100% - 32px, var(--rx-container-width));
margin-inline: auto;
}
.rx-content-area.rx-grid-with-sidebar {
display: grid;
gap: var(--rx-layout-gap);
grid-template-columns: minmax(0, 1fr) var(--rx-sidebar-width);
align-items: start;
}
.rx-sidebar-left-layout {
grid-template-columns: var(--rx-sidebar-width) minmax(0, 1fr);
}
.rx-sidebar-left-layout .rx-primary-content {
order: 2;
}
.rx-sidebar-left-layout .rx-sidebar {
order: 1;
}
.rx-primary-content {
min-width: 0;
}
.rx-sticky-sidebar {
position: sticky;
top: 32px;
}
.rx-related-posts-grid,
.rx-archive-columns-2,
.rx-archive-columns-3,
.rx-archive-columns-4 {
display: grid;
gap: var(--rx-layout-gap);
}
.rx-related-posts-grid.rx-columns-2,
.rx-archive-columns-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.rx-related-posts-grid.rx-columns-3,
.rx-archive-columns-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.rx-related-posts-grid.rx-columns-4,
.rx-archive-columns-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.rx-skip-link:focus {
position: fixed;
top: 16px;
left: 16px;
z-index: 999999;
padding: 10px 14px;
background: #000;
color: #fff;
text-decoration: none;
}
@media (max-width: 960px) {
.rx-content-area.rx-grid-with-sidebar,
.rx-sidebar-left-layout {
grid-template-columns: 1fr;
}
.rx-sidebar-left-layout .rx-primary-content,
.rx-sidebar-left-layout .rx-sidebar {
order: initial;
}
.rx-sticky-sidebar {
position: static;
}
.rx-related-posts-grid.rx-columns-2,
.rx-related-posts-grid.rx-columns-3,
.rx-related-posts-grid.rx-columns-4,
.rx-archive-columns-2,
.rx-archive-columns-3,
.rx-archive-columns-4 {
grid-template-columns: 1fr;
}
}
</style>
<?php
}
}
endif;
/**
* Helper function.
*
* @return RX_Layout_Builder
*/
function rx_layout_builder() {
return RX_Layout_Builder::instance();
}
/**
* Initialize layout builder.
*/
rx_layout_builder();
/**
* Template helper: open site.
*
* Use in header.php:
* do_action( 'rx_before_site' );
*/
function rx_site_open() {
do_action( 'rx_before_site' );
}
/**
* Template helper: close site.
*
* Use in footer.php:
* do_action( 'rx_after_site' );
*/
function rx_site_close() {
do_action( 'rx_after_site' );
}
/**
* Template helper: open main area.
*/
function rx_main_open() {
do_action( 'rx_before_main' );
do_action( 'rx_before_content_area' );
do_action( 'rx_before_primary_content' );
}
/**
* Template helper: close main area.
*/
function rx_main_close() {
do_action( 'rx_after_primary_content' );
if ( rx_layout_builder()->has_sidebar() ) {
do_action( 'rx_before_sidebar' );
if ( is_active_sidebar( 'sidebar-1' ) ) {
dynamic_sidebar( 'sidebar-1' );
}
do_action( 'rx_after_sidebar' );
}
do_action( 'rx_after_content_area' );
do_action( 'rx_after_main' );
}
/**
* Template helper: render loop header.
*/
function rx_loop_header() {
do_action( 'rx_before_loop' );
}
/**
* Template helper: render archive card.
*/
function rx_archive_card() {
rx_layout_builder()->archive_article();
}
/**
* Template helper: render single content.
*/
function rx_single_content() {
rx_layout_builder()->single_article();
}
/**
* Template helper: render featured image.
*
* @param string $size Image size.
*/
function rx_featured_image( $size = 'large' ) {
rx_layout_builder()->featured_image( $size );
}
/**
* Template helper: render post content.
*/
function rx_post_content() {
rx_layout_builder()->post_content();
}
/**
* Template helper: render post excerpt.
*/
function rx_post_excerpt() {
rx_layout_builder()->post_excerpt();
}
/**
* Template helper: render read more button.
*/
function rx_read_more_button() {
rx_layout_builder()->read_more_button();
}
Now include this file in your functions.php:
require_once get_template_directory() . '/inc/builders/layout-builder.php';
Example use in header.php:
<?php do_action( 'rx_before_site' ); ?>
<?php get_template_part( 'template-parts/header/site-header' ); ?>
Example use in footer.php:
<?php get_template_part( 'template-parts/footer/site-footer' ); ?>
<?php do_action( 'rx_after_site' ); ?>
Example use in index.php:
<?php get_header(); ?>
<?php rx_main_open(); ?>
<?php rx_loop_header(); ?>
<?php if ( have_posts() ) : ?>
<div class="rx-posts-loop">
<?php
while ( have_posts() ) :
the_post();
rx_archive_card();
endwhile;
?>
</div>
<?php the_posts_pagination(); ?>
<?php else : ?>
<p><?php esc_html_e( 'No posts found.', 'rx-theme' ); ?></p>
<?php endif; ?>
<?php rx_main_close(); ?>
<?php get_footer(); ?>
Example use in single.php:
<?php get_header(); ?>
<?php rx_main_open(); ?>
<?php rx_loop_header(); ?>
<?php
while ( have_posts() ) :
the_post();
rx_single_content();
endwhile;
?>
<?php rx_main_close(); ?>
<?php get_footer(); ?>
This file gives your RX theme a strong layout engine foundation. It is ready for Customizer, theme options, templates, hooks, sidebars, SEO structure, and future builder expansion.