I’ll build this as a full-featured WordPress theme template part for template-parts/content/content-page.php, focused on safe theme functions, accessibility, SEO markup, pagination, edit links, comments support, featured image, breadcrumbs hook compatibility, schema-friendly structure, and extension hooks.
Yes friend — for rx-theme/template-parts/content/content-page.php, you can make it very powerful. This file should mainly display page content, not register theme features. So I added many safe frontend functions: accessibility, schema markup, featured image, page meta, breadcrumbs hook, reading time hook compatibility, share hooks, table of contents hook area, child-page section hook, comments support, edit link, multipage pagination, password-protected handling, and many custom action/filter hooks.
WordPress template parts are designed for reusable theme sections, and functions like the_content(), wp_link_pages(), post_class(), the_post_thumbnail(), and edit_post_link() are standard theme-template tools.
Create this file:
rx-theme/template-parts/content/content-page.php
Then paste this full code:
<?php
/**
* Template part for displaying single Page content.
*
* File: template-parts/content/content-page.php
*
* This file is intentionally advanced but safe:
* - Semantic HTML5 article structure
* - Accessibility-ready skip anchors and ARIA labels
* - Schema.org WebPage / Article-like microdata
* - Featured image support
* - Breadcrumb hook support
* - Reading-time hook support
* - Page meta support
* - Multipage pagination
* - Password protected page handling
* - Comments support
* - Edit link
* - Child page / related content hook areas
* - Social share hook area
* - Table of contents hook area
* - Multiple WordPress filters/actions for future expansion
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
$post_id = get_the_ID();
if ( ! $post_id ) {
return;
}
/**
* Basic page data.
*/
$page_title = get_the_title( $post_id );
$page_permalink = get_permalink( $post_id );
$page_excerpt = has_excerpt( $post_id ) ? get_the_excerpt( $post_id ) : '';
$page_author_id = (int) get_post_field( 'post_author', $post_id );
$page_author_name = $page_author_id ? get_the_author_meta( 'display_name', $page_author_id ) : '';
$page_modified = get_the_modified_time( DATE_W3C, $post_id );
$page_published = get_the_date( DATE_W3C, $post_id );
/**
* Template display options.
* You can control these later from functions.php by using filters.
*/
$rx_show_title = apply_filters( 'rx_theme_content_page_show_title', true, $post_id );
$rx_show_featured_image = apply_filters(
'rx_theme_content_page_show_featured_image',
has_post_thumbnail( $post_id ),
$post_id
);
$rx_show_excerpt = apply_filters(
'rx_theme_content_page_show_excerpt',
! empty( $page_excerpt ),
$post_id
);
$rx_show_meta = apply_filters( 'rx_theme_content_page_show_meta', true, $post_id );
$rx_show_author = apply_filters( 'rx_theme_content_page_show_author', true, $post_id );
$rx_show_dates = apply_filters( 'rx_theme_content_page_show_dates', true, $post_id );
$rx_show_breadcrumbs = apply_filters( 'rx_theme_content_page_show_breadcrumbs', true, $post_id );
$rx_show_toc = apply_filters( 'rx_theme_content_page_show_toc', true, $post_id );
$rx_show_share = apply_filters( 'rx_theme_content_page_show_share', true, $post_id );
$rx_show_child_pages = apply_filters( 'rx_theme_content_page_show_child_pages', true, $post_id );
$rx_show_comments = apply_filters( 'rx_theme_content_page_show_comments', true, $post_id );
$rx_show_edit_link = apply_filters( 'rx_theme_content_page_show_edit_link', true, $post_id );
/**
* CSS class control.
*/
$rx_article_classes = array(
'rx-page',
'rx-page-content',
'rx-entry',
'rx-content-page',
);
if ( is_page_template() ) {
$rx_article_classes[] = 'rx-page-has-template';
}
if ( has_post_thumbnail( $post_id ) ) {
$rx_article_classes[] = 'rx-page-has-thumbnail';
} else {
$rx_article_classes[] = 'rx-page-no-thumbnail';
}
if ( post_password_required( $post_id ) ) {
$rx_article_classes[] = 'rx-page-password-required';
}
$rx_article_classes = apply_filters( 'rx_theme_content_page_article_classes', $rx_article_classes, $post_id );
/**
* Image size.
*/
$rx_featured_image_size = apply_filters( 'rx_theme_content_page_featured_image_size', 'large', $post_id );
/**
* Schema type.
*/
$rx_schema_type = apply_filters( 'rx_theme_content_page_schema_type', 'WebPage', $post_id );
?>
<article
id="post-<?php the_ID(); ?>"
<?php post_class( $rx_article_classes ); ?>
itemscope
itemtype="https://schema.org/<?php echo esc_attr( $rx_schema_type ); ?>"
>
<?php
/**
* Before page article.
*
* Useful for ads, notices, custom hero sections, SEO blocks, etc.
*/
do_action( 'rx_theme_before_content_page_article', $post_id );
?>
<meta itemprop="mainEntityOfPage" content="<?php echo esc_url( $page_permalink ); ?>">
<meta itemprop="url" content="<?php echo esc_url( $page_permalink ); ?>">
<meta itemprop="datePublished" content="<?php echo esc_attr( $page_published ); ?>">
<meta itemprop="dateModified" content="<?php echo esc_attr( $page_modified ); ?>">
<?php if ( $page_author_name ) : ?>
<meta itemprop="author" content="<?php echo esc_attr( $page_author_name ); ?>">
<?php endif; ?>
<?php if ( $rx_show_breadcrumbs ) : ?>
<nav class="rx-page-breadcrumbs" aria-label="<?php echo esc_attr_x( 'Breadcrumb', 'breadcrumb aria label', 'rx-theme' ); ?>">
<?php
/**
* Breadcrumb compatibility.
*
* You can connect your own breadcrumb function in functions.php:
*
* add_action( 'rx_theme_content_page_breadcrumbs', 'rx_theme_breadcrumbs' );
*/
do_action( 'rx_theme_content_page_breadcrumbs', $post_id );
?>
</nav>
<?php endif; ?>
<header class="rx-page-header entry-header">
<?php
/**
* Before page header content.
*/
do_action( 'rx_theme_before_content_page_header', $post_id );
?>
<?php if ( $rx_show_title ) : ?>
<?php
the_title(
'<h1 class="rx-page-title entry-title" itemprop="headline">',
'</h1>'
);
?>
<?php endif; ?>
<?php if ( $rx_show_excerpt && ! post_password_required( $post_id ) ) : ?>
<div class="rx-page-excerpt entry-summary" itemprop="description">
<?php echo wp_kses_post( wpautop( $page_excerpt ) ); ?>
</div>
<?php endif; ?>
<?php if ( $rx_show_meta ) : ?>
<div class="rx-page-meta rx-entry-meta" aria-label="<?php echo esc_attr_x( 'Page information', 'page meta aria label', 'rx-theme' ); ?>">
<?php if ( $rx_show_author && $page_author_name ) : ?>
<span class="rx-page-meta-item rx-page-author vcard">
<span class="rx-page-meta-label">
<?php echo esc_html_x( 'By', 'page author label', 'rx-theme' ); ?>
</span>
<span class="rx-page-meta-value fn" itemprop="author">
<?php echo esc_html( $page_author_name ); ?>
</span>
</span>
<?php endif; ?>
<?php if ( $rx_show_dates ) : ?>
<span class="rx-page-meta-item rx-page-published">
<span class="rx-page-meta-label">
<?php echo esc_html_x( 'Published', 'published date label', 'rx-theme' ); ?>
</span>
<time datetime="<?php echo esc_attr( $page_published ); ?>" itemprop="datePublished">
<?php echo esc_html( get_the_date( '', $post_id ) ); ?>
</time>
</span>
<?php if ( get_the_modified_time( 'U', $post_id ) !== get_the_time( 'U', $post_id ) ) : ?>
<span class="rx-page-meta-item rx-page-updated">
<span class="rx-page-meta-label">
<?php echo esc_html_x( 'Updated', 'updated date label', 'rx-theme' ); ?>
</span>
<time datetime="<?php echo esc_attr( $page_modified ); ?>" itemprop="dateModified">
<?php echo esc_html( get_the_modified_date( '', $post_id ) ); ?>
</time>
</span>
<?php endif; ?>
<?php endif; ?>
<?php
/**
* Reading time or custom meta.
*
* Example:
* add_action( 'rx_theme_content_page_meta', 'rx_theme_reading_time' );
*/
do_action( 'rx_theme_content_page_meta', $post_id );
?>
</div>
<?php endif; ?>
<?php
/**
* After page header content.
*/
do_action( 'rx_theme_after_content_page_header', $post_id );
?>
</header>
<?php if ( $rx_show_featured_image && has_post_thumbnail( $post_id ) && ! post_password_required( $post_id ) ) : ?>
<figure class="rx-page-featured-image post-thumbnail" itemprop="image" itemscope itemtype="https://schema.org/ImageObject">
<?php
echo get_the_post_thumbnail(
$post_id,
$rx_featured_image_size,
array(
'class' => 'rx-page-thumbnail-img',
'loading' => apply_filters( 'rx_theme_content_page_featured_image_loading', 'eager', $post_id ),
'decoding' => 'async',
'alt' => esc_attr( get_post_meta( get_post_thumbnail_id( $post_id ), '_wp_attachment_image_alt', true ) ?: $page_title ),
)
);
$rx_thumbnail_id = get_post_thumbnail_id( $post_id );
$rx_thumbnail_url = $rx_thumbnail_id ? wp_get_attachment_image_url( $rx_thumbnail_id, 'full' ) : '';
if ( $rx_thumbnail_url ) :
?>
<meta itemprop="url" content="<?php echo esc_url( $rx_thumbnail_url ); ?>">
<?php endif; ?>
<?php
$rx_caption = get_the_post_thumbnail_caption( $post_id );
if ( $rx_caption ) :
?>
<figcaption class="rx-page-featured-caption wp-caption-text">
<?php echo wp_kses_post( $rx_caption ); ?>
</figcaption>
<?php endif; ?>
</figure>
<?php endif; ?>
<?php
/**
* Before page body.
*/
do_action( 'rx_theme_before_content_page_body', $post_id );
?>
<?php if ( $rx_show_toc && ! post_password_required( $post_id ) ) : ?>
<aside class="rx-page-toc" aria-label="<?php echo esc_attr_x( 'Table of contents', 'toc aria label', 'rx-theme' ); ?>">
<?php
/**
* Table of contents hook.
*
* Add your TOC function from functions.php or plugin.
*/
do_action( 'rx_theme_content_page_toc', $post_id );
?>
</aside>
<?php endif; ?>
<div class="rx-page-body entry-content" itemprop="text">
<?php
/**
* Before the_content().
*/
do_action( 'rx_theme_before_content_page_content', $post_id );
if ( post_password_required( $post_id ) ) :
?>
<div class="rx-page-password-form">
<?php echo get_the_password_form( $post_id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
<?php
else :
the_content(
sprintf(
wp_kses(
/* translators: %s: Page title. */
__( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'rx-theme' ),
array(
'span' => array(
'class' => array(),
),
)
),
esc_html( $page_title )
)
);
wp_link_pages(
array(
'before' => '<nav class="rx-page-links 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>',
'next_or_number' => 'number',
'separator' => '<span class="rx-page-links-separator"> </span>',
'pagelink' => '<span class="screen-reader-text">' . esc_html__( 'Page', 'rx-theme' ) . ' </span>%',
'echo' => 1,
)
);
endif;
/**
* After the_content().
*/
do_action( 'rx_theme_after_content_page_content', $post_id );
?>
</div>
<?php if ( ! post_password_required( $post_id ) ) : ?>
<?php if ( $rx_show_share ) : ?>
<section class="rx-page-share" aria-label="<?php echo esc_attr_x( 'Share this page', 'share section aria label', 'rx-theme' ); ?>">
<?php
/**
* Social share hook.
*
* You can add custom social share buttons here.
*/
do_action( 'rx_theme_content_page_share', $post_id );
?>
</section>
<?php endif; ?>
<?php if ( $rx_show_child_pages ) : ?>
<section class="rx-page-child-pages" aria-label="<?php echo esc_attr_x( 'Related child pages', 'child pages aria label', 'rx-theme' ); ?>">
<?php
/**
* Child pages hook.
*
* You can connect a function that lists child pages.
*/
do_action( 'rx_theme_content_page_child_pages', $post_id );
?>
</section>
<?php endif; ?>
<?php endif; ?>
<footer class="rx-page-footer entry-footer">
<?php
/**
* Before footer area.
*/
do_action( 'rx_theme_before_content_page_footer', $post_id );
?>
<?php if ( $rx_show_edit_link ) : ?>
<?php
edit_post_link(
sprintf(
wp_kses(
/* translators: %s: Page title. */
__( 'Edit <span class="screen-reader-text">%s</span>', 'rx-theme' ),
array(
'span' => array(
'class' => array(),
),
)
),
esc_html( $page_title )
),
'<span class="rx-edit-link edit-link">',
'</span>'
);
?>
<?php endif; ?>
<?php
/**
* After footer area.
*/
do_action( 'rx_theme_after_content_page_footer', $post_id );
?>
</footer>
<?php
/**
* After page article.
*/
do_action( 'rx_theme_after_content_page_article', $post_id );
?>
</article>
<?php
/**
* Comments area.
*
* Page comments are shown only when comments are open or when the page already has comments.
*/
if (
$rx_show_comments
&& ! post_password_required( $post_id )
&& ( comments_open( $post_id ) || get_comments_number( $post_id ) )
) :
?>
<section class="rx-page-comments-area" id="comments-area" aria-label="<?php echo esc_attr_x( 'Page comments', 'comments area aria label', 'rx-theme' ); ?>">
<?php comments_template(); ?>
</section>
<?php
endif;
Add this optional CSS to style.css:
/* RX Page Content Template */
.rx-page {
width: 100%;
max-width: var(--rx-content-width, 920px);
margin-inline: auto;
padding-inline: var(--rx-content-padding, 1rem);
}
.rx-page-header {
margin-bottom: 2rem;
}
.rx-page-title {
margin: 0 0 1rem;
line-height: 1.15;
}
.rx-page-excerpt {
font-size: 1.125rem;
line-height: 1.7;
opacity: 0.85;
margin-bottom: 1rem;
}
.rx-page-meta {
display: flex;
flex-wrap: wrap;
gap: 0.75rem 1.25rem;
font-size: 0.9375rem;
opacity: 0.8;
margin-bottom: 1.5rem;
}
.rx-page-meta-label {
font-weight: 600;
margin-right: 0.25rem;
}
.rx-page-featured-image {
margin: 0 0 2rem;
}
.rx-page-thumbnail-img {
display: block;
width: 100%;
height: auto;
border-radius: var(--rx-radius-lg, 16px);
}
.rx-page-featured-caption {
margin-top: 0.5rem;
font-size: 0.875rem;
opacity: 0.75;
text-align: center;
}
.rx-page-body {
line-height: 1.8;
}
.rx-page-body > *:first-child {
margin-top: 0;
}
.rx-page-body img {
max-width: 100%;
height: auto;
}
.rx-page-body iframe,
.rx-page-body video {
max-width: 100%;
}
.rx-page-links {
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px solid currentColor;
}
.rx-page-links-title {
font-weight: 700;
margin-right: 0.75rem;
}
.rx-page-link-number {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2rem;
min-height: 2rem;
padding: 0.25rem 0.5rem;
border: 1px solid currentColor;
border-radius: 999px;
text-decoration: none;
}
.rx-page-share,
.rx-page-child-pages,
.rx-page-footer,
.rx-page-comments-area {
margin-top: 2rem;
}
.rx-edit-link a {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-weight: 600;
}
.screen-reader-text {
position: absolute !important;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
Example use in page.php:
<?php
/**
* Page template.
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
get_header();
?>
<main id="primary" class="site-main rx-site-main">
<?php
while ( have_posts() ) :
the_post();
get_template_part( 'template-parts/content/content', 'page' );
endwhile;
?>
</main>
<?php
get_footer();
This is a strong advanced content-page.php, but keep heavy logic like sitemap, cache, preload, SEO meta registration, scripts, menus, sidebars, and image sizes inside functions.php or files inside inc/. This template part should stay focused on displaying page content cleanly.