template-review-board.php

I’ll build this as a full advanced WordPress page template for RX Theme: security checks, custom query support, filters, schema JSON-LD, review-board cards, search/filter UI, pagination, accessibility, and fallback content.

Friend, create this file:

rx-theme/templates/template-review-board.php

This is an advanced self-contained Review Board page template for RX Theme. It supports:

Review board member listing, search, specialty filter, designation filter, country filter, sorting, pagination, verified/active badge, schema JSON-LD, accessibility, security escaping, shortcode support, reusable hooks, fallback demo content, responsive HTML structure, and SEO-friendly medical review board layout.

<?php
/**
 * Template Name: RX Review Board
 * Template Post Type: page
 *
 * Advanced Review Board Template for RX Theme.
 *
 * Location:
 * /templates/template-review-board.php
 *
 * Recommended Custom Post Type:
 * review_board
 *
 * Supported custom fields:
 * - rxrb_full_name
 * - rxrb_designation
 * - rxrb_specialty
 * - rxrb_country
 * - rxrb_institution
 * - rxrb_qualification
 * - rxrb_experience
 * - rxrb_profile_url
 * - rxrb_orcid
 * - rxrb_google_scholar
 * - rxrb_pubmed
 * - rxrb_verified
 * - rxrb_status
 * - rxrb_review_count
 * - rxrb_last_reviewed
 * - rxrb_short_bio
 *
 * @package RX_Theme
 */

defined( 'ABSPATH' ) || exit;

get_header();

/**
 * ------------------------------------------------------------
 * RX Review Board Helper Functions
 * ------------------------------------------------------------
 */

if ( ! function_exists( 'rx_review_board_get_meta' ) ) {
	/**
	 * Safe post meta getter.
	 *
	 * @param int    $post_id Post ID.
	 * @param string $key     Meta key.
	 * @param string $default Default value.
	 * @return string
	 */
	function rx_review_board_get_meta( $post_id, $key, $default = '' ) {
		$value = get_post_meta( $post_id, $key, true );

		if ( is_array( $value ) ) {
			$value = implode( ', ', array_map( 'sanitize_text_field', $value ) );
		}

		if ( '' === $value || null === $value ) {
			return $default;
		}

		return sanitize_text_field( wp_unslash( $value ) );
	}
}

if ( ! function_exists( 'rx_review_board_bool_meta' ) ) {
	/**
	 * Convert meta value to boolean.
	 *
	 * @param int    $post_id Post ID.
	 * @param string $key     Meta key.
	 * @return bool
	 */
	function rx_review_board_bool_meta( $post_id, $key ) {
		$value = get_post_meta( $post_id, $key, true );

		return in_array( strtolower( (string) $value ), array( '1', 'yes', 'true', 'on', 'verified', 'active' ), true );
	}
}

