Claude Skill

classic-theme-comments-discussion

Build or audit classic theme comments output for WP 7.1. Covers `comments_template()`, `comments.php`, `post_password_required()`, `have_comments()`, `wp_list_comments()`, comment pagination, `comment_form()`, threaded comment reply script loading, closed-comment messaging, acces

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download lonsdale201-wp-agent-skills-theme-development_classic-theme-comments-discussion-52f6020.zip · 3 KB
Part of lonsdale201/wp-agent-skills — 226 skills

Install

skills CLI npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/theme-development/classic-theme-comments-discussion
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart
Git git clone https://github.com/Lonsdale201/wp-agent-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole lonsdale201/wp-agent-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Classic Theme Comments and Discussion

Use this when adding or reviewing comments in a classic PHP theme: comments.php, comment list markup, comment pagination, the comment form, closed-comment states, and threaded reply behavior.

When to Use This Skill

  • Creating or editing comments.php.
  • Calling comments_template() from single.php, page.php, or a singular template part.
  • Styling wp_list_comments() output or replacing a comment callback.
  • Loading comment-reply.
  • Fixing missing comment pagination, password-protected post leaks, or inaccessible comment navigation.

Call Comments From Singular Templates

In a singular template, call comments after the content when the post supports discussion.

if ( comments_open() || get_comments_number() ) {
	comments_template();
}

Rules:

  • Do not call comments_template() on archives or search templates.
  • Check comments_open() or get_comments_number() before loading the template.
  • If a custom post type does not support comments, do not force comments into its template.
  • Keep the rendering code in comments.php.
  • Editor Notes use the comments table but are private editorial data. Do not use type => all in custom public queries or walkers; keep public theme output to ordinary comments/pings intentionally.

comments_template() is designed for single/page contexts and returns early outside supported contexts unless $withcomments is set.

comments.php Skeleton

Start with the password guard. This prevents comment content from leaking on protected posts.

<?php
if ( post_password_required() ) {
	return;
}
?>

<section id="comments" class="comments-area" aria-label="<?php esc_attr_e( 'Comments', 'textdomain' ); ?>">
	<?php if ( have_comments() ) : ?>
		<h2 class="comments-title">
			<?php
			$comment_count = get_comments_number();

			printf(
				esc_html(
					_nx(
						'%1$s comment on "%2$s"',
						'%1$s comments on "%2$s"',
						$comment_count,
						'comments title',
						'textdomain'
					)
				),
				esc_html( number_format_i18n( $comment_count ) ),
				esc_html( get_the_title() )
			);
			?>
		</h2>

		<ol class="comment-list">
			<?php
			wp_list_comments(
				array(
					'style'      => 'ol',
					'short_ping' => true,
					'avatar_size' => 48,
				)
			);
			?>
		</ol>
	<?php endif; ?>

	<?php comment_form(); ?>
</section>

Rules:

  • Use post_password_required() before output.
  • Use have_comments() for the list state.
  • Use number_format_i18n() for counts.
  • Escape the post title when inserting it into a comment heading.
  • Use comment_form() unless there is a very specific reason not to.

Comment Pagination

If comment pagination is enabled, render navigation before and/or after the list.

if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) :
	?>
	<nav class="comment-navigation" aria-label="<?php esc_attr_e( 'Comment navigation', 'textdomain' ); ?>">
		<h2 class="screen-reader-text"><?php esc_html_e( 'Comment navigation', 'textdomain' ); ?></h2>
		<div class="nav-previous"><?php previous_comments_link( esc_html__( 'Older comments', 'textdomain' ) ); ?></div>
		<div class="nav-next"><?php next_comments_link( esc_html__( 'Newer comments', 'textdomain' ) ); ?></div>
	</nav>
	<?php
endif;

Rules:

  • Only show comment navigation when there is more than one comment page.
  • Respect the page_comments option.
  • Give comment navigation an accessible name.
  • Do not build comment-page URLs manually.

