Skip to main content

Theme Integration Guide

Complete guide for integrating ThemeRuby Multi Authors into your WordPress theme.

Quick Start​

Minimum Integration​

Add this to your single.php or content-single.php:

<?php
// Display authors
if ( function_exists( 'tmauthors_the_authors' ) ) {
tmauthors_the_authors( 0, array(
'before' => '<span class="byline">By ',
'after' => '</span>',
) );
} else {
// Fallback to WordPress default
echo '<span class="byline">By ';
the_author_posts_link();
echo '</span>';
}
?>

That's it! Your theme now supports multiple authors.

Complete Integration​

Step 1: Theme Functions​

Add to functions.php:

/**
* Add theme support for ThemeRuby Multi Authors
*/
function mytheme_tmauthors_support() {
// Declare theme support
add_theme_support( 'easy-multi-authors' );

// Add custom image sizes for author avatars
add_image_size( 'author-thumbnail', 80, 80, true );
add_image_size( 'author-large', 150, 150, true );
}
add_action( 'after_setup_theme', 'mytheme_tmauthors_support' );

/**
* Enqueue author styles
*/
function mytheme_author_styles() {
if ( is_single() || is_author() ) {
wp_enqueue_style(
'mytheme-authors',
get_template_directory_uri() . '/css/authors.css',
array(),
'1.0.0'
);
}
}
add_action( 'wp_enqueue_scripts', 'mytheme_author_styles' );

Step 2: Template Files​

single.php​

<?php
/**
* Single Post Template
*/
get_header();

while ( have_posts() ) :
the_post();
?>

<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<h1 class="entry-title"><?php the_title(); ?></h1>

<div class="entry-meta">
<?php
// Author byline
if ( function_exists( 'tmauthors_the_authors' ) ) {
tmauthors_the_authors( 0, array(
'before' => '<span class="byline">By ',
'after' => '</span>',
'separator' => ', ',
) );
} else {
echo '<span class="byline">By ';
the_author_posts_link();
echo '</span>';
}
?>

<span class="posted-on">
<time datetime="<?php echo get_the_date( 'c' ); ?>">
<?php echo get_the_date(); ?>
</time>
</span>
</div>
</header>

<div class="entry-content">
<?php the_content(); ?>
</div>

<footer class="entry-footer">
<?php
// Author box
if ( function_exists( 'tmauthors_box' ) ) {
tmauthors_box();
}
?>
</footer>
</article>

<?php
endwhile;

get_footer();
?>

author.php​

<?php
/**
* Author Archive Template
*/
get_header();

$author = get_queried_object();
?>

<div class="author-archive">
<header class="page-header">
<div class="author-info">
<div class="author-avatar">
<?php echo get_avatar( $author->ID, 120 ); ?>
</div>

<div class="author-details">
<h1 class="author-title">
<?php echo esc_html( $author->display_name ); ?>
</h1>

<?php if ( $author->description ) : ?>
<div class="author-bio">
<?php echo wpautop( $author->description ); ?>
</div>
<?php endif; ?>

<?php
// Post count
if ( function_exists( 'tmauthors_get_author_post_count' ) ) {
$count = tmauthors_get_author_post_count( $author->ID );
echo '<div class="author-post-count">';
printf( _n( '%s post', '%s posts', $count, 'mytheme' ), number_format_i18n( $count ) );
echo '</div>';
}
?>
</div>
</div>
</header>

<div class="author-posts">
<?php
if ( have_posts() ) :
while ( have_posts() ) :
the_post();
get_template_part( 'template-parts/content', get_post_type() );
endwhile;

the_posts_pagination();
else :
get_template_part( 'template-parts/content', 'none' );
endif;
?>
</div>
</div>

<?php get_footer(); ?>

Step 3: Custom Styles​

Create css/authors.css:

/**
* Author Styles
*/

/* Byline */
.byline {
font-size: 14px;
color: #666;
}

.byline a {
color: #333;
text-decoration: none;
font-weight: 600;
}

.byline a:hover {
color: #0073aa;
}

/* Author Box */
.ema-author-box {
margin: 40px 0;
padding: 30px;
background: #f9f9f9;
border: 1px solid #e0e0e0;
border-radius: 8px;
}

.ema-author-box h3 {
margin-top: 0;
margin-bottom: 20px;
font-size: 24px;
color: #333;
}

.ema-author-item {
display: flex;
gap: 20px;
margin-bottom: 25px;
padding-bottom: 25px;
border-bottom: 1px solid #e0e0e0;
}

.ema-author-item:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}

.ema-author-avatar {
flex-shrink: 0;
}

.ema-author-avatar img {
border-radius: 50%;
border: 3px solid #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.ema-author-info {
flex: 1;
}

.ema-author-name {
margin: 0 0 10px;
font-size: 20px;
font-weight: 600;
}

.ema-author-name a {
color: #333;
text-decoration: none;
}

