📚 Homework: Build a Complete Blog Listing
Apply everything you've learned about The Loop, template tags, custom queries, and pagination
Create a professional blog listing page with advanced features
Assignment Overview
In this homework assignment, you'll create a comprehensive blog listing page that demonstrates your mastery of WordPress content display techniques. You'll implement custom loops, template tags, pagination, and create a professional, user-friendly design.
Estimated Time: 4-6 hours
Due Date: End of Module 5
Points: 100 points (+ 20 bonus points available)
📋 Core Requirements
1 Create a Custom Home Page Template
Build a custom page template (template-blog-home.php) with the following sections:
- Hero section with site title and description
- Featured post section (1 large featured post)
- Recent posts grid (6 posts in 2x3 or 3x2 layout)
- Category-specific sections (posts from 2 different categories)
2 Implement Multiple Custom Queries
Use WP_Query to create at least 4 different custom queries:
- Featured post query (meta field or sticky post)
- Recent posts query (excluding featured)
- Category-specific queries
- Popular posts query (by comment count or views)
3 Display Complete Post Information
For each post, display using appropriate template tags:
- Post title with permalink
- Featured image (with fallback)
- Author name with link to author archive
- Publication date (formatted)
- Categories and tags
- Excerpt or trimmed content
- Read more link
- Comment count
4 Create an Archive Template
Build an archive.php template with:
- Standard WordPress Loop
- Archive title and description
- Post cards in a grid layout
- Sidebar with widgets
5 Implement Pagination
Add pagination to your archive template:
- Numbered pagination using paginate_links()
- Proper styling for pagination
- Mobile-responsive pagination
- Previous/Next links on single posts
6 Add a Single Post Template
Create or enhance single.php with:
- Full post content display
- Author bio section
- Related posts section
- Post navigation (previous/next)
- Comments template
📦 Deliverables
Starter Code Templates
template-blog-home.php Structure
<?php
/**
* Template Name: Blog Home
* Description: Custom blog homepage with multiple sections
*/
get_header();
?>
<main id="primary" class="site-main">
<!-- Hero Section -->
<section class="hero-section">
<div class="container">
<h1><?php bloginfo('name'); ?></h1>
<p><?php bloginfo('description'); ?></p>
</div>
</section>
<!-- Featured Post Section -->
<section class="featured-post">
<div class="container">
<h2>Featured Post</h2>
<?php
// Query for featured post
$featured_args = array(
'posts_per_page' => 1,
'meta_key' => 'featured',
'meta_value' => 'yes',
// OR use sticky posts
// 'post__in' => get_option('sticky_posts'),
// 'ignore_sticky_posts' => 1
);
$featured_query = new WP_Query($featured_args);
if ($featured_query->have_posts()) :
while ($featured_query->have_posts()) : $featured_query->the_post();
// Display featured post
get_template_part('template-parts/content', 'featured');
endwhile;
wp_reset_postdata();
endif;
?>
</div>
</section>
<!-- Recent Posts Grid -->
<section class="recent-posts">
<div class="container">
<h2>Recent Posts</h2>
<div class="posts-grid">
<?php
// Query for recent posts
$recent_args = array(
'posts_per_page' => 6,
'post__not_in' => get_option('sticky_posts'),
);
$recent_query = new WP_Query($recent_args);
if ($recent_query->have_posts()) :
while ($recent_query->have_posts()) : $recent_query->the_post();
// Display post card
get_template_part('template-parts/content', 'card');
endwhile;
wp_reset_postdata();
endif;
?>
</div>
</div>
</section>
<!-- Category Sections -->
<?php
// Add more sections for different categories
$categories = array('news', 'tutorials'); // Your category slugs
foreach ($categories as $cat_slug) :
$category = get_category_by_slug($cat_slug);
if ($category) :
?>
<section class="category-section">
<div class="container">
<h2><?php echo esc_html($category->name); ?></h2>
<div class="posts-list">
<?php
$cat_args = array(
'category_name' => $cat_slug,
'posts_per_page' => 4,
);
$cat_query = new WP_Query($cat_args);
if ($cat_query->have_posts()) :
while ($cat_query->have_posts()) : $cat_query->the_post();
get_template_part('template-parts/content', 'list');
endwhile;
wp_reset_postdata();
endif;
?>
</div>
<a href="<?php echo get_category_link($category->term_id); ?>" class="view-all">
View all in <?php echo esc_html($category->name); ?> →
</a>
</div>
</section>
<?php
endif;
endforeach;
?>
</main>
<?php
get_footer();
?>
template-parts/content-card.php
<article id="post-<?php the_ID(); ?>" <?php post_class('post-card'); ?>>
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
</div>
<?php else : ?>
<div class="post-thumbnail placeholder">
<a href="<?php the_permalink(); ?>">
<img src="<?php echo get_template_directory_uri(); ?>/images/placeholder.jpg" alt="<?php the_title_attribute(); ?>">
</a>
</div>
<?php endif; ?>
<div class="post-content">
<header class="entry-header">
<?php the_title('<h3 class="entry-title"><a href="' . esc_url(get_permalink()) . '">', '</a></h3>'); ?>
<div class="entry-meta">
<span class="author">
By <?php the_author_posts_link(); ?>
</span>
<span class="date">
<?php echo get_the_date(); ?>
</span>
<span class="comments">
<?php comments_number('0', '1', '%'); ?> Comments
</span>
</div>
</header>
<div class="entry-excerpt">
<?php
if (has_excerpt()) {
the_excerpt();
} else {
echo wp_trim_words(get_the_content(), 20);
}
?>
</div>
<footer class="entry-footer">
<div class="categories">
<?php the_category(', '); ?>
</div>
<a href="<?php the_permalink(); ?>" class="read-more">
Read More →
</a>
</footer>
</div>
</article>
CSS Grid Layout Starter
/* Posts Grid Layout */
.posts-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
margin: 2rem 0;
}
.post-card {
background: #fff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.post-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.post-thumbnail {
aspect-ratio: 16/9;
overflow: hidden;
}
.post-thumbnail img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
.post-card:hover .post-thumbnail img {
transform: scale(1.05);
}
.post-content {
padding: 1.5rem;
}
.entry-title {
margin: 0 0 0.5rem;
font-size: 1.25rem;
}
.entry-title a {
color: #333;
text-decoration: none;
}
.entry-title a:hover {
color: #007cba;
}
.entry-meta {
display: flex;
gap: 1rem;
font-size: 0.875rem;
color: #666;
margin-bottom: 1rem;
}
.entry-excerpt {
color: #555;
line-height: 1.6;
margin-bottom: 1rem;
}
.entry-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.categories a {
background: #f0f0f0;
padding: 0.25rem 0.75rem;
border-radius: 4px;
text-decoration: none;
font-size: 0.875rem;
color: #555;
}
.read-more {
color: #007cba;
text-decoration: none;
font-weight: 600;
}
/* Responsive Design */
@media (max-width: 768px) {
.posts-grid {
grid-template-columns: 1fr;
}
}
@media (min-width: 769px) and (max-width: 1024px) {
.posts-grid {
grid-template-columns: repeat(2, 1fr);
}
}
🌟 Bonus Challenges (20 extra points)
AJAX Load More (+10 points)
Implement AJAX "Load More" functionality instead of traditional pagination:
- Load more button that fetches additional posts
- Smooth animation when new posts appear
- Loading indicator
- Disable button when no more posts
Advanced Filtering (+10 points)
Add filtering capabilities to your archive page:
- Filter by category dropdown
- Filter by tag
- Sort options (date, title, popularity)
- Search within results
Grading Rubric
| Component | Description | Points |
|---|---|---|
| Custom Home Template | Complete template with all required sections | 20 |
| Custom Queries | Proper use of WP_Query with wp_reset_postdata() | 20 |
| Template Tags | Correct usage of all required template tags | 15 |
| Archive Template | Functional archive with proper Loop | 15 |
| Pagination | Working pagination with proper styling | 10 |
| Single Post Template | Complete single post display with navigation | 10 |
| Code Quality | Clean, commented, properly formatted code | 5 |
| Design & UX | Professional appearance and user experience | 5 |
| Total | 100 | |
📤 Submission Guidelines
- Create a ZIP file containing your entire theme folder
- Name your file: firstname_lastname_blog_listing.zip
- Include a README.md with:
- Your name and date
- Any special features you implemented
- Known issues or incomplete features
- Bonus challenges attempted
- Test your theme with Theme Check plugin before submission
- Submit via the course management system
💡 Tips for Success
Start with Structure
Create all your template files first with basic structure, then add functionality incrementally.
Use Template Parts
Create reusable template parts for post cards, headers, and other repeated elements to maintain DRY principles.
Test with Different Content
Test your templates with posts that have different lengths, with and without featured images, and various numbers of categories/tags.
Mobile-First Design
Ensure your blog listing looks great on mobile devices. Test responsive breakpoints thoroughly.
Performance Matters
Optimize your queries and consider using transients for expensive operations like popular posts.