Comment List Output

Prefer core comment output unless the design truly needs custom markup.

wp_list_comments(
	array(
		'style'       => 'ol',
		'short_ping'  => true,
		'avatar_size' => 48,
		'format'      => 'html5',
	)
);

Rules:

  • style => 'ol' should match an ordered-list wrapper.
  • Use format => 'html5' if the theme supports HTML5 comment markup.
  • Avoid custom callbacks/walkers for simple class or avatar-size changes.
  • If using a callback, escape author links, dates, edit links, and custom fields.
  • Preserve reply links and moderation notices.

Comment Form

Use comment_form() for the public comment form.

comment_form(
	array(
		'title_reply_before' => '<h2 id="reply-title" class="comment-reply-title">',
		'title_reply_after'  => '</h2>',
	)
);

Rules:

  • Do not hand-code a replacement form unless you are intentionally replacing core behavior.
  • Core handles logged-in state, required fields, cookies consent, form action, hidden comment fields, and closed comments.
  • If overriding fields, keep labels, required state, autocomplete attributes, and cookies consent behavior.
  • Escape any custom labels or descriptions.

Threaded Replies

Load comment-reply only when it can be used.

add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_comment_reply' );

function mytheme_enqueue_comment_reply() {
	if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
		wp_enqueue_script( 'comment-reply' );
	}
}

Rules:

  • Do not enqueue comment-reply globally.
  • The script belongs on wp_enqueue_scripts, not inside comments.php.
  • Threaded comments also need compatible wp_list_comments() output and reply links.

Closed Comments

Show a closed-comments message only when useful.

if ( ! comments_open() && get_comments_number() && post_type_supports( get_post_type(), 'comments' ) ) :
	?>
	<p class="no-comments"><?php esc_html_e( 'Comments are closed.', 'textdomain' ); ?></p>
	<?php
endif;

Do not show "Comments are closed" on every page with no discussion.

Review Checklist

  • Singular templates call comments_template() only when needed.
  • comments.php returns early for post_password_required().
  • Comment count headings are pluralized and escaped.
  • Comment pagination respects page_comments.
  • wp_list_comments() is used instead of raw comment loops.
  • comment_form() is used instead of a hand-built form.
  • comment-reply is conditionally enqueued.
  • Closed-comment messaging is not noisy.
  • Custom callbacks preserve reply links, moderation state, and escaping.
  • Custom comment queries do not expose comment_type = note.

Common Mistakes

  • Forgetting the password-protected post guard.
  • Building a custom public comment form and losing core hidden fields/consent behavior.
  • Loading comment-reply on every frontend request.
  • Rendering comment navigation when comments are not paginated.
  • Echoing get_the_title() raw inside the comments heading.
  • Using a <div> wrapper while asking wp_list_comments() for style => 'ol'.
  • Querying all comment types and leaking editor Notes into public output.

References

