Skip to main content

Course Progress

Loading...

Creating a Basic Theme Structure

Duration: 50 minutes
Module 5: Session 1

Learning Objectives

  • Understand the minimum required files for a WordPress theme
  • Create proper theme metadata in style.css
  • Build a functional index.php template
  • Design and implement a theme screenshot
  • Organize theme files following WordPress best practices

Introduction

Creating a WordPress theme is like building a house - you need a solid foundation before adding walls, windows, and decorations. Today, we'll lay that foundation by creating the essential files every WordPress theme must have.

🏗️
Building Analogy
If WordPress is the land, and your content is the furniture, then your theme is the house itself - it determines how everything looks and where everything goes!

The Two Required Files

WordPress requires only TWO files for a theme to be recognized. Think of these as the birth certificate and the body of your theme:

flowchart TD
    A[WordPress Theme] --> B[style.css]
    A --> C[index.php]
    
    B --> B1[Theme Information]
    B --> B2[Theme Name]
    B --> B3[Author Details]
    B --> B4[Version]
    
    C --> C1[Template Logic]
    C --> C2[HTML Output]
    C --> C3[The Loop]
    
    style B fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
    style C fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
                                    

📄style.css REQUIRED

This file serves two critical purposes:

  • Theme Declaration: Contains metadata that tells WordPress "I'm a theme!"
  • Styling: Contains all your CSS rules (though you can also use separate CSS files)

📄index.php REQUIRED

The ultimate fallback template - if WordPress can't find a more specific template, it uses index.php. Think of it as the "catch-all" template.

Creating style.css with Theme Metadata

The style.css file must start with a special comment block that contains your theme's information. This is like your theme's passport - it identifies who made it, what it's called, and other vital information:

/*
Theme Name: My Awesome Theme
Theme URI: https://example.com/my-awesome-theme
Author: Your Name
Author URI: https://yourwebsite.com
Description: A beautiful and responsive WordPress theme that showcases modern design principles and best practices. Perfect for blogs, portfolios, and business websites.
Version: 1.0.0
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: my-awesome-theme
Tags: blog, portfolio, custom-colors, custom-menu, featured-images, responsive-layout, translation-ready
*/

/* Theme styles start here */
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
    line-height: 1.6;
    color: #333;
    margin: 0;
    padding: 0;
}

.site-header {
    background: #2c3e50;
    color: white;
    padding: 2rem 0;
}

.site-title {
    margin: 0;
    font-size: 2rem;
}

.site-main {
    max-width: 1200px;
    margin: 2rem auto;
    padding: 0 1rem;
}

article {
    margin-bottom: 3rem;
}

.entry-title {
    color: #2c3e50;
    margin-bottom: 1rem;
}

.entry-meta {
    color: #7f8c8d;
    font-size: 0.9rem;
    margin-bottom: 1rem;
}
⚠️
Important Note
The comment block MUST be at the very top of style.css - even a single blank line before it will cause WordPress to not recognize your theme!

Building index.php

The index.php file is your theme's workhorse. It needs to handle displaying posts, pages, and any other content type. Here's a complete, functional index.php:

<?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).
 *
 * @package My_Awesome_Theme
 */

get_header(); ?>

<main id="primary" class="site-main">
    <div class="container">
        
        <?php if ( have_posts() ) : ?>
            
            <?php if ( is_home() && ! is_front_page() ) : ?>
                <header class="page-header">
                    <h1 class="page-title"><?php single_post_title(); ?></h1>
                </header>
            <?php endif; ?>
            
            <?php
            // 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 <?php the_author_posts_link(); ?>
                            </span>
                        </div>
                    </header>
                    
                    <div class="entry-content">
                        <?php
                        if ( is_singular() ) :
                            the_content();
                            
                            wp_link_pages( array(
                                'before' => '<div class="page-links">Pages:',
                                'after'  => '</div>',
                            ) );
                        else :
                            the_excerpt();
                            ?>
                            <a href="<?php echo esc_url( get_permalink() ); ?>" class="read-more">
                                Continue reading →
                            </a>
                            <?php
                        endif;
                        ?>
                    </div>
                    
                    <footer class="entry-footer">
                        <?php
                        $categories = get_the_category_list( ', ' );
                        if ( $categories ) :
                            ?>
                            <span class="cat-links">
                                Categories: <?php echo $categories; ?>
                            </span>
                            <?php
                        endif;
                        
                        $tags = get_the_tag_list( '', ', ' );
                        if ( $tags ) :
                            ?>
                            <span class="tags-links">
                                Tags: <?php echo $tags; ?>
                            </span>
                            <?php
                        endif;
                        ?>
                    </footer>
                </article>
                
                <?php
            endwhile;
            
            // Pagination
            the_posts_pagination( array(
                'mid_size'  => 2,
                'prev_text' => '← Previous',
                'next_text' => 'Next →',
            ) );
            
        else :
            ?>
            
            <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(); ?>
                    <?php else : ?>
                        <p>It seems we can't find what you're looking for. 
                        Perhaps searching can help.</p>
                        <?php get_search_form(); ?>
                    <?php endif; ?>
                </div>
            </article>
            
        <?php endif; ?>
        
    </div>
