🎯 Homework Assignment
Create a Minimal WordPress Theme
Build your first complete WordPress theme from scratch!
⏰ Due: Before Next Session
Assignment Overview
It's time to put everything you've learned into practice! You'll create a fully functional WordPress theme that meets all WordPress requirements and standards. Think of this as building your first house - it might be simple, but it needs to be solid and follow building codes!
Learning Goals
Project Requirements
Your minimal theme must include the following components:
1
📄
Required Files
- style.css - With complete theme header
- index.php - Main template file
- screenshot.png - 1200×900px
2
🎨
Theme Information
- Unique theme name
- Your name as author
- Version 1.0.0
- Meaningful description
- GPL v2 license
3
🔄
The Loop
- Display posts correctly
- Handle no posts found
- Show post title & content
- Display post metadata
4
💅
Styling (20+ Rules)
- Typography styles
- Layout structure
- Color scheme
- Responsive design
5
⚙️
Functions.php
- Theme setup function
- Enqueue stylesheet
- Add theme support
- Set content width
6
✅
Validation
- Pass Theme Check plugin
- No PHP errors
- Valid HTML output
- Works in 3+ browsers
File Structure
Your theme folder should be organized like this:
my-minimal-theme/
├── style.css (REQUIRED - Theme information and styles)
├── index.php (REQUIRED - Main template)
├── screenshot.png (REQUIRED - 1200×900px preview)
├── functions.php (REQUIRED - Theme setup)
├── header.php (OPTIONAL - Header template)
├── footer.php (OPTIONAL - Footer template)
├── sidebar.php (OPTIONAL - Sidebar template)
├── single.php (OPTIONAL - Single post template)
├── page.php (OPTIONAL - Page template)
└── README.md (OPTIONAL - Documentation)
Starter Templates
Use these templates as your starting point:
📝 style.css Template
/*
Theme Name: My Minimal Theme
Theme URI: https://yourwebsite.com/themes/my-minimal-theme
Author: Your Name
Author URI: https://yourwebsite.com
Description: A clean and minimal WordPress theme created as a learning project. Features responsive design, semantic HTML5 markup, and modern CSS styling. Perfect for blogs and simple websites.
Version: 1.0.0
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: my-minimal-theme
Tags: blog, one-column, custom-colors, custom-menu, featured-images, threaded-comments, translation-ready
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned.
*/
/* =Reset & Base Styles
-------------------------------------------------------------- */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
font-size: 16px;
line-height: 1.6;
color: #333;
background: #fff;
}
/* =Layout
-------------------------------------------------------------- */
.site-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* =Header
-------------------------------------------------------------- */
.site-header {
background: #2c3e50;
color: #fff;
padding: 2rem 0;
margin-bottom: 2rem;
}
.site-title {
font-size: 2.5rem;
margin: 0;
font-weight: bold;
}
.site-title a {
color: #fff;
text-decoration: none;
}
.site-description {
font-size: 1.1rem;
opacity: 0.9;
margin-top: 0.5rem;
}
/* =Navigation
-------------------------------------------------------------- */
.main-navigation {
background: #34495e;
margin-bottom: 2rem;
}
.main-navigation ul {
list-style: none;
display: flex;
flex-wrap: wrap;
}
.main-navigation li {
margin-right: 2rem;
}
.main-navigation a {
color: #ecf0f1;
text-decoration: none;
padding: 1rem 0;
display: block;
transition: color 0.3s ease;
}
.main-navigation a:hover {
color: #3498db;
}
/* =Content
-------------------------------------------------------------- */
.site-main {
margin-bottom: 3rem;
}
article {
margin-bottom: 3rem;
padding-bottom: 2rem;
border-bottom: 1px solid #ecf0f1;
}
.entry-header {
margin-bottom: 1.5rem;
}
.entry-title {
font-size: 2rem;
margin-bottom: 0.5rem;
color: #2c3e50;
}
.entry-title a {
color: inherit;
text-decoration: none;
transition: color 0.3s ease;
}
.entry-title a:hover {
color: #3498db;
}
.entry-meta {
color: #7f8c8d;
font-size: 0.9rem;
}
.entry-content {
margin-bottom: 1.5rem;
}
.entry-content p {
margin-bottom: 1.25rem;
}
.entry-content h2 {
margin: 2rem 0 1rem;
color: #2c3e50;
}
.entry-content img {
max-width: 100%;
height: auto;
}
/* =Footer
-------------------------------------------------------------- */
.site-footer {
background: #2c3e50;
color: #ecf0f1;
padding: 2rem 0;
text-align: center;
}
/* =Responsive Design
-------------------------------------------------------------- */
@media (max-width: 768px) {
.site-title {
font-size: 2rem;
}
.main-navigation ul {
flex-direction: column;
}
.main-navigation li {
margin-right: 0;
}
}
📝 index.php Template
<?php
/**
* The main template file
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
*
* @package My_Minimal_Theme
*/
get_header(); ?>
<div class="site-container">
<main id="primary" class="site-main">
<?php
if ( have_posts() ) :
// Display page title if on blog page
if ( is_home() && ! is_front_page() ) :
?>
<header class="page-header">
<h1 class="page-title"><?php single_post_title(); ?></h1>
</header>
<?php
endif;
// Start the Loop
while ( have_posts() ) :
the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php
if ( is_singular() ) :
the_title( '<h1 class="entry-title">', '</h1>' );
else :
the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );
endif;
?>
<div class="entry-meta">
<span class="posted-on">
Posted on <time datetime="<?php echo esc_attr( get_the_date( 'c' ) ); ?>">
<?php echo esc_html( get_the_date() ); ?>
</time>
</span>
<span class="posted-by">
by <a href="<?php echo esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ); ?>">
<?php echo esc_html( get_the_author() ); ?>
</a>
</span>
<?php
// Display categories
$categories_list = get_the_category_list( ', ' );
if ( $categories_list ) :
?>
<span class="cat-links">
in <?php echo $categories_list; ?>
</span>
<?php
endif;
?>
</div>
</header>
<div class="entry-content">
<?php
if ( is_singular() ) :
the_content();
// Display pagination for multi-page posts
wp_link_pages( array(
'before' => '<div class="page-links">Pages: ',
'after' => '</div>',
) );
else :
// Display excerpt for archives
the_excerpt();
?>
<a href="<?php echo esc_url( get_permalink() ); ?>" class="read-more">
Continue reading →
</a>
<?php
endif;
?>
</div>
<footer class="entry-footer">
<?php
// Display tags
$tags_list = get_the_tag_list( '', ', ' );
if ( $tags_list ) :
?>
<span class="tags-links">
Tagged: <?php echo $tags_list; ?>
</span>
<?php
endif;
// Display comments link
if ( ! is_singular() && comments_open() ) :
?>
<span class="comments-link">
<?php comments_popup_link( 'Leave a comment', '1 Comment', '% Comments' ); ?>
</span>
<?php
endif;
?>
</footer>
</article>
<?php
endwhile;
// Display pagination
the_posts_pagination( array(
'mid_size' => 2,
'prev_text' => '← Previous',
'next_text' => 'Next →',
) );
else :
// No posts found
?>
<article class="no-results not-found">
<header class="page-header">
<h1 class="page-title">Nothing Found</h1>
</header>
<div class="page-content">
<?php
if ( is_home() && current_user_can( 'publish_posts' ) ) :
?>
<p>Ready to publish your first post?
<a href="<?php echo esc_url( admin_url( 'post-new.php' ) ); ?>">
Get started here
</a>.</p>
<?php
elseif ( is_search() ) :
?>
<p>Sorry, but nothing matched your search terms.
Please try again with different keywords.</p>
<?php
get_search_form();
else :
?>
<p>It seems we can't find what you're looking for.
Perhaps searching can help.</p>
<?php
get_search_form();
endif;
?>
</div>
</article>
<?php
endif;
?>
</main>
</div>
<?php
get_sidebar();
get_footer();
📝 functions.php Template
<?php
/**
* Theme functions and definitions
*
* @package My_Minimal_Theme
*/
// Set content width
if ( ! isset( $content_width ) ) {
$content_width = 800;
}
/**
* Theme setup
*/
function my_minimal_theme_setup() {
// Add default posts and comments RSS feed links
add_theme_support( 'automatic-feed-links' );
// Let WordPress manage the document title
add_theme_support( 'title-tag' );
// Enable support for Post Thumbnails
add_theme_support( 'post-thumbnails' );
// Register navigation menu
register_nav_menus( array(
'primary' => __( 'Primary Menu', 'my-minimal-theme' ),
) );
// Switch default core markup to output valid HTML5
add_theme_support( 'html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
'style',
'script',
) );
// Add theme support for selective refresh for widgets
add_theme_support( 'customize-selective-refresh-widgets' );
// Add support for core custom logo
add_theme_support( 'custom-logo', array(
'height' => 250,
'width' => 250,
'flex-width' => true,
'flex-height' => true,
) );
}
add_action( 'after_setup_theme', 'my_minimal_theme_setup' );
/**
* Enqueue scripts and styles
*/
function my_minimal_theme_scripts() {
// Enqueue main stylesheet
wp_enqueue_style(
'my-minimal-theme-style',
get_stylesheet_uri(),
array(),
wp_get_theme()->get( 'Version' )
);
// Enqueue comment reply script on singular pages
if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
wp_enqueue_script( 'comment-reply' );
}
}
add_action( 'wp_enqueue_scripts', 'my_minimal_theme_scripts' );
/**
* Register widget area
*/
function my_minimal_theme_widgets_init() {
register_sidebar( array(
'name' => __( 'Sidebar', 'my-minimal-theme' ),
'id' => 'sidebar-1',
'description' => __( 'Add widgets here.', 'my-minimal-theme' ),
'before_widget' => '<section id="%1$s" class="widget %2$s">',
'after_widget' => '</section>',
'before_title' => '<h2 class="widget-title">',
'after_title' => '</h2>',
) );
}
add_action( 'widgets_init', 'my_minimal_theme_widgets_init' );
Submission Checklist
Before submitting your theme, make sure you've completed everything:
✅ Pre-Submission Checklist
Testing Your Theme
Grading Rubric
Your theme will be evaluated based on the following criteria:
| Component | Requirements | Points |
|---|---|---|
| Theme Files | All required files present and properly named | 20 |
| Theme Header | Complete and valid theme information in style.css | 15 |
| The Loop | Correctly implements WordPress Loop with proper output | 20 |
| Styling | Minimum 20 CSS rules, responsive design | 15 |
| Functions | Proper theme setup, enqueue, and support features | 15 |
| Validation | Passes Theme Check, no PHP errors | 10 |
| Screenshot | 1200×900px, represents theme accurately | 5 |
| Total | 100 | |
💡 Pro Tips for Success
- Start Simple: Get the basics working before adding complexity
- Test Often: Activate your theme frequently to catch errors early
- Use Debug Mode: Enable WP_DEBUG to see all errors and warnings
- Check Browser Console: Look for JavaScript errors that might affect display
- Validate HTML: Use W3C validator to ensure proper markup
- Mobile First: Design for mobile, then enhance for larger screens
- Comment Your Code: Explain complex sections for future reference
- Version Control: Use Git to track changes and revert if needed
🌟 Bonus Challenges (Extra Credit)
Want to go above and beyond? Try these optional enhancements:
- Custom Header (+5 points): Add customizable header image support
- Custom Colors (+5 points): Implement Customizer color options
- Widget Area (+5 points): Add a functional sidebar with widgets
- Custom Menu (+5 points): Implement wp_nav_menu() properly
- Translation Ready (+5 points): Use proper text domain functions
- Accessibility (+5 points): Add skip links and ARIA labels
- Custom Logo (+5 points): Add custom logo support
- Dark Mode (+10 points): Implement a dark mode toggle
Common Mistakes to Avoid
Watch Out For These Issues
📤 Submission Instructions
- Zip your theme folder (not the files inside, the whole folder)
- Name the zip file: yourname-minimal-theme.zip
- Test the zip: Try installing it on a fresh WordPress site
- Submit via:
- GitHub repository (preferred)
- Course submission portal
- Email to instructor
- Include README.md with:
- Your name and date
- Theme features list
- Any bonus features attempted
- Known issues or limitations
- Testing browsers used
Helpful Resources
Ready to Build?