I’ll build this as an advanced WordPress page.php template for your RX Theme, with SEO-friendly structure, accessibility, breadcrumbs, featured image, TOC, child pages, pagination, comments, schema hooks, and safe fallbacks.
Below is an advanced page.php for your RX Theme. It is safe, SEO-friendly, accessible, and includes many possible page-template features with fallback checks so it will not break if some helper functions do not exist.
Create this file here:
rx-theme/page.php
Then paste this code:
<?php
/**
* The template for displaying all static pages.
*
* File: page.php
*
* RX Theme Advanced Page Template
*
* Features included:
* - Secure direct-access protection
* - Header and footer loading
* - Schema-ready wrapper
* - Skip link friendly structure
* - Breadcrumb support
* - Hero section
* - Featured image support
* - Page title
* - Subtitle/excerpt support
* - Author/date modified meta option
* - Reading time support
* - Table of contents support
* - Main page content
* - Page pagination
* - Child pages listing
* - Related pages/posts support
* - Previous/next page navigation
* - Comments support
* - Sidebar support
* - Edit link for admins
* - Hooks for future extension
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
get_header();
/**
* Helpful variables.
*/
$rx_page_id = get_the_ID();
$rx_show_sidebar = is_active_sidebar( 'sidebar-page' );
$rx_has_thumbnail = has_post_thumbnail();
$rx_page_classes = array( 'rx-page-template', 'rx-page-single' );
$rx_container_class = $rx_show_sidebar ? 'rx-container rx-layout rx-layout-sidebar' : 'rx-container rx-layout rx-layout-full';
/**
* Add custom body-like classes for the page wrapper.
*/
if ( $rx_has_thumbnail ) {
$rx_page_classes[] = 'rx-page-has-thumbnail';
} else {
$rx_page_classes[] = 'rx-page-no-thumbnail';
}
if ( $rx_show_sidebar ) {
$rx_page_classes[] = 'rx-page-with-sidebar';
} else {
$rx_page_classes[] = 'rx-page-no-sidebar';
}
/**
* Optional custom page settings.
*
* You can later create these custom fields:
* - rx_hide_page_title = 1
* - rx_hide_featured_image = 1
* - rx_show_page_meta = 1
* - rx_show_child_pages = 1
* - rx_show_related_content = 1
* - rx_page_subtitle = custom subtitle text
*/
$rx_hide_title = get_post_meta( $rx_page_id, 'rx_hide_page_title', true );
$rx_hide_featured_image = get_post_meta( $rx_page_id, 'rx_hide_featured_image', true );
$rx_show_page_meta = get_post_meta( $rx_page_id, 'rx_show_page_meta', true );
$rx_show_child_pages = get_post_meta( $rx_page_id, 'rx_show_child_pages', true );
$rx_show_related = get_post_meta( $rx_page_id, 'rx_show_related_content', true );
$rx_custom_subtitle = get_post_meta( $rx_page_id, 'rx_page_subtitle', true );
/**
* RX before page hook.
*/
do_action( 'rx_before_page_template' );
?>
<main id="primary" class="<?php echo esc_attr( implode( ' ', $rx_page_classes ) ); ?>" role="main">
<?php
/**
* RX before page main hook.
*/
do_action( 'rx_before_page_main' );
?>
<?php if ( function_exists( 'rx_breadcrumbs' ) ) : ?>
<section class="rx-breadcrumb-section" aria-label="<?php esc_attr_e( 'Breadcrumb', 'rx-theme' ); ?>">
<div class="rx-container">
<?php rx_breadcrumbs(); ?>
</div>
</section>
<?php endif; ?>
<?php while ( have_posts() ) : ?>
<?php the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class( 'rx-page-article' ); ?> itemscope itemtype="https://schema.org/WebPage">
<?php
/**
* RX before page article hook.
*/
do_action( 'rx_before_page_article', $rx_page_id );
?>
<header class="rx-page-header">
<div class="rx-container">
<?php if ( empty( $rx_hide_title ) ) : ?>
<div class="rx-page-title-wrap">
<?php
/**
* Optional parent page label.
*/
$rx_parent_id = wp_get_post_parent_id( $rx_page_id );
if ( $rx_parent_id ) :
?>
<p class="rx-page-parent-label">
<a href="<?php echo esc_url( get_permalink( $rx_parent_id ) ); ?>">
<?php echo esc_html( get_the_title( $rx_parent_id ) ); ?>
</a>
</p>
<?php endif; ?>
<h1 class="rx-page-title" itemprop="headline">
<?php the_title(); ?>
</h1>
<?php if ( ! empty( $rx_custom_subtitle ) ) : ?>
<p class="rx-page-subtitle">
<?php echo esc_html( $rx_custom_subtitle ); ?>
</p>
<?php elseif ( has_excerpt() ) : ?>
<p class="rx-page-subtitle" itemprop="description">
<?php echo esc_html( get_the_excerpt() ); ?>
</p>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ( ! empty( $rx_show_page_meta ) ) : ?>
<div class="rx-page-meta" aria-label="<?php esc_attr_e( 'Page information', 'rx-theme' ); ?>">
<span class="rx-page-meta-item rx-page-author">
<?php esc_html_e( 'By', 'rx-theme' ); ?>
<a href="<?php echo esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ); ?>" rel="author">
<?php echo esc_html( get_the_author() ); ?>
</a>
</span>
<span class="rx-page-meta-item rx-page-updated">
<?php esc_html_e( 'Updated:', 'rx-theme' ); ?>
<time datetime="<?php echo esc_attr( get_the_modified_date( DATE_W3C ) ); ?>" itemprop="dateModified">
<?php echo esc_html( get_the_modified_date() ); ?>
</time>
</span>
<?php if ( function_exists( 'rx_reading_time' ) ) : ?>
<span class="rx-page-meta-item rx-page-reading-time">
<?php echo esc_html( rx_reading_time( $rx_page_id ) ); ?>
</span>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
</header>
<?php if ( $rx_has_thumbnail && empty( $rx_hide_featured_image ) ) : ?>
<section class="rx-page-featured-image-section">
<div class="rx-container">
<figure class="rx-page-featured-image">
<?php
the_post_thumbnail(
'full',
array(
'class' => 'rx-page-thumbnail-img',
'loading' => 'eager',
'decoding' => 'async',
'itemprop' => 'primaryImageOfPage',
)
);
?>
<?php
$rx_thumbnail_caption = wp_get_attachment_caption( get_post_thumbnail_id() );
if ( ! empty( $rx_thumbnail_caption ) ) :
?>
<figcaption class="rx-page-featured-caption">
<?php echo wp_kses_post( $rx_thumbnail_caption ); ?>
</figcaption>
<?php endif; ?>
</figure>
</div>
</section>
<?php endif; ?>
<div class="<?php echo esc_attr( $rx_container_class ); ?>">
<section class="rx-page-content-area">
<?php
/**
* RX before page content hook.
*/
do_action( 'rx_before_page_content', $rx_page_id );
?>
<?php if ( function_exists( 'rx_table_of_contents' ) ) : ?>
<aside class="rx-page-toc" aria-label="<?php esc_attr_e( 'Table of contents', 'rx-theme' ); ?>">
<?php rx_table_of_contents(); ?>
</aside>
<?php endif; ?>
<div class="rx-page-content entry-content" itemprop="mainContentOfPage">
<?php
the_content();
wp_link_pages(
array(
'before' => '<nav class="rx-page-links" aria-label="' . esc_attr__( 'Page navigation', 'rx-theme' ) . '"><span class="rx-page-links-title">' . esc_html__( 'Pages:', 'rx-theme' ) . '</span>',
'after' => '</nav>',
'link_before' => '<span class="rx-page-link-number">',
'link_after' => '</span>',
)
);
?>
</div>
<?php
/**
* Admin edit link.
*/
edit_post_link(
esc_html__( 'Edit this page', 'rx-theme' ),
'<div class="rx-edit-link">',
'</div>'
);
?>
<?php
/**
* Child pages section.
*/
$rx_child_pages = new WP_Query(
array(
'post_type' => 'page',
'post_parent' => $rx_page_id,
'posts_per_page' => 12,
'orderby' => 'menu_order title',
'order' => 'ASC',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
)
);
if ( ! empty( $rx_show_child_pages ) && $rx_child_pages->have_posts() ) :
?>
<section class="rx-child-pages-section" aria-labelledby="rx-child-pages-title">
<h2 id="rx-child-pages-title" class="rx-section-title">
<?php esc_html_e( 'Explore More Pages', 'rx-theme' ); ?>
</h2>
<div class="rx-child-pages-grid">
<?php while ( $rx_child_pages->have_posts() ) : ?>
<?php $rx_child_pages->the_post(); ?>
<article id="child-page-<?php the_ID(); ?>" <?php post_class( 'rx-child-page-card' ); ?>>
<?php if ( has_post_thumbnail() ) : ?>
<a class="rx-child-page-thumb-link" href="<?php the_permalink(); ?>" aria-label="<?php the_title_attribute(); ?>">
<?php
the_post_thumbnail(
'medium_large',
array(
'class' => 'rx-child-page-thumb',
'loading' => 'lazy',
'decoding' => 'async',
)
);
?>
</a>
<?php endif; ?>
<div class="rx-child-page-card-body">
<h3 class="rx-child-page-title">
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</h3>
<?php if ( has_excerpt() ) : ?>
<p class="rx-child-page-excerpt">
<?php echo esc_html( wp_trim_words( get_the_excerpt(), 24, '...' ) ); ?>
</p>
<?php endif; ?>
<a class="rx-read-more-link" href="<?php the_permalink(); ?>">
<?php esc_html_e( 'Read more', 'rx-theme' ); ?>
<span aria-hidden="true">→</span>
</a>
</div>
</article>
<?php endwhile; ?>
</div>
</section>
<?php
wp_reset_postdata();
endif;
?>
<?php
/**
* Related content section.
*
* If your helper function exists, it will run.
* Otherwise a fallback section will show recent pages.
*/
if ( ! empty( $rx_show_related ) ) :
?>
<section class="rx-related-pages-section" aria-labelledby="rx-related-pages-title">
<h2 id="rx-related-pages-title" class="rx-section-title">
<?php esc_html_e( 'Related Information', 'rx-theme' ); ?>
</h2>
<?php if ( function_exists( 'rx_related_posts' ) ) : ?>
<?php rx_related_posts( $rx_page_id ); ?>
<?php else : ?>
<?php
$rx_related_pages = new WP_Query(
array(
'post_type' => 'page',
'post__not_in' => array( $rx_page_id ),
'posts_per_page' => 6,
'orderby' => 'modified',
'order' => 'DESC',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
)
);
if ( $rx_related_pages->have_posts() ) :
?>
<div class="rx-related-pages-grid">
<?php while ( $rx_related_pages->have_posts() ) : ?>
<?php $rx_related_pages->the_post(); ?>
<article id="related-page-<?php the_ID(); ?>" <?php post_class( 'rx-related-page-card' ); ?>>
<h3 class="rx-related-page-title">
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</h3>
<?php if ( has_excerpt() ) : ?>
<p class="rx-related-page-excerpt">
<?php echo esc_html( wp_trim_words( get_the_excerpt(), 22, '...' ) ); ?>
</p>
<?php endif; ?>
</article>
<?php endwhile; ?>
</div>
<?php
wp_reset_postdata();
endif;
?>
<?php endif; ?>
</section>
<?php endif; ?>
<?php
/**
* Previous / next navigation.
*
* Pages usually do not use category navigation like posts,
* so this uses parent/child/sibling page logic when available.
*/
$rx_sibling_args = array(
'post_type' => 'page',
'post_parent' => wp_get_post_parent_id( $rx_page_id ),
'posts_per_page' => -1,
'orderby' => 'menu_order title',
'order' => 'ASC',
'fields' => 'ids',
);
$rx_sibling_pages = get_posts( $rx_sibling_args );
$rx_current_index = array_search( $rx_page_id, $rx_sibling_pages, true );
$rx_prev_page_id = false;
$rx_next_page_id = false;
if ( false !== $rx_current_index ) {
$rx_prev_page_id = isset( $rx_sibling_pages[ $rx_current_index - 1 ] ) ? $rx_sibling_pages[ $rx_current_index - 1 ] : false;
$rx_next_page_id = isset( $rx_sibling_pages[ $rx_current_index + 1 ] ) ? $rx_sibling_pages[ $rx_current_index + 1 ] : false;
}
if ( $rx_prev_page_id || $rx_next_page_id ) :
?>
<nav class="rx-page-navigation" aria-label="<?php esc_attr_e( 'Page navigation', 'rx-theme' ); ?>">
<?php if ( $rx_prev_page_id ) : ?>
<div class="rx-page-nav-item rx-page-nav-prev">
<span class="rx-page-nav-label">
<?php esc_html_e( 'Previous Page', 'rx-theme' ); ?>
</span>
<a href="<?php echo esc_url( get_permalink( $rx_prev_page_id ) ); ?>">
<?php echo esc_html( get_the_title( $rx_prev_page_id ) ); ?>
</a>
</div>
<?php endif; ?>
<?php if ( $rx_next_page_id ) : ?>
<div class="rx-page-nav-item rx-page-nav-next">
<span class="rx-page-nav-label">
<?php esc_html_e( 'Next Page', 'rx-theme' ); ?>
</span>
<a href="<?php echo esc_url( get_permalink( $rx_next_page_id ) ); ?>">
<?php echo esc_html( get_the_title( $rx_next_page_id ) ); ?>
</a>
</div>
<?php endif; ?>
</nav>
<?php endif; ?>
<?php
/**
* RX after page content hook.
*/
do_action( 'rx_after_page_content', $rx_page_id );
?>
<?php
/**
* Comments section.
*/
if ( comments_open() || get_comments_number() ) :
comments_template();
endif;
?>
</section>
<?php if ( $rx_show_sidebar ) : ?>
<aside id="secondary" class="rx-page-sidebar widget-area" role="complementary" aria-label="<?php esc_attr_e( 'Page sidebar', 'rx-theme' ); ?>">
<?php dynamic_sidebar( 'sidebar-page' ); ?>
</aside>
<?php endif; ?>
</div>
<?php
/**
* JSON-LD schema fallback.
*
* If you already have a full schema system in inc/helpers/schema.php,
* you may remove this block or replace it with your own helper.
*/
if ( ! function_exists( 'rx_schema_webpage_output' ) ) :
$rx_schema_image = $rx_has_thumbnail ? get_the_post_thumbnail_url( $rx_page_id, 'full' ) : '';
$rx_schema_data = array(
'@context' => 'https://schema.org',
'@type' => 'WebPage',
'@id' => esc_url_raw( get_permalink() ) . '#webpage',
'url' => esc_url_raw( get_permalink() ),
'name' => wp_strip_all_tags( get_the_title() ),
'description' => wp_strip_all_tags( get_the_excerpt() ),
'inLanguage' => get_bloginfo( 'language' ),
'isPartOf' => array(
'@type' => 'WebSite',
'name' => get_bloginfo( 'name' ),
'url' => esc_url_raw( home_url( '/' ) ),
),
'datePublished' => get_the_date( DATE_W3C ),
'dateModified' => get_the_modified_date( DATE_W3C ),
);
if ( ! empty( $rx_schema_image ) ) {
$rx_schema_data['primaryImageOfPage'] = array(
'@type' => 'ImageObject',
'url' => esc_url_raw( $rx_schema_image ),
);
}
?>
<script type="application/ld+json">
<?php echo wp_json_encode( $rx_schema_data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT ); ?>
</script>
<?php endif; ?>
<?php
/**
* RX after page article hook.
*/
do_action( 'rx_after_page_article', $rx_page_id );
?>
</article>
<?php endwhile; ?>
<?php
/**
* RX after page main hook.
*/
do_action( 'rx_after_page_main' );
?>
</main>
<?php
/**
* RX after page template hook.
*/
do_action( 'rx_after_page_template' );
get_footer();
Optional sidebar registration for functions.php
Because this page.php supports a page sidebar named sidebar-page, add this in your sidebar registration file or functions.php if you have not already added it:
function rx_register_page_sidebar() {
register_sidebar(
array(
'name' => esc_html__( 'Page Sidebar', 'rx-theme' ),
'id' => 'sidebar-page',
'description' => esc_html__( 'Widgets added here will appear on static pages.', 'rx-theme' ),
'before_widget' => '<section id="%1$s" class="widget rx-widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title rx-widget-title">',
'after_title' => '</h2>',
)
);
}
add_action( 'widgets_init', 'rx_register_page_sidebar' );
Optional CSS for style.css
.rx-container {
width: min(1200px, calc(100% - 32px));
margin-inline: auto;
}
.rx-layout {
display: grid;
gap: 32px;
}
.rx-layout-sidebar {
grid-template-columns: minmax(0, 1fr) 320px;
align-items: start;
}
.rx-layout-full {
grid-template-columns: minmax(0, 1fr);
}
.rx-page-header {
padding: 48px 0 24px;
}
.rx-page-title {
margin: 0;
font-size: clamp(2rem, 4vw, 4rem);
line-height: 1.1;
}
.rx-page-subtitle {
margin-top: 16px;
max-width: 760px;
font-size: 1.15rem;
line-height: 1.7;
opacity: 0.85;
}
.rx-page-parent-label {
margin-bottom: 10px;
font-weight: 600;
}
.rx-page-meta {
display: flex;
flex-wrap: wrap;
gap: 12px 20px;
margin-top: 18px;
font-size: 0.95rem;
opacity: 0.85;
}
.rx-page-featured-image-section {
margin-bottom: 32px;
}
.rx-page-featured-image {
margin: 0;
}
.rx-page-thumbnail-img {
width: 100%;
height: auto;
border-radius: 18px;
display: block;
}
.rx-page-featured-caption {
margin-top: 10px;
font-size: 0.9rem;
text-align: center;
opacity: 0.75;
}
.rx-page-content-area {
min-width: 0;
}
.rx-page-content {
font-size: 1.05rem;
line-height: 1.8;
}
.rx-page-content img {
max-width: 100%;
height: auto;
}
.rx-page-content h2,
.rx-page-content h3,
.rx-page-content h4 {
scroll-margin-top: 100px;
}
.rx-page-toc {
padding: 20px;
margin-bottom: 28px;
border: 1px solid rgba(0,0,0,0.08);
border-radius: 16px;
background: rgba(0,0,0,0.02);
}
.rx-page-links {
margin-top: 28px;
padding-top: 20px;
border-top: 1px solid rgba(0,0,0,0.08);
}
.rx-page-link-number {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 34px;
height: 34px;
margin: 4px;
border-radius: 999px;
border: 1px solid rgba(0,0,0,0.15);
}
.rx-child-pages-section,
.rx-related-pages-section {
margin-top: 48px;
}
.rx-section-title {
margin-bottom: 20px;
font-size: 1.7rem;
}
.rx-child-pages-grid,
.rx-related-pages-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 24px;
}
.rx-child-page-card,
.rx-related-page-card {
padding: 20px;
border: 1px solid rgba(0,0,0,0.08);
border-radius: 18px;
background: #fff;
}
.rx-child-page-thumb {
width: 100%;
height: auto;
border-radius: 14px;
margin-bottom: 14px;
}
.rx-child-page-title,
.rx-related-page-title {
margin-top: 0;
font-size: 1.2rem;
line-height: 1.35;
}
.rx-read-more-link {
display: inline-flex;
gap: 6px;
align-items: center;
font-weight: 700;
text-decoration: none;
}
.rx-page-navigation {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 20px;
margin-top: 48px;
padding-top: 28px;
border-top: 1px solid rgba(0,0,0,0.08);
}
.rx-page-nav-item {
padding: 18px;
border-radius: 16px;
border: 1px solid rgba(0,0,0,0.08);
}
.rx-page-nav-next {
text-align: right;
}
.rx-page-nav-label {
display: block;
margin-bottom: 6px;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.04em;
opacity: 0.7;
}
.rx-edit-link {
margin-top: 32px;
}
.rx-page-sidebar {
padding: 24px;
border-radius: 18px;
border: 1px solid rgba(0,0,0,0.08);
background: rgba(0,0,0,0.02);
}
@media (max-width: 900px) {
.rx-layout-sidebar {
grid-template-columns: 1fr;
}
.rx-child-pages-grid,
.rx-related-pages-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 600px) {
.rx-child-pages-grid,
.rx-related-pages-grid,
.rx-page-navigation {
grid-template-columns: 1fr;
}
.rx-page-nav-next {
text-align: left;
}
}
Important custom field controls
This page.php supports these optional custom fields:
rx_hide_page_title
rx_hide_featured_image
rx_show_page_meta
rx_show_child_pages
rx_show_related_content
rx_page_subtitle
Example values:
rx_show_child_pages = 1
rx_show_related_content = 1
rx_show_page_meta = 1
rx_hide_page_title = 1
rx_hide_featured_image = 1
rx_page_subtitle = Your custom subtitle here
This is a strong advanced page.php base for your RX Theme. It will work now, and later you can connect it with your helper files like:
inc/helpers/breadcrumbs.php
inc/helpers/reading-time.php
inc/helpers/related-posts.php
inc/helpers/schema.php
inc/helpers/table-of-contents.php