.ema-author-name a:hover {
color: #0073aa;
}

.ema-author-bio {
margin: 0 0 10px;
color: #666;
line-height: 1.6;
}

.ema-author-link a {
color: #0073aa;
text-decoration: none;
font-weight: 600;
}

.ema-author-link a:hover {
text-decoration: underline;
}

/* Author Archive */
.author-archive .author-info {
display: flex;
gap: 30px;
align-items: flex-start;
margin-bottom: 40px;
}

.author-archive .author-avatar {
flex-shrink: 0;
}

.author-archive .author-avatar img {
border-radius: 50%;
}

.author-archive .author-details {
flex: 1;
}

.author-archive .author-title {
margin: 0 0 15px;
font-size: 32px;
}

.author-archive .author-bio {
color: #666;
line-height: 1.6;
margin-bottom: 15px;
}

.author-archive .author-post-count {
color: #999;
font-size: 14px;
}

/* Responsive */
@media (max-width: 768px) {
.ema-author-item {
flex-direction: column;
text-align: center;
}

.author-archive .author-info {
flex-direction: column;
text-align: center;
}

.author-archive .author-avatar {
margin: 0 auto;
}
}

Custom Templates​

Author Cards Template​

Create template-parts/author-cards.php:

<?php
/**
* Author Cards Template
*/
$authors = tmauthors_get_post_authors( get_the_ID() );

if ( empty( $authors ) ) {
return;
}
?>

<div class="author-cards">
<h3 class="author-cards-title">About the Authors</h3>

<div class="author-cards-grid">
<?php foreach ( $authors as $author ) : ?>
<div class="author-card">
<div class="author-card-avatar">
<a href="<?php echo esc_url( get_author_posts_url( $author->ID ) ); ?>">
<?php echo get_avatar( $author->ID, 80 ); ?>
</a>
</div>

<div class="author-card-info">
<h4 class="author-card-name">
<a href="<?php echo esc_url( get_author_posts_url( $author->ID ) ); ?>">
<?php echo esc_html( $author->display_name ); ?>
</a>
</h4>

<?php if ( $author->description ) : ?>
<p class="author-card-bio">
<?php echo esc_html( wp_trim_words( $author->description, 20 ) ); ?>
</p>
<?php endif; ?>

<div class="author-card-meta">
<?php
$post_count = tmauthors_get_author_post_count( $author->ID );
printf( _n( '%s post', '%s posts', $post_count, 'mytheme' ), number_format_i18n( $post_count ) );
?>
</div>

<a href="<?php echo esc_url( get_author_posts_url( $author->ID ) ); ?>" class="author-card-link">
View all posts →
</a>
</div>
</div>
<?php endforeach; ?>
</div>
</div>

<style>
.author-cards {
margin: 40px 0;
}

.author-cards-title {
font-size: 24px;
margin-bottom: 20px;
}

.author-cards-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}

.author-card {
background: #fff;
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 20px;
text-align: center;
}

.author-card-avatar img {
border-radius: 50%;
}

.author-card-name {
margin: 15px 0 10px;
font-size: 18px;
}

.author-card-name a {
color: #333;
text-decoration: none;
}

.author-card-bio {
color: #666;
font-size: 14px;
line-height: 1.5;
margin-bottom: 10px;
}

.author-card-meta {
color: #999;
font-size: 12px;
margin-bottom: 15px;
}

.author-card-link {
color: #0073aa;
text-decoration: none;
font-size: 14px;
}
</style>

Usage:

<?php get_template_part( 'template-parts/author-cards' ); ?>

Inline Author List​

Create template-parts/inline-authors.php:

<?php
/**
* Inline Author List
*/
if ( ! function_exists( 'tmauthors_get_post_authors' ) ) {
return;
}

$authors = tmauthors_get_post_authors( get_the_ID() );
if ( empty( $authors ) ) {
return;
}
?>

<div class="inline-authors">
<?php foreach ( $authors as $index => $author ) : ?>
<?php if ( $index > 0 ) echo ', '; ?>

<span class="author-item">
<?php echo get_avatar( $author->ID, 24 ); ?>
<a href="<?php echo esc_url( get_author_posts_url( $author->ID ) ); ?>">
<?php echo esc_html( $author->display_name ); ?>
</a>
</span>
<?php endforeach; ?>
</div>

<style>
.inline-authors {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 5px;
font-size: 14px;
}

.inline-authors .author-item {
display: inline-flex;
align-items: center;
gap: 5px;
}

.inline-authors .author-item img {
border-radius: 50%;
vertical-align: middle;
}

.inline-authors .author-item a {
color: #333;
text-decoration: none;
}

.inline-authors .author-item a:hover {
color: #0073aa;
}
</style>

Widget Integration​

Recent Posts by Authors Widget​

