Skip to main content

Course Progress

Loading...

🎯 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
This assignment will reinforce:
  • WordPress theme file structure
  • Required vs optional theme files
  • The WordPress Loop implementation
  • Theme metadata and configuration
  • Basic styling and responsive design
  • Theme testing and validation

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
  • Missing wp_head(): Always include in header before </head>
  • Missing wp_footer(): Always include before </body>
  • Hard-coded paths: Use get_template_directory_uri() instead
  • Not escaping output: Use esc_html(), esc_url(), etc.
  • Wrong text domain: Must match folder name
  • No content width: Set $content_width in functions.php
  • Forgetting prefixes: Prefix all functions with theme name
  • Not enqueueing properly: Never hard-code stylesheets

📤 Submission Instructions

  1. Zip your theme folder (not the files inside, the whole folder)
  2. Name the zip file: yourname-minimal-theme.zip
  3. Test the zip: Try installing it on a fresh WordPress site
  4. Submit via:
    • GitHub repository (preferred)
    • Course submission portal
    • Email to instructor
  5. 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?

You have all the knowledge and tools needed to create your first WordPress theme! Remember:

  • Start with the required files
  • Test frequently as you build
  • Ask for help if you get stuck
  • Have fun and be creative!

You've got this! 💪