</main>

<?php
get_sidebar();
get_footer();

Understanding The Loop

The Loop is WordPress's way of cycling through posts. Think of it like a playlist:

Creating a Theme Screenshot

The screenshot.png file is your theme's visual identity in the WordPress admin. It's like the cover of a book - it should accurately represent your theme's design:

Screenshot Best Practices

  • Dimensions: Exactly 1200px × 900px (WordPress will resize as needed)
  • Format: PNG format for best quality
  • Content: Show actual theme design, not logos or mockups
  • Quality: Use high-quality images and clear typography
  • Representation: Must accurately represent your theme's appearance
<!-- How to create a screenshot -->
1. Set up your theme with sample content
2. Navigate to your homepage
3. Use browser DevTools to set viewport to 1200px wide
4. Take a full-page screenshot
5. Crop to exactly 1200px × 900px
6. Save as screenshot.png in your theme root

<!-- Tools you can use: -->
- Chrome DevTools (Device Mode)
- Firefox Screenshot tool
- Photoshop/GIMP for editing
- Online tools like Canva or Figma

Complete Theme Directory Structure

While only two files are required, a professional theme needs proper organization. Here's the recommended structure:

graph TD
    A[my-awesome-theme/] --> B[style.css]
    A --> C[index.php]
    A --> D[screenshot.png]
    A --> E[functions.php]
    A --> F[header.php]
    A --> G[footer.php]
    A --> H[sidebar.php]
    A --> I[assets/]
    A --> J[template-parts/]
    A --> K[inc/]
    
    I --> I1[css/]
    I --> I2[js/]
    I --> I3[images/]
    I --> I4[fonts/]
    
    J --> J1[content/]
    J --> J2[header/]
    J --> J3[footer/]
    
    K --> K1[customizer.php]
    K --> K2[template-functions.php]
    K --> K3[template-tags.php]
    
    style B fill:#fef3c7,stroke:#f59e0b,stroke-width:3px
    style C fill:#dbeafe,stroke:#3b82f6,stroke-width:3px
    style D fill:#fce7f3,stroke:#ec4899,stroke-width:2px
                                    
💡
Pro Organization Tip
  • /assets/ - All static resources (CSS, JS, images)
  • /template-parts/ - Reusable template components
  • /inc/ - PHP includes and functionality
  • /languages/ - Translation files

Testing Your Basic Theme

Once you've created your files, let's verify everything works:

<?php
// Quick test checklist:

// 1. Theme appears in WordPress admin?
// Navigate to Appearance > Themes

// 2. Screenshot displays correctly?
// Check the theme thumbnail

// 3. Theme activates without errors?
// Click "Activate" and check for PHP errors

// 4. Content displays on frontend?
// Visit your site and verify posts appear

// 5. Basic styling applied?
// Check that your CSS from style.css is loading

// Debug helper - add to index.php temporarily:
echo '<!-- Theme is loading correctly -->';
echo '<!-- Template: ' . basename(__FILE__) . ' -->';
echo '<!-- Theme directory: ' . get_template_directory_uri() . ' -->';

What You Should See

After activating your theme, you should see:

  • ✅ Your site title at the top
  • ✅ Posts displaying with titles and content
  • ✅ Post metadata (date, author, categories)
  • ✅ Pagination links if you have multiple posts
  • ✅ Your custom styles from style.css applied

Practice Exercise

Let's build a minimal theme together:

💻
Hands-On Practice
  1. Create a new folder: practice-theme
  2. Add style.css with your own theme information
  3. Create index.php with a simplified Loop
  4. Add at least 5 CSS rules in style.css
  5. Create a 1200×900px screenshot.png
  6. Activate the theme and verify it works
  7. Bonus: Add a custom color scheme!
<?php
// Minimal index.php starter
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
    <meta charset="<?php bloginfo( 'charset' ); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
    <header>
        <h1><?php bloginfo( 'name' ); ?></h1>
        <p><?php bloginfo( 'description' ); ?></p>
    </header>
    
    <main>
        <?php
        if ( have_posts() ) :
            while ( have_posts() ) : the_post();
                ?>
                <article>
                    <h2><?php the_title(); ?></h2>
                    <?php the_content(); ?>
                </article>
                <?php
            endwhile;
        endif;
        ?>
    </main>
    
    <?php wp_footer(); ?>
</body>
</html>

Practice Assignment

Create your first complete WordPress theme with the following requirements:

  • Create a theme folder with your name (e.g., "johns-first-theme")
  • Include properly formatted style.css with all recommended metadata
  • Build an index.php that displays posts, handles no content, and includes pagination
  • Add at least 20 CSS rules for basic styling
  • Create a professional screenshot.png (1200×900px)
  • Include helpful code comments explaining your logic
  • Test with at least 5 posts and 2 pages
  • Bonus: Add a custom Google Font via functions.php

Additional Resources