/**
* Recent Posts by Multiple Authors Widget
*/
class MultiAuthor_Recent_Posts_Widget extends WP_Widget {

public function __construct() {
parent::__construct(
'multiauthor_recent_posts',
'Recent Posts (Multi-Author)',
array( 'description' => 'Display recent posts by selected authors' )
);
}

public function widget( $args, $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : 'Recent Posts';
$author_ids = ! empty( $instance['author_ids'] ) ? explode( ',', $instance['author_ids'] ) : array();
$limit = ! empty( $instance['limit'] ) ? absint( $instance['limit'] ) : 5;

echo $args['before_widget'];

if ( ! empty( $title ) ) {
echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
}

$query_args = array(
'posts_per_page' => $limit,
'post_status' => 'publish',
);

if ( ! empty( $author_ids ) ) {
$query_args['author__in'] = $author_ids;
}

$query = new WP_Query( $query_args );

if ( $query->have_posts() ) {
echo '<ul class="multiauthor-recent-posts">';

while ( $query->have_posts() ) {
$query->the_post();
?>
<li>
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
<div class="post-meta">
<?php
if ( function_exists( 'tmauthors_the_authors' ) ) {
tmauthors_the_authors( 0, array(
'link' => true,
'separator' => ', ',
) );
}
?>
</div>
</li>
<?php
}

echo '</ul>';
wp_reset_postdata();
}

echo $args['after_widget'];
}

public function form( $instance ) {
$title = ! empty( $instance['title'] ) ? $instance['title'] : '';
$author_ids = ! empty( $instance['author_ids'] ) ? $instance['author_ids'] : '';
$limit = ! empty( $instance['limit'] ) ? $instance['limit'] : 5;
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">Title:</label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text"
value="<?php echo esc_attr( $title ); ?>">
</p>

<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'author_ids' ) ); ?>">
Author IDs (comma-separated):
</label>
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'author_ids' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'author_ids' ) ); ?>" type="text"
value="<?php echo esc_attr( $author_ids ); ?>">
<small>Leave empty for all authors</small>
</p>

<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>">Number of posts:</label>
<input class="small-text" id="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'limit' ) ); ?>" type="number"
value="<?php echo esc_attr( $limit ); ?>" min="1" max="20">
</p>
<?php
}

public function update( $new_instance, $old_instance ) {
$instance = array();
$instance['title'] = ! empty( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : '';
$instance['author_ids'] = ! empty( $new_instance['author_ids'] ) ? sanitize_text_field( $new_instance['author_ids'] ) : '';
$instance['limit'] = ! empty( $new_instance['limit'] ) ? absint( $new_instance['limit'] ) : 5;

return $instance;
}
}

// Register widget
add_action( 'widgets_init', function() {
register_widget( 'MultiAuthor_Recent_Posts_Widget' );
} );

Block Editor Integration​

Custom Block for Author Display​

/**
* Author Display Block
* File: blocks/author-display/index.js
*/
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';

registerBlockType( 'mytheme/author-display', {
title: 'Author Display',
icon: 'admin-users',
category: 'widgets',
attributes: {
showAvatar: {
type: 'boolean',
default: true,
},
showBio: {
type: 'boolean',
default: true,
},
},

edit: ( { attributes, setAttributes } ) => {
const blockProps = useBlockProps();
const postId = useSelect( ( select ) =>
select( 'core/editor' ).getCurrentPostId()
);

return (
<div { ...blockProps }>
<div className="author-display-block">
<h3>Author Display Block</h3>
<p>Authors will be displayed here on the frontend.</p>
</div>
</div>
);
},

save: () => {
return null; // Rendered via PHP
},
} );

Register server-side rendering in functions.php:

/**
* Register author display block
*/
function mytheme_register_author_block() {
register_block_type( 'mytheme/author-display', array(
'render_callback' => 'mytheme_render_author_block',
) );
}
add_action( 'init', 'mytheme_register_author_block' );

function mytheme_render_author_block( $attributes, $content ) {
$show_avatar = isset( $attributes['showAvatar'] ) ? $attributes['showAvatar'] : true;
$show_bio = isset( $attributes['showBio'] ) ? $attributes['showBio'] : true;

$authors = tmauthors_get_post_authors( get_the_ID() );
if ( empty( $authors ) ) {
return '';
}

ob_start();
?>
<div class="wp-block-mytheme-author-display">
<?php foreach ( $authors as $author ) : ?>
<div class="author-item">
<?php if ( $show_avatar ) : ?>
<?php echo get_avatar( $author->ID, 60 ); ?>
<?php endif; ?>

<div>
<strong><?php echo esc_html( $author->display_name ); ?></strong>

<?php if ( $show_bio && $author->description ) : ?>
<p><?php echo esc_html( $author->description ); ?></p>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php
return ob_get_clean();
}

Complete Example Theme​

Download complete example theme: 👉 GitHub: ThemeRuby Multi Authors Example Theme

Next Steps​