Files (wp-agent-skills)
  • SKILL.md 8 KB
    ---
    name: classic-theme-comments-discussion
    description: Build or audit classic theme comments output for WP 7.1. Covers `comments_template()`, `comments.php`, `post_password_required()`, `have_comments()`, `wp_list_comments()`, comment pagination, `comment_form()`, threaded comment reply script loading, closed-comment messaging, accessible comment navigation, excluding private editor Notes, escaping comment titles and labels, and common mistakes such as custom comment forms, missing password guards, loading `comment-reply` globally, broken callback walkers, or showing comments on unsupported post types.
    metadata:
      wp-skills-author: "Soczó Kristóf"
      wp-skills-contact: "mailto:lonsdale201@hotmail.com"
      wp-skills-plugin: "wordpress"
      wp-skills-plugin-version-tested: "7.0 - 7.1"
      wp-skills-wp-version-tested: "7.1"
      wp-skills-php-min: "7.4"
      wp-skills-last-updated: "2026-08-20"
    ---
    
    # Classic Theme Comments and Discussion
    
    Use this when adding or reviewing comments in a classic PHP theme: `comments.php`, comment list markup, comment pagination, the comment form, closed-comment states, and threaded reply behavior.
    
    ## When to Use This Skill
    
    - Creating or editing `comments.php`.
    - Calling `comments_template()` from `single.php`, `page.php`, or a singular template part.
    - Styling `wp_list_comments()` output or replacing a comment callback.
    - Loading `comment-reply`.
    - Fixing missing comment pagination, password-protected post leaks, or inaccessible comment navigation.
    
    ## Call Comments From Singular Templates
    
    In a singular template, call comments after the content when the post supports discussion.
    
    ```php
    if ( comments_open() || get_comments_number() ) {
    	comments_template();
    }
    ```
    
    Rules:
    
    - Do not call `comments_template()` on archives or search templates.
    - Check `comments_open()` or `get_comments_number()` before loading the template.
    - If a custom post type does not support comments, do not force comments into its template.
    - Keep the rendering code in `comments.php`.
    - Editor Notes use the comments table but are private editorial data. Do not use
      `type => all` in custom public queries or walkers; keep public theme output to
      ordinary comments/pings intentionally.
    
    `comments_template()` is designed for single/page contexts and returns early outside supported contexts unless `$withcomments` is set.
    
    ## comments.php Skeleton
    
    Start with the password guard. This prevents comment content from leaking on protected posts.
    
    ```php
    <?php
    if ( post_password_required() ) {
    	return;
    }
    ?>
    
    <section id="comments" class="comments-area" aria-label="<?php esc_attr_e( 'Comments', 'textdomain' ); ?>">
    	<?php if ( have_comments() ) : ?>
    		<h2 class="comments-title">
    			<?php
    			$comment_count = get_comments_number();
    
    			printf(
    				esc_html(
    					_nx(
    						'%1$s comment on "%2$s"',
    						'%1$s comments on "%2$s"',
    						$comment_count,
    						'comments title',
    						'textdomain'
    					)
    				),
    				esc_html( number_format_i18n( $comment_count ) ),
    				esc_html( get_the_title() )
    			);
    			?>
    		</h2>
    
    		<ol class="comment-list">
    			<?php
    			wp_list_comments(
    				array(
    					'style'      => 'ol',
    					'short_ping' => true,
    					'avatar_size' => 48,
    				)
    			);
    			?>
    		</ol>
    	<?php endif; ?>
    
    	<?php comment_form(); ?>
    </section>
    ```
    
    Rules:
    
    - Use `post_password_required()` before output.
    - Use `have_comments()` for the list state.
    - Use `number_format_i18n()` for counts.
    - Escape the post title when inserting it into a comment heading.
    - Use `comment_form()` unless there is a very specific reason not to.
    
    ## Comment Pagination
    
    If comment pagination is enabled, render navigation before and/or after the list.
    
    ```php
    if ( get_comment_pages_count() > 1 && get_option( 'page_comments' ) ) :
    	?>
    	<nav class="comment-navigation" aria-label="<?php esc_attr_e( 'Comment navigation', 'textdomain' ); ?>">
    		<h2 class="screen-reader-text"><?php esc_html_e( 'Comment navigation', 'textdomain' ); ?></h2>
    		<div class="nav-previous"><?php previous_comments_link( esc_html__( 'Older comments', 'textdomain' ) ); ?></div>
    		<div class="nav-next"><?php next_comments_link( esc_html__( 'Newer comments', 'textdomain' ) ); ?></div>
    	</nav>
    	<?php
    endif;
    ```
    
    Rules:
    
    - Only show comment navigation when there is more than one comment page.
    - Respect the `page_comments` option.
    - Give comment navigation an accessible name.
    - Do not build comment-page URLs manually.
    
    ## Comment List Output
    
    Prefer core comment output unless the design truly needs custom markup.
    
    ```php
    wp_list_comments(
    	array(
    		'style'       => 'ol',
    		'short_ping'  => true,
    		'avatar_size' => 48,
    		'format'      => 'html5',
    	)
    );
    ```
    
    Rules:
    
    - `style => 'ol'` should match an ordered-list wrapper.
    - Use `format => 'html5'` if the theme supports HTML5 comment markup.
    - Avoid custom callbacks/walkers for simple class or avatar-size changes.
    - If using a callback, escape author links, dates, edit links, and custom fields.
    - Preserve reply links and moderation notices.
    
    ## Comment Form
    
    Use `comment_form()` for the public comment form.
    
    ```php
    comment_form(
    	array(
    		'title_reply_before' => '<h2 id="reply-title" class="comment-reply-title">',
    		'title_reply_after'  => '</h2>',
    	)
    );
    ```
    
    Rules:
    
    - Do not hand-code a replacement form unless you are intentionally replacing core behavior.
    - Core handles logged-in state, required fields, cookies consent, form action, hidden comment fields, and closed comments.
    - If overriding fields, keep labels, `required` state, autocomplete attributes, and cookies consent behavior.
    - Escape any custom labels or descriptions.
    
    ## Threaded Replies
    
    Load `comment-reply` only when it can be used.
    
    ```php
    add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_comment_reply' );
    
    function mytheme_enqueue_comment_reply() {
    	if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
    		wp_enqueue_script( 'comment-reply' );
    	}
    }
    ```
    
    Rules:
    
    - Do not enqueue `comment-reply` globally.
    - The script belongs on `wp_enqueue_scripts`, not inside `comments.php`.
    - Threaded comments also need compatible `wp_list_comments()` output and reply links.
    
    ## Closed Comments
    
    Show a closed-comments message only when useful.
    
    ```php
    if ( ! comments_open() && get_comments_number() && post_type_supports( get_post_type(), 'comments' ) ) :
    	?>
    	<p class="no-comments"><?php esc_html_e( 'Comments are closed.', 'textdomain' ); ?></p>
    	<?php
    endif;
    ```
    
    Do not show "Comments are closed" on every page with no discussion.
    
    ## Review Checklist
    
    - Singular templates call `comments_template()` only when needed.
    - `comments.php` returns early for `post_password_required()`.
    - Comment count headings are pluralized and escaped.
    - Comment pagination respects `page_comments`.
    - `wp_list_comments()` is used instead of raw comment loops.
    - `comment_form()` is used instead of a hand-built form.
    - `comment-reply` is conditionally enqueued.
    - Closed-comment messaging is not noisy.
    - Custom callbacks preserve reply links, moderation state, and escaping.
    - Custom comment queries do not expose `comment_type = note`.
    
    ## Common Mistakes
    
    - Forgetting the password-protected post guard.
    - Building a custom public comment form and losing core hidden fields/consent behavior.
    - Loading `comment-reply` on every frontend request.
    - Rendering comment navigation when comments are not paginated.
    - Echoing `get_the_title()` raw inside the comments heading.
    - Using a `<div>` wrapper while asking `wp_list_comments()` for `style => 'ol'`.
    - Querying all comment types and leaking editor Notes into public output.
    
    ## References
    
    - Official documentation: <https://developer.wordpress.org/themes/classic-themes/templates/partial-and-miscellaneous-template-files/comment-template/>
    - Official documentation: <https://developer.wordpress.org/reference/functions/comment_form/>
    - Official documentation: <https://developer.wordpress.org/reference/functions/wp_list_comments/>
    - Related skill: `wordpress/wp-comments-notes-api` for Notes, notification,
      REST, and ping behavior.
    - Verified source paths:
      - `wp-includes/comment-template.php`
      - `wp-includes/script-loader.php`
      - `wp-content/themes/storefront/comments.php`
      - `wp-content/themes/generatepress/comments.php`
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related