A WordPress theme controls how a site looks and how its content is laid out. Plugins add features; themes handle presentation. Building your own theme is one of the most practical skills for a front-end developer in India, because so many business, school and tourism websites run on WordPress.
Today there are two ways to build a theme: the original classic theme written with PHP templates, and the newer block theme built from HTML templates made of blocks and edited in the Site Editor. This guide to WordPress theme development explains both, shows the minimum files for each, and helps you decide where to start.
Classic themes vs block themes
| Classic theme | Block theme | |
|---|---|---|
| Templates written in | PHP files (index.php, single.php…) | HTML files containing block markup (templates/index.html…) |
| Required files | style.css and index.php | style.css and templates/index.html |
| Site-wide editing | Customizer, widgets and menus screens | Site Editor: templates, template parts, styles, navigation |
| Global styles | Mostly your own CSS; theme.json optional | theme.json is central for settings and styles |
| Skills needed | PHP, HTML, CSS | Mainly HTML, CSS and JSON; PHP for extras |
| Who edits the layout | Mostly developers | Developers and site owners, visually |
The WordPress developer documentation describes block themes as the modern way to build themes, while classic themes remain fully supported. Many existing sites and commercial themes are still classic, so knowing both is valuable for WordPress theme development work.
Before you start
- A local WordPress install – for example using XAMPP, or a local development tool of your choice.
- A code editor and basic HTML and CSS.
- For classic themes, some PHP: PHP Syntax and Variables, PHP Functions and PHP Include and Files.
- Debugging turned on in
wp-config.phpon your local site:define( 'WP_DEBUG', true );
Themes live in wp-content/themes/your-theme-folder/. Once the required files exist, the theme appears under Appearance → Themes.
style.css: the theme header
Both theme types need a style.css with a comment header at the top. WordPress reads it to show the theme name and details. Only Theme Name is strictly required, but fill in the rest for a professional theme.
/*
Theme Name: Kolam Starter
Author: Your Name
Description: A simple starter theme for learning.
Version: 1.0.0
Requires at least: 6.6
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: kolam-starter
*/Building a minimal classic theme
A classic theme needs style.css and index.php. In practice you will also add functions.php, header.php and footer.php.
functions.php
This file runs on every page load. Use it to declare theme features and load your CSS and JavaScript properly (never hard-code <link> tags for theme assets).
<?php
function kolam_setup() {
add_theme_support( 'title-tag' );
add_theme_support( 'post-thumbnails' );
register_nav_menus( array(
'primary' => __( 'Primary Menu', 'kolam-starter' ),
) );
}
add_action( 'after_setup_theme', 'kolam_setup' );
function kolam_assets() {
wp_enqueue_style(
'kolam-style',
get_stylesheet_uri(),
array(),
wp_get_theme()->get( 'Version' )
);
}
add_action( 'wp_enqueue_scripts', 'kolam_assets' );(no visible output – registers theme features and the stylesheet)
header.php, index.php and footer.php
<!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(); ?>>
<?php wp_body_open(); ?>
<header class="site-header">
<a href="<?php echo esc_url( home_url( '/' ) ); ?>"><?php bloginfo( 'name' ); ?></a>
<?php wp_nav_menu( array( 'theme_location' => 'primary' ) ); ?>
</header>(outputs the document head, opening body and site header)
<?php get_header(); ?>
<main class="site-main">
<?php if ( have_posts() ) : ?>
<?php while ( have_posts() ) : the_post(); ?>
<article <?php post_class(); ?>>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
</article>
<?php endwhile; ?>
<?php the_posts_pagination(); ?>
<?php else : ?>
<p><?php esc_html_e( 'No posts found.', 'kolam-starter' ); ?></p>
<?php endif; ?>
</main>
<?php get_footer(); ?>(prints each post title as a link, followed by its excerpt)
<footer class="site-footer">
<p>© <?php echo esc_html( date_i18n( 'Y' ) ); ?> <?php bloginfo( 'name' ); ?></p>
</footer>
<?php wp_footer(); ?>
</body>
</html>(prints the footer and closes the document)
Watch out: Never forget wp_head() and wp_footer(). WordPress and plugins use them to add styles, scripts and the admin bar. Missing them is the most common reason a plugin “does not work” in a custom theme.
The template hierarchy
WordPress chooses which template file to use for each request by looking for specific files first and falling back to more general ones, ending at index.php. A few examples:
| Request | Files checked (in order, simplified) |
|---|---|
| A single blog post | single-post.php → single.php → singular.php → index.php |
| A page | page-{slug}.php → page.php → singular.php → index.php |
| A category archive | category-{slug}.php → category.php → archive.php → index.php |
| Search results | search.php → index.php |
| Not found | 404.php → index.php |
Block themes use the same hierarchy, but with .html files in the templates folder, such as templates/single.html.
Building a minimal block theme
A block theme needs style.css and templates/index.html. The recommended structure adds a parts folder for template parts like the header and footer, a patterns folder for reusable block patterns, a styles folder for style variations, and a theme.json file.
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
<!-- wp:query {"query":{"inherit":true}} -->
<div class="wp-block-query">
<!-- wp:post-template -->
<!-- wp:post-title {"isLink":true} /-->
<!-- wp:post-excerpt /-->
<!-- /wp:post-template -->
</div>
<!-- /wp:query -->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->The HTML comments are block delimiters. WordPress reads them to know which block each piece is and what settings it has. You rarely write long templates by hand – a common workflow is to design in the Site Editor and then copy or export the templates into your theme files.
theme.json: settings and styles in one file
theme.json defines your colour palette, font sizes, spacing scale, layout widths and default styles for blocks. The editor reads it, so site owners only see the colours and sizes you allow. The current schema is version 3, which works with WordPress 6.6 or later. It can also be used in classic themes.
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"color": {
"palette": [
{ "slug": "primary", "color": "#1f4fd1", "name": "Primary" },
{ "slug": "base", "color": "#ffffff", "name": "Base" },
{ "slug": "contrast", "color": "#1d1d1f", "name": "Contrast" }
]
},
"layout": { "contentSize": "720px", "wideSize": "1200px" }
},
"styles": {
"color": { "background": "var(--wp--preset--color--base)", "text": "var(--wp--preset--color--contrast)" },
"elements": {
"link": { "color": { "text": "var(--wp--preset--color--primary)" } }
}
}
}WordPress turns each palette entry into a CSS custom property such as --wp--preset--color--primary, which you can use in your own CSS – the same idea as the tokens in Dark Mode Design and CSS.
Template parts and patterns
The parts folder holds reusable areas such as parts/header.html and parts/footer.html. Every template that includes them stays consistent, and site owners can edit the header once in the Site Editor. Patterns are ready-made groups of blocks – a hero section, a pricing table, a contact strip – that editors insert with a click. Registering a pattern can be as simple as adding a PHP file with a header comment to the patterns folder. Good patterns let clients build new pages without breaking the design.
A simple workflow for your first theme
- Sketch the pages you need: home, blog list, single post, page and 404. Note which parts repeat.
- Create the theme folder with
style.cssand the required template, and activate it on your local site. - Add some real-looking content: a few posts with featured images, a long page and a menu. Testing with empty content hides layout problems.
- Build the general template first (
index.phportemplates/index.html), then add more specific templates only when a page type needs a different layout. - Set your colours, font sizes and content widths in
theme.jsonso the editor and the front end match. - Check the site on a phone, with the keyboard, and with debugging on. Fix every notice and warning.
- Bump the
Versioninstyle.csseach time you release changes, so browsers load the new stylesheet.
Which should you learn first?
- Learn block themes if you are starting fresh, building new sites for clients who want to edit layouts themselves, or want to follow where WordPress is heading.
- Learn classic themes if you will maintain existing sites, work with WooCommerce or plugin-heavy setups built on classic themes, or need fine PHP control. Many agency jobs still involve classic themes.
- Either way, learn the template hierarchy, enqueuing assets, escaping output and
theme.json– they apply to both.
Good WordPress theme development habits from day one
- Escape output:
esc_html(),esc_url(),esc_attr(). - Make strings translatable with
__()and a text domain. - Use a child theme if you are customising someone else’s theme, so updates do not wipe your changes.
- Keep features that must survive a theme change (custom post types, shortcodes) in a plugin, not the theme.
- Check accessibility and performance: semantic HTML, alt text, sensible image sizes – see Semantic HTML for SEO and Core Web Vitals for Designers.
Frequently asked questions
What are the minimum files for a WordPress theme?
A classic theme needs style.css and index.php. A block theme needs style.css and templates/index.html.
Do I need to know PHP to build a block theme?
Not much. Block themes are built mainly with HTML block markup, CSS and theme.json. PHP is still useful for functions.php, custom blocks and advanced features.
Can a classic theme use theme.json?
Yes. theme.json works with both classic and block themes, so a classic theme can use it to control editor colour palettes, font sizes and other settings.
What is the difference between a theme and a plugin?
A theme controls presentation and layout. A plugin adds functionality. Anything that should keep working after switching themes, such as custom post types, belongs in a plugin.
Should I build my theme on Bootstrap?
You can, especially for classic themes, but it adds weight. Block themes usually work better with theme.json and the editor’s own layout system. See the Bootstrap 5 Grid post if you go that route.
Further reading
- developer.wordpress.org/themes/getting-started/what-is-a-theme
- developer.wordpress.org/themes/core-concepts/theme-structure
- developer.wordpress.org/themes/templates/template-hierarchy
- developer.wordpress.org/themes/global-settings-and-styles/introduction-to-theme-json
- developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living