if ( ! function_exists( 'rx_review_board_get_field_options' ) ) {
	/**
	 * Collect unique meta values for filter dropdown.
	 *
	 * @param string $meta_key Meta key.
	 * @return array
	 */
	function rx_review_board_get_field_options( $meta_key ) {
		global $wpdb;

		$cache_key = 'rxrb_options_' . md5( $meta_key );
		$cached    = get_transient( $cache_key );

		if ( false !== $cached ) {
			return $cached;
		}

		$values = $wpdb->get_col(
			$wpdb->prepare(
				"
				SELECT DISTINCT meta_value
				FROM {$wpdb->postmeta}
				INNER JOIN {$wpdb->posts}
					ON {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID
				WHERE meta_key = %s
					AND post_type = 'review_board'
					AND post_status = 'publish'
					AND meta_value != ''
				ORDER BY meta_value ASC
				",
				$meta_key
			)
		);

		$clean_values = array();

		if ( ! empty( $values ) ) {
			foreach ( $values as $value ) {
				$value = sanitize_text_field( $value );

				if ( ! empty( $value ) ) {
					$clean_values[] = $value;
				}
			}
		}

		$clean_values = array_unique( $clean_values );

		set_transient( $cache_key, $clean_values, HOUR_IN_SECONDS );

		return $clean_values;
	}
}

if ( ! function_exists( 'rx_review_board_get_current_url' ) ) {
	/**
	 * Current page URL without unsafe input.
	 *
	 * @return string
	 */
	function rx_review_board_get_current_url() {
		global $wp;

		$current_url = home_url( add_query_arg( array(), $wp->request ) );

		return esc_url( $current_url );
	}
}

if ( ! function_exists( 'rx_review_board_get_sort_args' ) ) {
	/**
	 * Sorting arguments.
	 *
	 * @param string $sort Sort value.
	 * @return array
	 */
	function rx_review_board_get_sort_args( $sort ) {
		$args = array(
			'orderby' => 'title',
			'order'   => 'ASC',
		);

		switch ( $sort ) {
			case 'name_desc':
				$args['orderby'] = 'title';
				$args['order']   = 'DESC';
				break;

			case 'experience_high':
				$args['meta_key'] = 'rxrb_experience';
				$args['orderby']  = 'meta_value_num';
				$args['order']    = 'DESC';
				break;

			case 'review_count_high':
				$args['meta_key'] = 'rxrb_review_count';
				$args['orderby']  = 'meta_value_num';
				$args['order']    = 'DESC';
				break;

			case 'recent_reviewed':
				$args['meta_key'] = 'rxrb_last_reviewed';
				$args['orderby']  = 'meta_value';
				$args['order']    = 'DESC';
				break;

			case 'name_asc':
			default:
				$args['orderby'] = 'title';
				$args['order']   = 'ASC';
				break;
		}

		return $args;
	}
}

if ( ! function_exists( 'rx_review_board_get_member_schema' ) ) {
	/**
	 * Person schema for one member.
	 *
	 * @param int $post_id Post ID.
	 * @return array
	 */
	function rx_review_board_get_member_schema( $post_id ) {
		$name          = rx_review_board_get_meta( $post_id, 'rxrb_full_name', get_the_title( $post_id ) );
		$designation   = rx_review_board_get_meta( $post_id, 'rxrb_designation' );
		$specialty     = rx_review_board_get_meta( $post_id, 'rxrb_specialty' );
		$country       = rx_review_board_get_meta( $post_id, 'rxrb_country' );
		$institution   = rx_review_board_get_meta( $post_id, 'rxrb_institution' );
		$profile_url   = rx_review_board_get_meta( $post_id, 'rxrb_profile_url', get_permalink( $post_id ) );
		$image         = get_the_post_thumbnail_url( $post_id, 'full' );
		$same_as       = array();
		$orcid         = rx_review_board_get_meta( $post_id, 'rxrb_orcid' );
		$google        = rx_review_board_get_meta( $post_id, 'rxrb_google_scholar' );
		$pubmed        = rx_review_board_get_meta( $post_id, 'rxrb_pubmed' );

		foreach ( array( $orcid, $google, $pubmed ) as $url ) {
			if ( ! empty( $url ) && filter_var( $url, FILTER_VALIDATE_URL ) ) {
				$same_as[] = esc_url_raw( $url );
			}
		}

		$schema = array(
			'@type'       => 'Person',
			'name'        => $name,
			'url'         => esc_url_raw( $profile_url ),
			'jobTitle'    => $designation,
			'description' => $specialty,
		);

		if ( $image ) {
			$schema['image'] = esc_url_raw( $image );
		}

		if ( $country ) {
			$schema['nationality'] = $country;
		}

		if ( $institution ) {
			$schema['affiliation'] = array(
				'@type' => 'Organization',
				'name'  => $institution,
			);
		}

		if ( ! empty( $same_as ) ) {
			$schema['sameAs'] = $same_as;
		}

		return array_filter( $schema );
	}
}

if ( ! function_exists( 'rx_review_board_demo_members' ) ) {
	/**
	 * Fallback members when CPT has no content.
	 *
	 * @return array
	 */
	function rx_review_board_demo_members() {
		return array(
			array(
				'name'          => 'Medical Review Board Member',
				'designation'   => 'Consultant Physician',
				'specialty'     => 'Internal Medicine',
				'country'       => 'Global',
				'institution'   => 'RX Medical Knowledge Network',
				'qualification' => 'MBBS, MD',
				'experience'    => '10+ years',
				'bio'           => 'This sample profile appears because no review board member has been added yet. Add members using the review_board custom post type or connect this template with your own custom fields.',
				'verified'      => true,
			),
			array(
				'name'          => 'Clinical Content Reviewer',
				'designation'   => 'Specialist Doctor',
				'specialty'     => 'Evidence-Based Medicine',
				'country'       => 'Global',
				'institution'   => 'RX Health Editorial System',
				'qualification' => 'Clinical reviewer',
				'experience'    => '8+ years',
				'bio'           => 'This placeholder helps your layout stay beautiful while you are building your real review board database.',
				'verified'      => true,
			),
		);
	}
}

/**
 * ------------------------------------------------------------
 * Query Variables
 * ------------------------------------------------------------
 */

$paged = max(
	1,
	get_query_var( 'paged' ) ? absint( get_query_var( 'paged' ) ) : absint( filter_input( INPUT_GET, 'rxrb_page', FILTER_SANITIZE_NUMBER_INT ) )
);

$search_query = isset( $_GET['rxrb_search'] )
	? sanitize_text_field( wp_unslash( $_GET['rxrb_search'] ) )
	: '';

$specialty_filter = isset( $_GET['rxrb_specialty'] )
	? sanitize_text_field( wp_unslash( $_GET['rxrb_specialty'] ) )
	: '';

$designation_filter = isset( $_GET['rxrb_designation'] )
	? sanitize_text_field( wp_unslash( $_GET['rxrb_designation'] ) )
	: '';

$country_filter = isset( $_GET['rxrb_country'] )
	? sanitize_text_field( wp_unslash( $_GET['rxrb_country'] ) )
	: '';

$status_filter = isset( $_GET['rxrb_status'] )
	? sanitize_text_field( wp_unslash( $_GET['rxrb_status'] ) )
	: '';

$sort = isset( $_GET['rxrb_sort'] )
	? sanitize_key( wp_unslash( $_GET['rxrb_sort'] ) )
	: 'name_asc';

$posts_per_page = apply_filters( 'rx_review_board_posts_per_page', 12 );

$meta_query = array(
	'relation' => 'AND',
);

if ( ! empty( $specialty_filter ) ) {
	$meta_query[] = array(
		'key'     => 'rxrb_specialty',
		'value'   => $specialty_filter,
		'compare' => '=',
	);
}

if ( ! empty( $designation_filter ) ) {
	$meta_query[] = array(
		'key'     => 'rxrb_designation',
		'value'   => $designation_filter,
		'compare' => '=',
	);
}

if ( ! empty( $country_filter ) ) {
	$meta_query[] = array(
		'key'     => 'rxrb_country',
		'value'   => $country_filter,
		'compare' => '=',
	);
}

if ( 'verified' === $status_filter ) {
	$meta_query[] = array(
		'key'     => 'rxrb_verified',
		'value'   => array( '1', 'yes', 'true', 'verified' ),
		'compare' => 'IN',
	);
}

$sort_args = rx_review_board_get_sort_args( $sort );

$query_args = array(
	'post_type'           => 'review_board',
	'post_status'         => 'publish',
	'posts_per_page'      => $posts_per_page,
	'paged'               => $paged,
	's'                   => $search_query,
	'ignore_sticky_posts' => true,
	'no_found_rows'       => false,
);

if ( count( $meta_query ) > 1 ) {
	$query_args['meta_query'] = $meta_query;
}

$query_args = array_merge( $query_args, $sort_args );

$query_args = apply_filters( 'rx_review_board_query_args', $query_args );

$rx_review_board_query = new WP_Query( $query_args );

$specialty_options   = rx_review_board_get_field_options( 'rxrb_specialty' );
$designation_options = rx_review_board_get_field_options( 'rxrb_designation' );
$country_options     = rx_review_board_get_field_options( 'rxrb_country' );

$schema_members = array();

?>

<main id="primary" class="site-main rx-review-board-page" role="main">

	<section class="rxrb-hero" aria-labelledby="rxrb-title">
		<div class="rx-container rxrb-hero__inner">

			<?php if ( function_exists( 'rx_theme_breadcrumbs' ) ) : ?>
				<nav class="rxrb-breadcrumbs" aria-label="<?php esc_attr_e( 'Breadcrumb', 'rx-theme' ); ?>">
					<?php rx_theme_breadcrumbs(); ?>
				</nav>
			<?php endif; ?>

			<p class="rxrb-kicker">
				<?php esc_html_e( 'RX Health Editorial Governance', 'rx-theme' ); ?>
			</p>

			<h1 id="rxrb-title" class="rxrb-title">
				<?php the_title(); ?>
			</h1>

			<div class="rxrb-intro">
				<?php
				while ( have_posts() ) :
					the_post();

					if ( has_excerpt() ) {
						the_excerpt();
					} elseif ( get_the_content() ) {
						the_content();
					} else {
						echo '<p>' . esc_html__( 'Our review board supports medical accuracy, clinical clarity, editorial independence, and patient-friendly health education. Every reviewer helps strengthen the quality of RX medical content before it reaches readers.', 'rx-theme' ) . '</p>';
					}
				endwhile;
				?>
			</div>

			<div class="rxrb-hero__stats" aria-label="<?php esc_attr_e( 'Review board statistics', 'rx-theme' ); ?>">
				<div class="rxrb-stat">
					<strong><?php echo esc_html( number_format_i18n( (int) $rx_review_board_query->found_posts ) ); ?></strong>
					<span><?php esc_html_e( 'Listed reviewers', 'rx-theme' ); ?></span>
				</div>

				<div class="rxrb-stat">
					<strong><?php echo esc_html( number_format_i18n( count( $specialty_options ) ) ); ?></strong>
					<span><?php esc_html_e( 'Medical specialties', 'rx-theme' ); ?></span>
				</div>

				<div class="rxrb-stat">
					<strong><?php echo esc_html( number_format_i18n( count( $country_options ) ) ); ?></strong>
					<span><?php esc_html_e( 'Countries represented', 'rx-theme' ); ?></span>
				</div>
			</div>

		</div>
	</section>

	<section class="rxrb-governance" aria-labelledby="rxrb-governance-title">
		<div class="rx-container">

			<h2 id="rxrb-governance-title" class="rxrb-section-title">
				<?php esc_html_e( 'How the RX Review Board Helps Readers', 'rx-theme' ); ?>
			</h2>

			<div class="rxrb-governance-grid">
				<article class="rxrb-governance-card">
					<h3><?php esc_html_e( 'Medical Accuracy', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'Reviewers check important medical statements, disease explanations, diagnostic concepts, treatment language, and safety warnings so readers receive dependable health information.', 'rx-theme' ); ?></p>
				</article>

				<article class="rxrb-governance-card">
					<h3><?php esc_html_e( 'Evidence-Based Editing', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'The review process encourages use of reliable clinical references, current medical understanding, clear definitions, and balanced explanations without unnecessary fear or confusion.', 'rx-theme' ); ?></p>
				</article>

				<article class="rxrb-governance-card">
					<h3><?php esc_html_e( 'Plain English Health Education', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'Complex medical terms are translated into simple, readable language so patients, families, students, and general readers can understand the topic more easily.', 'rx-theme' ); ?></p>
				</article>

				<article class="rxrb-governance-card">
					<h3><?php esc_html_e( 'Editorial Independence', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'Review board members help protect the content from unsupported claims, promotional pressure, unsafe advice, and unclear medical recommendations.', 'rx-theme' ); ?></p>
				</article>
			</div>

		</div>
	</section>

	<section class="rxrb-filter-section" aria-labelledby="rxrb-filter-title">
		<div class="rx-container">

			<h2 id="rxrb-filter-title" class="screen-reader-text">
				<?php esc_html_e( 'Search and filter review board members', 'rx-theme' ); ?>
			</h2>

			<form class="rxrb-filter-form" method="get" action="<?php echo esc_url( get_permalink() ); ?>">
				<div class="rxrb-filter-grid">

					<div class="rxrb-field">
						<label for="rxrb_search">
							<?php esc_html_e( 'Search by name or keyword', 'rx-theme' ); ?>
						</label>
						<input
							type="search"
							id="rxrb_search"
							name="rxrb_search"
							value="<?php echo esc_attr( $search_query ); ?>"
							placeholder="<?php esc_attr_e( 'Example: cardiology, surgeon, professor', 'rx-theme' ); ?>"
						/>
					</div>

					<div class="rxrb-field">
						<label for="rxrb_specialty">
							<?php esc_html_e( 'Specialty', 'rx-theme' ); ?>
						</label>
						<select id="rxrb_specialty" name="rxrb_specialty">
							<option value=""><?php esc_html_e( 'All specialties', 'rx-theme' ); ?></option>
							<?php foreach ( $specialty_options as $option ) : ?>
								<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $specialty_filter, $option ); ?>>
									<?php echo esc_html( $option ); ?>
								</option>
							<?php endforeach; ?>
						</select>
					</div>

					<div class="rxrb-field">
						<label for="rxrb_designation">
							<?php esc_html_e( 'Designation', 'rx-theme' ); ?>
						</label>
						<select id="rxrb_designation" name="rxrb_designation">
							<option value=""><?php esc_html_e( 'All designations', 'rx-theme' ); ?></option>
							<?php foreach ( $designation_options as $option ) : ?>
								<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $designation_filter, $option ); ?>>
									<?php echo esc_html( $option ); ?>
								</option>
							<?php endforeach; ?>
						</select>
					</div>

					<div class="rxrb-field">
						<label for="rxrb_country">
							<?php esc_html_e( 'Country', 'rx-theme' ); ?>
						</label>
						<select id="rxrb_country" name="rxrb_country">
							<option value=""><?php esc_html_e( 'All countries', 'rx-theme' ); ?></option>
							<?php foreach ( $country_options as $option ) : ?>
								<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $country_filter, $option ); ?>>
									<?php echo esc_html( $option ); ?>
								</option>
							<?php endforeach; ?>
						</select>
					</div>

					<div class="rxrb-field">
						<label for="rxrb_status">
							<?php esc_html_e( 'Status', 'rx-theme' ); ?>
						</label>
						<select id="rxrb_status" name="rxrb_status">
							<option value=""><?php esc_html_e( 'All members', 'rx-theme' ); ?></option>
							<option value="verified" <?php selected( $status_filter, 'verified' ); ?>>
								<?php esc_html_e( 'Verified only', 'rx-theme' ); ?>
							</option>
						</select>
					</div>

					<div class="rxrb-field">
						<label for="rxrb_sort">
							<?php esc_html_e( 'Sort by', 'rx-theme' ); ?>
						</label>
						<select id="rxrb_sort" name="rxrb_sort">
							<option value="name_asc" <?php selected( $sort, 'name_asc' ); ?>>
								<?php esc_html_e( 'Name A to Z', 'rx-theme' ); ?>
							</option>
							<option value="name_desc" <?php selected( $sort, 'name_desc' ); ?>>
								<?php esc_html_e( 'Name Z to A', 'rx-theme' ); ?>
							</option>
							<option value="experience_high" <?php selected( $sort, 'experience_high' ); ?>>
								<?php esc_html_e( 'Highest experience', 'rx-theme' ); ?>
							</option>
							<option value="review_count_high" <?php selected( $sort, 'review_count_high' ); ?>>
								<?php esc_html_e( 'Most reviewed articles', 'rx-theme' ); ?>
							</option>
							<option value="recent_reviewed" <?php selected( $sort, 'recent_reviewed' ); ?>>
								<?php esc_html_e( 'Recently reviewed', 'rx-theme' ); ?>
							</option>
						</select>
					</div>

				</div>

				<div class="rxrb-filter-actions">
					<button type="submit" class="rxrb-button rxrb-button--primary">
						<?php esc_html_e( 'Apply Filters', 'rx-theme' ); ?>
					</button>

					<a class="rxrb-button rxrb-button--secondary" href="<?php echo esc_url( get_permalink() ); ?>">
						<?php esc_html_e( 'Reset', 'rx-theme' ); ?>
					</a>
				</div>
			</form>

		</div>
	</section>

	<section class="rxrb-members-section" aria-labelledby="rxrb-members-title">
		<div class="rx-container">

			<div class="rxrb-section-heading">
				<h2 id="rxrb-members-title" class="rxrb-section-title">
					<?php esc_html_e( 'Meet the Review Board', 'rx-theme' ); ?>
				</h2>

				<p class="rxrb-results-count">
					<?php
					printf(
						esc_html(
							_n(
								'%s reviewer found',
								'%s reviewers found',
								(int) $rx_review_board_query->found_posts,
								'rx-theme'
							)
						),
						esc_html( number_format_i18n( (int) $rx_review_board_query->found_posts ) )
					);
					?>
				</p>
			</div>

			<?php if ( $rx_review_board_query->have_posts() ) : ?>

				<div class="rxrb-members-grid">

					<?php
					while ( $rx_review_board_query->have_posts() ) :
						$rx_review_board_query->the_post();

						$member_id     = get_the_ID();
						$name          = rx_review_board_get_meta( $member_id, 'rxrb_full_name', get_the_title() );
						$designation   = rx_review_board_get_meta( $member_id, 'rxrb_designation', __( 'Medical Reviewer', 'rx-theme' ) );
						$specialty     = rx_review_board_get_meta( $member_id, 'rxrb_specialty', __( 'General Medicine', 'rx-theme' ) );
						$country       = rx_review_board_get_meta( $member_id, 'rxrb_country' );
						$institution   = rx_review_board_get_meta( $member_id, 'rxrb_institution' );
						$qualification = rx_review_board_get_meta( $member_id, 'rxrb_qualification' );
						$experience    = rx_review_board_get_meta( $member_id, 'rxrb_experience' );
						$profile_url   = rx_review_board_get_meta( $member_id, 'rxrb_profile_url', get_permalink() );
						$orcid         = rx_review_board_get_meta( $member_id, 'rxrb_orcid' );
						$google        = rx_review_board_get_meta( $member_id, 'rxrb_google_scholar' );
						$pubmed        = rx_review_board_get_meta( $member_id, 'rxrb_pubmed' );
						$verified      = rx_review_board_bool_meta( $member_id, 'rxrb_verified' );
						$review_count  = rx_review_board_get_meta( $member_id, 'rxrb_review_count', '0' );
						$last_reviewed = rx_review_board_get_meta( $member_id, 'rxrb_last_reviewed' );
						$short_bio     = rx_review_board_get_meta( $member_id, 'rxrb_short_bio' );

						if ( empty( $short_bio ) ) {
							$short_bio = wp_trim_words( wp_strip_all_tags( get_the_excerpt() ), 28, '...' );
						}

						$schema_members[] = rx_review_board_get_member_schema( $member_id );
						?>

						<article id="reviewer-<?php echo esc_attr( $member_id ); ?>" <?php post_class( 'rxrb-member-card' ); ?>>
							<div class="rxrb-member-card__media">
								<a href="<?php echo esc_url( $profile_url ); ?>" aria-label="<?php echo esc_attr( sprintf( __( 'View profile of %s', 'rx-theme' ), $name ) ); ?>">
									<?php if ( has_post_thumbnail() ) : ?>
										<?php
										the_post_thumbnail(
											'medium_large',
											array(
												'class'   => 'rxrb-member-card__image',
												'loading' => 'lazy',
												'alt'     => esc_attr( $name ),
											)
										);
										?>
									<?php else : ?>
										<div class="rxrb-member-card__avatar" aria-hidden="true">
											<?php echo esc_html( mb_substr( $name, 0, 1 ) ); ?>
										</div>
									<?php endif; ?>
								</a>

								<?php if ( $verified ) : ?>
									<span class="rxrb-badge rxrb-badge--verified">
										<?php esc_html_e( 'Verified', 'rx-theme' ); ?>
									</span>
								<?php endif; ?>
							</div>

							<div class="rxrb-member-card__body">
								<h3 class="rxrb-member-card__name">
									<a href="<?php echo esc_url( $profile_url ); ?>">
										<?php echo esc_html( $name ); ?>
									</a>
								</h3>

								<p class="rxrb-member-card__designation">
									<?php echo esc_html( $designation ); ?>
								</p>

								<p class="rxrb-member-card__specialty">
									<?php echo esc_html( $specialty ); ?>
								</p>

								<?php if ( ! empty( $qualification ) ) : ?>
									<p class="rxrb-member-card__qualification">
										<strong><?php esc_html_e( 'Qualification:', 'rx-theme' ); ?></strong>
										<?php echo esc_html( $qualification ); ?>
									</p>
								<?php endif; ?>

								<?php if ( ! empty( $institution ) ) : ?>
									<p class="rxrb-member-card__institution">
										<strong><?php esc_html_e( 'Institution:', 'rx-theme' ); ?></strong>
										<?php echo esc_html( $institution ); ?>
									</p>
								<?php endif; ?>

								<?php if ( ! empty( $country ) ) : ?>
									<p class="rxrb-member-card__country">
										<strong><?php esc_html_e( 'Country:', 'rx-theme' ); ?></strong>
										<?php echo esc_html( $country ); ?>
									</p>
								<?php endif; ?>

								<?php if ( ! empty( $experience ) ) : ?>
									<p class="rxrb-member-card__experience">
										<strong><?php esc_html_e( 'Experience:', 'rx-theme' ); ?></strong>
										<?php echo esc_html( $experience ); ?>
										<?php esc_html_e( 'years', 'rx-theme' ); ?>
									</p>
								<?php endif; ?>

								<?php if ( ! empty( $short_bio ) ) : ?>
									<p class="rxrb-member-card__bio">
										<?php echo esc_html( $short_bio ); ?>
									</p>
								<?php endif; ?>

								<div class="rxrb-member-card__meta">
									<span>
										<?php
										printf(
											esc_html__( '%s articles reviewed', 'rx-theme' ),
											esc_html( number_format_i18n( (int) $review_count ) )
										);
										?>
									</span>

									<?php if ( ! empty( $last_reviewed ) ) : ?>
										<span>
											<?php
											printf(
												esc_html__( 'Last reviewed: %s', 'rx-theme' ),
												esc_html( date_i18n( get_option( 'date_format' ), strtotime( $last_reviewed ) ) )
											);
											?>
										</span>
									<?php endif; ?>
								</div>

								<div class="rxrb-member-card__links">
									<a class="rxrb-profile-link" href="<?php echo esc_url( $profile_url ); ?>">
										<?php esc_html_e( 'View Profile', 'rx-theme' ); ?>
									</a>

									<?php if ( ! empty( $orcid ) && filter_var( $orcid, FILTER_VALIDATE_URL ) ) : ?>
										<a href="<?php echo esc_url( $orcid ); ?>" rel="nofollow noopener" target="_blank">
											<?php esc_html_e( 'ORCID', 'rx-theme' ); ?>
										</a>
									<?php endif; ?>

									<?php if ( ! empty( $google ) && filter_var( $google, FILTER_VALIDATE_URL ) ) : ?>
										<a href="<?php echo esc_url( $google ); ?>" rel="nofollow noopener" target="_blank">
											<?php esc_html_e( 'Scholar', 'rx-theme' ); ?>
										</a>
									<?php endif; ?>

									<?php if ( ! empty( $pubmed ) && filter_var( $pubmed, FILTER_VALIDATE_URL ) ) : ?>
										<a href="<?php echo esc_url( $pubmed ); ?>" rel="nofollow noopener" target="_blank">
											<?php esc_html_e( 'PubMed', 'rx-theme' ); ?>
										</a>
									<?php endif; ?>
								</div>
							</div>
						</article>

					<?php endwhile; ?>

				</div>

				<?php
				$pagination_links = paginate_links(
					array(
						'total'     => max( 1, (int) $rx_review_board_query->max_num_pages ),
						'current'   => $paged,
						'mid_size'  => 2,
						'prev_text' => esc_html__( 'Previous', 'rx-theme' ),
						'next_text' => esc_html__( 'Next', 'rx-theme' ),
						'type'      => 'list',
						'add_args'  => array_filter(
							array(
								'rxrb_search'      => $search_query,
								'rxrb_specialty'   => $specialty_filter,
								'rxrb_designation' => $designation_filter,
								'rxrb_country'     => $country_filter,
								'rxrb_status'      => $status_filter,
								'rxrb_sort'        => $sort,
							)
						),
					)
				);
				?>

				<?php if ( $pagination_links ) : ?>
					<nav class="rxrb-pagination" aria-label="<?php esc_attr_e( 'Review board pagination', 'rx-theme' ); ?>">
						<?php echo wp_kses_post( $pagination_links ); ?>
					</nav>
				<?php endif; ?>

			<?php else : ?>

				<?php $demo_members = rx_review_board_demo_members(); ?>

				<div class="rxrb-empty">
					<h3><?php esc_html_e( 'No review board members found yet', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'You can add real members by creating a review_board custom post type and adding the supported custom fields. Until then, these sample cards show how the final design will look.', 'rx-theme' ); ?></p>
				</div>

				<div class="rxrb-members-grid rxrb-members-grid--demo">
					<?php foreach ( $demo_members as $demo ) : ?>
						<article class="rxrb-member-card rxrb-member-card--demo">
							<div class="rxrb-member-card__media">
								<div class="rxrb-member-card__avatar" aria-hidden="true">
									<?php echo esc_html( mb_substr( $demo['name'], 0, 1 ) ); ?>
								</div>

								<?php if ( ! empty( $demo['verified'] ) ) : ?>
									<span class="rxrb-badge rxrb-badge--verified">
										<?php esc_html_e( 'Verified', 'rx-theme' ); ?>
									</span>
								<?php endif; ?>
							</div>

							<div class="rxrb-member-card__body">
								<h3 class="rxrb-member-card__name">
									<?php echo esc_html( $demo['name'] ); ?>
								</h3>

								<p class="rxrb-member-card__designation">
									<?php echo esc_html( $demo['designation'] ); ?>
								</p>

								<p class="rxrb-member-card__specialty">
									<?php echo esc_html( $demo['specialty'] ); ?>
								</p>

								<p>
									<strong><?php esc_html_e( 'Qualification:', 'rx-theme' ); ?></strong>
									<?php echo esc_html( $demo['qualification'] ); ?>
								</p>

								<p>
									<strong><?php esc_html_e( 'Institution:', 'rx-theme' ); ?></strong>
									<?php echo esc_html( $demo['institution'] ); ?>
								</p>

								<p class="rxrb-member-card__bio">
									<?php echo esc_html( $demo['bio'] ); ?>
								</p>
							</div>
						</article>
					<?php endforeach; ?>
				</div>

			<?php endif; ?>

			<?php wp_reset_postdata(); ?>

		</div>
	</section>

	<section class="rxrb-editorial-process" aria-labelledby="rxrb-process-title">
		<div class="rx-container">

			<h2 id="rxrb-process-title" class="rxrb-section-title">
				<?php esc_html_e( 'RX Medical Review Process', 'rx-theme' ); ?>
			</h2>

			<div class="rxrb-process-list">
				<article class="rxrb-process-item">
					<span class="rxrb-process-number">01</span>
					<h3><?php esc_html_e( 'Topic Selection', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'Medical topics are selected based on patient need, public health relevance, search demand, clinical importance, and educational value.', 'rx-theme' ); ?></p>
				</article>

				<article class="rxrb-process-item">
					<span class="rxrb-process-number">02</span>
					<h3><?php esc_html_e( 'Evidence Review', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'Writers and reviewers examine trusted clinical information, diagnostic standards, medical terminology, and treatment principles before publication.', 'rx-theme' ); ?></p>
				</article>

				<article class="rxrb-process-item">
					<span class="rxrb-process-number">03</span>
					<h3><?php esc_html_e( 'Clinical Review', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'Reviewers check whether the article explains the condition correctly, avoids unsafe claims, and uses language suitable for general readers.', 'rx-theme' ); ?></p>
				</article>

				<article class="rxrb-process-item">
					<span class="rxrb-process-number">04</span>
					<h3><?php esc_html_e( 'Update Cycle', 'rx-theme' ); ?></h3>
					<p><?php esc_html_e( 'Content should be reviewed again when medical guidelines, evidence, drug safety information, or diagnostic recommendations change.', 'rx-theme' ); ?></p>
				</article>
			</div>

		</div>
	</section>

