Managing WordPress Themes and Plugins with WP-CLI
When you manage a WordPress site from a terminal, WP-CLI lets you inspect, install, update, activate, and remove themes and plugins with…
A WordPress theme controls the appearance and layout of a site’s pages. A block theme is a practical starting point for a new theme. It uses HTML files with WordPress blocks, which are page elements such as titles and navigation menus. Site owners can edit templates, headers, and footers in the Site Editor. A classic theme uses PHP template files and suits projects that rely on PHP to render pages or follow an established classic-theme workflow. WordPress’s theme documentation describes both approaches.
These steps create a basic block theme, then add design settings for the whole site and layouts you can reuse. You will need a local WordPress site, a separate copy of WordPress that runs on your computer. If a template breaks there, it will not affect a live site.
Version details here reflect the WordPress release list checked on October 26, 2026: WordPress 7.1.3 was the newest stable release listed, while 7.2 Beta 1 was available for testing. Use a stable release for ordinary development unless you are specifically testing compatibility with a beta. WordPress’s version list records the release status.
Install WordPress on your computer in a local development environment, a separate setup for building and testing a site. The Theme Handbook lists options such as WordPress Studio, Local, Docker, MAMP, XAMPP, and @wordpress/env; choose one that fits your computer and workflow. The WordPress setup documentation describes these options.
Once WordPress runs, locate its themes directory:
wp-content/themes/
Create a folder for the new theme:
wp-content/themes/starter-theme/
WordPress identifies the theme by the files in this folder. The Create Block Theme plugin can also generate a blank theme or export one as a ZIP. You should still learn what the generated files do. The Create Block Theme tutorial covers that option.
This walkthrough builds a block theme. Its templates are HTML files with WordPress block markup, which allows the Site Editor to work with site-wide layouts. A classic theme instead uses PHP templates and is useful when PHP must control how pages are rendered. A hybrid theme keeps a classic foundation while adopting selected block-theme features.
A theme does not become a block theme just because it has a theme.json file. WordPress identifies a block theme by its block templates, including templates/index.html. Both classic and block themes can use theme.json to set site-wide options and styles. WordPress’s overview of theme types explains the distinction.
A block theme needs two files for WordPress to recognize it: style.css and templates/index.html. theme.json is optional, but it is useful for setting shared colors, typography, spacing, and layout. WordPress lists these requirements and other theme components in its theme structure documentation.
Create this initial folder structure:
starter-theme/
├── style.css
├── theme.json
├── templates/
│ └── index.html
└── parts/
├── header.html
└── footer.html
Add the theme header to style.css:
/*
Theme Name: Starter Theme
Description: A small custom block theme.
Version: 1.0.0
*/
WordPress reads the theme details in this comment to identify the theme. The file can also contain CSS, but a block theme does not need to keep all its design rules there.
theme.jsonA theme.json file tells WordPress which design settings and default styles the theme uses. WordPress applies those settings to the site and in the editor, where site owners can choose the theme’s colors and layout options. The theme.json introduction explains how the file connects theme design to WordPress’s editing tools.
The following example uses theme.json version 3, introduced in WordPress 6.6. Its schema URL targets WordPress 7.1, so check the schema and supported settings if the theme must also work with older WordPress versions. The settings and styles documentation describes version and compatibility considerations.
{
"$schema": "https://schemas.wp.org/wp/7.1/theme.json",
"version": 3,
"settings": {
"color": {
"palette": [
{
"slug": "ink",
"name": "Ink",
"color": "#202124"
},
{
"slug": "paper",
"name": "Paper",
"color": "#ffffff"
},
{
"slug": "accent",
"name": "Accent",
"color": "#2457c5"
}
]
},
"layout": {
"contentSize": "720px",
"wideSize": "1200px"
}
},
"styles": {
"color": {
"text": "var(--wp--preset--color--ink)",
"background": "var(--wp--preset--color--paper)"
}
}
}
The settings section lists choices the editor can offer, such as colors and content widths. The styles section sets the default appearance. In this example, it sets the text and background colors.
A site owner can change styles and templates in the Site Editor. WordPress uses saved user settings instead of theme defaults, and it uses a template saved by the user instead of the theme’s template file. If a file change does not appear on the site, check whether the Site Editor has a saved version of that template. WordPress’s explanation of global style precedence and its template hierarchy documentation describe these priorities.
A template defines the layout WordPress uses for a type of page. The index.html template is the fallback. WordPress uses it when no more specific template applies.
Create templates/index.html:
<!-- 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 comments identify WordPress blocks and their settings so the Site Editor can interpret the template. The query block displays posts from the current WordPress query, while the post template specifies how each result appears. The template-part blocks insert the shared header and footer.
A template part is a reusable region of a template, such as a header or footer. Create parts/header.html:
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:site-title /-->
<!-- wp:navigation /-->
</div>
<!-- /wp:group -->
Then create parts/footer.html:
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Site footer</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
These examples give the theme a site title, a navigation block, and a simple footer. Open the Site Editor to set up the navigation and adjust the parts. If you change a part in the editor, WordPress may save that change in the database and display it instead of the file version.
The fallback template is enough to make a basic theme, but a site may need separate layouts for individual posts, pages, archives, search results, or error pages. Add a template only when that view needs a different structure. Common filenames include single.html, page.html, archive.html, search.html, and 404.html.
WordPress follows a set of rules, called the template hierarchy, to choose a template for each view. Test more than the home page: visit an individual post, a page, an archive, search results, and a URL that should show a not-found page. The template hierarchy reference explains which templates WordPress selects.
A pattern is a reusable arrangement of blocks, such as a callout, hero section, or post-card layout. Patterns help site owners add recurring designs without assembling the same blocks each time. Add a patterns/ directory when you have layouts worth reusing, then test that each pattern inserts and displays as intended.
A basic block theme may not need a functions.php file or custom JavaScript. When you add a stylesheet or script, use WordPress’s enqueue functions and hooks. These let WordPress manage those files alongside files from plugins and other themes. The asset inclusion handbook covers wp_enqueue_style() and related functions.
If PHP outputs changing content, escape it for where it appears. For example, use esc_html() for text and esc_url() for URLs. Escaping helps prevent unsafe content from being treated as page markup or a link. The WordPress security guidance explains safe output practices.
Keep features that should continue working after a visitor changes themes, such as custom post types or business logic, in a plugin. A theme should handle presentation.
Check the theme in both the front end and the Site Editor. WordPress recommends testing with different kinds of content. Long titles, unusual images, nested comments, and mixed HTML can reveal layout problems that a short sample post does not show. The theme testing handbook covers test data and other checks.
Use a short test pass that covers the main failure points:
Automated checks can help find defects, but passing a checker does not prove that every visitor can use the theme. WordPress’s accessibility guidance discusses keyboard access, screen-reader compatibility, and appropriate ARIA use. The accessibility handbook also clarifies that an “Accessibility Ready” directory tag does not mean a theme meets WCAG AA.
For a personal or client site, put the theme in a ZIP file and install it through the WordPress dashboard, or use the Create Block Theme plugin to export it. Before sharing the ZIP, confirm that it contains the theme folder and all the files WordPress needs.
Submitting a theme to the WordPress.org directory involves additional review and requirements. Check the current theme guidelines before submission, and test the packaged theme rather than relying only on the development copy.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com