</main>

<?php
/**
 * ------------------------------------------------------------
 * JSON-LD Schema
 * ------------------------------------------------------------
 */

$schema = array(
	'@context'    => 'https://schema.org',
	'@type'       => 'WebPage',
	'name'        => get_the_title(),
	'url'         => get_permalink(),
	'description' => wp_strip_all_tags( get_the_excerpt() ),
	'publisher'   => array(
		'@type' => 'Organization',
		'name'  => get_bloginfo( 'name' ),
		'url'   => home_url( '/' ),
	),
	'mainEntity'  => array(
		'@type'           => 'ItemList',
		'name'            => __( 'RX Review Board Members', 'rx-theme' ),
		'numberOfItems'   => count( $schema_members ),
		'itemListElement' => array(),
	),
);

if ( ! empty( $schema_members ) ) {
	foreach ( $schema_members as $index => $member_schema ) {
		$schema['mainEntity']['itemListElement'][] = array(
			'@type'    => 'ListItem',
			'position' => $index + 1,
			'item'     => $member_schema,
		);
	}
}
?>

<script type="application/ld+json">
<?php echo wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT ); ?>
</script>

<?php
get_footer();

Add this CSS in:

assets/css/templates/review-board.css

.rx-review-board-page {
	--rxrb-bg: var(--rx-color-background, #ffffff);
	--rxrb-soft-bg: var(--rx-color-surface, #f7f9fc);
	--rxrb-card-bg: var(--rx-color-card, #ffffff);
	--rxrb-text: var(--rx-color-text, #162033);
	--rxrb-muted: var(--rx-color-muted, #667085);
	--rxrb-border: var(--rx-color-border, #e5e7eb);
	--rxrb-primary: var(--rx-color-primary, #1266f1);
	--rxrb-primary-dark: var(--rx-color-primary-dark, #084ab8);
	--rxrb-success: var(--rx-color-success, #11845b);
	--rxrb-radius: var(--rx-radius-lg, 18px);
	--rxrb-shadow: 0 18px 45px rgba(16, 24, 40, 0.08);
	color: var(--rxrb-text);
	background: var(--rxrb-bg);
}

.rx-container {
	width: min(1180px, calc(100% - 32px));
	margin-inline: auto;
}

.rxrb-hero {
	padding: clamp(48px, 7vw, 96px) 0;
	background:
		radial-gradient(circle at top left, rgba(18, 102, 241, 0.12), transparent 36%),
		linear-gradient(135deg, #f8fbff 0%, #ffffff 60%);
}

.rxrb-kicker {
	margin: 0 0 12px;
	color: var(--rxrb-primary);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 0.82rem;
}

.rxrb-title {
	margin: 0;
	font-size: clamp(2.2rem, 5vw, 4.7rem);
	line-height: 1.04;
	letter-spacing: -0.045em;
}

.rxrb-intro {
	max-width: 780px;
	margin-top: 22px;
	color: var(--rxrb-muted);
	font-size: clamp(1rem, 2vw, 1.18rem);
	line-height: 1.75;
}

.rxrb-hero__stats {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 18px;
	margin-top: 34px;
	max-width: 820px;
}

.rxrb-stat {
	padding: 22px;
	background: rgba(255, 255, 255, 0.78);
	border: 1px solid var(--rxrb-border);
	border-radius: var(--rxrb-radius);
	box-shadow: 0 12px 30px rgba(16, 24, 40, 0.06);
	backdrop-filter: blur(10px);
}

.rxrb-stat strong {
	display: block;
	font-size: clamp(1.7rem, 3vw, 2.5rem);
	line-height: 1;
	color: var(--rxrb-primary);
}

.rxrb-stat span {
	display: block;
	margin-top: 8px;
	color: var(--rxrb-muted);
	font-size: 0.95rem;
}

.rxrb-governance,
.rxrb-filter-section,
.rxrb-members-section,
.rxrb-editorial-process {
	padding: clamp(42px, 6vw, 76px) 0;
}

.rxrb-governance,
.rxrb-editorial-process {
	background: var(--rxrb-soft-bg);
}

.rxrb-section-heading {
	display: flex;
	align-items: end;
	justify-content: space-between;
	gap: 20px;
	margin-bottom: 28px;
}

.rxrb-section-title {
	margin: 0 0 26px;
	font-size: clamp(1.75rem, 3vw, 2.65rem);
	line-height: 1.12;
	letter-spacing: -0.025em;
}

.rxrb-results-count {
	margin: 0 0 30px;
	color: var(--rxrb-muted);
}

.rxrb-governance-grid,
.rxrb-process-list {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 18px;
}

.rxrb-governance-card,
.rxrb-process-item {
	padding: 24px;
	background: var(--rxrb-card-bg);
	border: 1px solid var(--rxrb-border);
	border-radius: var(--rxrb-radius);
	box-shadow: 0 10px 24px rgba(16, 24, 40, 0.04);
}

.rxrb-governance-card h3,
.rxrb-process-item h3 {
	margin: 0 0 10px;
	font-size: 1.08rem;
}

.rxrb-governance-card p,
.rxrb-process-item p {
	margin: 0;
	color: var(--rxrb-muted);
	line-height: 1.7;
}

.rxrb-process-number {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	margin-bottom: 16px;
	border-radius: 999px;
	background: rgba(18, 102, 241, 0.1);
	color: var(--rxrb-primary);
	font-weight: 800;
}

.rxrb-filter-form {
	padding: 22px;
	background: var(--rxrb-card-bg);
	border: 1px solid var(--rxrb-border);
	border-radius: var(--rxrb-radius);
	box-shadow: var(--rxrb-shadow);
}

.rxrb-filter-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 16px;
}

.rxrb-field label {
	display: block;
	margin-bottom: 8px;
	font-weight: 700;
	font-size: 0.92rem;
}

.rxrb-field input,
.rxrb-field select {
	width: 100%;
	min-height: 48px;
	padding: 10px 14px;
	border: 1px solid var(--rxrb-border);
	border-radius: 12px;
	background: #fff;
	color: var(--rxrb-text);
	font: inherit;
}

.rxrb-field input:focus,
.rxrb-field select:focus {
	outline: 3px solid rgba(18, 102, 241, 0.18);
	border-color: var(--rxrb-primary);
}

.rxrb-filter-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 18px;
}

.rxrb-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 46px;
	padding: 10px 18px;
	border-radius: 12px;
	border: 1px solid transparent;
	font-weight: 700;
	text-decoration: none;
	cursor: pointer;
}

.rxrb-button--primary {
	background: var(--rxrb-primary);
	color: #fff;
}

.rxrb-button--primary:hover {
	background: var(--rxrb-primary-dark);
	color: #fff;
}

.rxrb-button--secondary {
	background: #fff;
	color: var(--rxrb-text);
	border-color: var(--rxrb-border);
}

.rxrb-members-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 22px;
}

.rxrb-member-card {
	position: relative;
	overflow: hidden;
	background: var(--rxrb-card-bg);
	border: 1px solid var(--rxrb-border);
	border-radius: var(--rxrb-radius);
	box-shadow: 0 14px 32px rgba(16, 24, 40, 0.06);
	transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
}

.rxrb-member-card:hover {
	transform: translateY(-4px);
	border-color: rgba(18, 102, 241, 0.25);
	box-shadow: var(--rxrb-shadow);
}

.rxrb-member-card__media {
	position: relative;
	aspect-ratio: 16 / 10;
	background: linear-gradient(135deg, rgba(18, 102, 241, 0.12), rgba(17, 132, 91, 0.12));
	display: flex;
	align-items: center;
	justify-content: center;
}

.rxrb-member-card__image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.rxrb-member-card__avatar {
	width: 96px;
	height: 96px;
	border-radius: 999px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: #fff;
	color: var(--rxrb-primary);
	font-size: 2.8rem;
	font-weight: 800;
	box-shadow: 0 12px 34px rgba(16, 24, 40, 0.12);
}

.rxrb-badge {
	position: absolute;
	top: 14px;
	right: 14px;
	display: inline-flex;
	align-items: center;
	min-height: 30px;
	padding: 6px 10px;
	border-radius: 999px;
	font-size: 0.78rem;
	font-weight: 800;
}

.rxrb-badge--verified {
	background: rgba(17, 132, 91, 0.12);
	color: var(--rxrb-success);
	border: 1px solid rgba(17, 132, 91, 0.22);
}

.rxrb-member-card__body {
	padding: 22px;
}

.rxrb-member-card__name {
	margin: 0 0 6px;
	font-size: 1.28rem;
	line-height: 1.25;
}

.rxrb-member-card__name a {
	color: inherit;
	text-decoration: none;
}

.rxrb-member-card__name a:hover {
	color: var(--rxrb-primary);
}

.rxrb-member-card__designation {
	margin: 0;
	color: var(--rxrb-primary);
	font-weight: 700;
}

.rxrb-member-card__specialty {
	margin: 8px 0 14px;
	color: var(--rxrb-muted);
	font-weight: 600;
}

.rxrb-member-card__body p {
	line-height: 1.65;
}

.rxrb-member-card__qualification,
.rxrb-member-card__institution,
.rxrb-member-card__country,
.rxrb-member-card__experience {
	margin: 8px 0;
	color: var(--rxrb-text);
	font-size: 0.95rem;
}

.rxrb-member-card__bio {
	margin-top: 14px;
	color: var(--rxrb-muted);
}

.rxrb-member-card__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin-top: 16px;
	color: var(--rxrb-muted);
	font-size: 0.86rem;
}

.rxrb-member-card__meta span {
	padding: 6px 9px;
	border-radius: 999px;
	background: var(--rxrb-soft-bg);
}

.rxrb-member-card__links {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin-top: 18px;
}

.rxrb-member-card__links a {
	display: inline-flex;
	align-items: center;
	min-height: 34px;
	padding: 6px 10px;
	border-radius: 999px;
	background: var(--rxrb-soft-bg);
	color: var(--rxrb-primary);
	text-decoration: none;
	font-weight: 700;
	font-size: 0.9rem;
}

.rxrb-member-card__links a:hover {
	background: var(--rxrb-primary);
	color: #fff;
}

.rxrb-empty {
	padding: 28px;
	margin-bottom: 24px;
	border: 1px dashed var(--rxrb-border);
	border-radius: var(--rxrb-radius);
	background: var(--rxrb-soft-bg);
}

.rxrb-empty h3 {
	margin-top: 0;
}

.rxrb-empty p {
	margin-bottom: 0;
	color: var(--rxrb-muted);
}

.rxrb-pagination {
	margin-top: 36px;
}

.rxrb-pagination ul {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	list-style: none;
	padding: 0;
	margin: 0;
}

.rxrb-pagination a,
.rxrb-pagination span {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 42px;
	min-height: 42px;
	padding: 8px 12px;
	border-radius: 12px;
	border: 1px solid var(--rxrb-border);
	text-decoration: none;
	color: var(--rxrb-text);
	background: #fff;
	font-weight: 700;
}

.rxrb-pagination .current {
	background: var(--rxrb-primary);
	color: #fff;
	border-color: var(--rxrb-primary);
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

@media (max-width: 1024px) {
	.rxrb-governance-grid,
	.rxrb-process-list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.rxrb-members-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.rxrb-filter-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 700px) {
	.rxrb-hero__stats,
	.rxrb-governance-grid,
	.rxrb-process-list,
	.rxrb-members-grid,
	.rxrb-filter-grid {
		grid-template-columns: 1fr;
	}

	.rxrb-section-heading {
		display: block;
	}

	.rxrb-title {
		font-size: 2.4rem;
	}

	.rxrb-filter-actions {
		display: grid;
	}

	.rxrb-button {
		width: 100%;
	}
}

To load this CSS only on the Review Board page, add this in your functions.php or inc/core/enqueue.php:

/**
 * Enqueue Review Board template CSS.
 */
function rx_theme_enqueue_review_board_template_assets() {
	if ( is_page_template( 'templates/template-review-board.php' ) ) {
		wp_enqueue_style(
			'rx-review-board-template',
			get_template_directory_uri() . '/assets/css/templates/review-board.css',
			array(),
			wp_get_theme()->get( 'Version' )
		);
	}
}
add_action( 'wp_enqueue_scripts', 'rx_theme_enqueue_review_board_template_assets' );

Important: this template is ready for a future review_board custom post type. If you have not created the CPT yet, the page will still show a beautiful fallback demo section instead of breaking.

Leave a Reply

Your email address will not be published. Required fields are marked *