WordPress works on a template system with defaults when one doesn’t exist. Each template type serves a purpose by letting users display different formats and styles based on content type. For example, your front page may show a different layout and content from your actual post page.
Each page type has its own name. When a page type doesn’t have an associated template, WordPress will fall back and use the closest parent template in its place. The root default fall back is your
index.php – a file that is required in every theme, regardless of everything.
In fact, there are only two files that WordPress requires, at minimum, to be recognized as a valid theme and it is your
You can also add a
functions.php that contains all your additional classes, php hooks and whatever else – but the finer details of its contents are for a different post. For this post, we’ll be going over the theme file structure, what each file does and where they sit in the WordPress hierarchy for rendering.
Presenting the template tree
The diagram above is basically the decision tree that WordPress goes through in order to figure out which template to render based on the page type. If a template doesn’t exist, it continues down the flow, until ultimately we land on index.php if nothing else matches.
index.php the catch-all template and hence why it is one of the minimally required file in a WordPress theme.
You can click on the diagram above to go to the source image and it will let you view the entire flow chart in full size.
The content below is going to go through the individual pathways and what each template file means, beginning from left to right, in accordance with the flow chart above.
Search Results Page
As a user, you find yourself hitting the search bar on a WordPress website. This leads you to a search results page – or according to WordPress, it’s the
search.php template page.
search.php template doesn’t exist, WordPress defaults to your
There isn’t much to the search results page and the display hierarchy structure is pretty flat.
search page ------> search.php ------> index.php
Error 404 page
Like the search results page, the error 404 page’s hierarchy is also very flat and straight forward. When a page doesn’t exist or something went wrong, WordPress will show a 404 page.
404.php exists, WordPress will display that. If not, it will default to whatever logic has been coded into the
index.php template page.
404 page ------> 404.php ------> index.php
Blog Posts Page
Your blog posts page is the page that displays a list of all your blog posts. At first, WordPress will search for the
home.php template. If that doesn’t exist, then it will hit the default
blog posts page ------> home.php ------> index.php
Site Front Page
Everything so far has been rather simple and flat. The site’s front page gets a little bit more interesting because there is a choice available, forking the displayed template based on the selected item.
This is because the site owner can select if a specific static page is shown or the blog posts list page. They can do this via the customization option that’s available by default.
When Your latest posts is selected, WordPress will put you on the blog posts page flow, showing
home.php first if it exists, then defaults to
index.php if it doesn’t.
If A static page is selected, the user gets the option to choose which page they want to display as the front landing page for the website. Flow wise, WordPress will put you onto the singular page flow, which is discussed below.
site front page ------> if Your latest posts ------> Blog Posts Page flow ------> if A static page ------> Singular Page flow
This is where the complexity of potential templates begin. A singular page is split into two types – static page and single post. Each type has its own separate flow that merges on the file
singular.php and ultimately the default fall-back of
Static page flow
A static page is the single pages that you’d use for things like about and contact pages. They are one-off instances that aren’t expected to change often or be part of a larger categorical collection.
When you have a static page, you have the option to use the default or a custom template that is available under the Page Settings section of a page.
For example, in the screenshot below, the specific page has two other templates – an Authors template and a Contacts template – associated with it.
When a custom template is selected, WordPress will render that custom template. If none exists, WordPress will render
page.php. If that doesn’t exist, then WordPress will default to
If default is selected, WordPress looks for a
page-$slug.php template. If that doesn’t exist, then it goes for
page-$id.php. It does this to give more granularity to your theme’s customization and doesn’t expect the slug or id to change, hence why it hones in a very specific value that’s associated to that particular page. If none these things exists, then WordPress will default to
page.php before going to
singular.php and then, finally,
So the static page flow looks something like this:
site static page ---> if custom template ---> $custom.php ----------------- | ---> page.php ---> singular.php ---> index.php ---> if default ---> page-$slug.php ---> page-$id.php ------
Single post page flow
A single post has three potential forks you can go down – attachment, custom and blog post type.
An attachment type is simply a page that’s dedicated to the attachments such as images. A blog post is the default post type that comes with WordPress. Finally, a custom post type is where WordPress’ flexibility is – in its ability for developers to create custom post types.
Let’s look at the first flow – the attachment flow.
In the attachment flow, WordPress looks for a combination of custom mime and subtype combination. A mime type is your file extension such as .wav, .mp3 and .jpg
If this file doesn’t exist, it will hunt down a corresponding subtype file. If that doesn’t exist, WordPress will go to the next thing in the tree, which is the mime type template. If that also doesn’t exist, then WordPress will hunt down the
attachment.php. Finally, if that also doesn’t exist, then
single.php is used, before it hits singular.php and then the default of
So the flow for the attachment option looks something like this:
single post page ---> attachment type --> $mimetype-$subtype.php ---> $subtype.php ---> $mimetype.php ---> attachment.php ---> single.php --> singular.php --> index.php
Next on the potential options list is…custom type
When it comes to custom types, this is one of the most powerful features available to WordPress. This is because you can set your custom post type to be anything you want. For example, you could have a custom portfolio post type or a series of FAQ items post type.
When a custom post type single page is selected, WordPress goes through a flow of matching the custom post type template first. If that doesn’t exist, then it hunts down a
single-$posttype-$slug.php file. If there is no match, next in the hierarchy is
If nothing matches at all, WordPress defaults to
singular.php and finally, the fallback default for everything –
Here is what the flow looks like:
single post page ---> custom post type ---> $custom.php ---> single-$posttype-$slug.php ---> single.php ---> singular.php ---> index.php
And finally, the blog type
The blog type is the default post type that comes out of the box with WordPress. You can also have a
$custom.php template for blog types, followed by
singular.php and finally the default of
For this flow, it looks something like this:
single post page ---> blog post type ---> $custom.php ---> single-post.php ---> single.php ---> singular.php ---> index.php
Putting it all together
So, now if we were to put it all together, this branch of options and hierarchy looks something like this:
|---> attachment type --> $mimetype-$subtype.php ---> $subtype.php ---> $mimetype.php ---> attachment.php ---| single post page |---> custom post type ---> $custom.php ---> single-$posttype-$slug.php -------------------------------------| ----> single.php ---> singular.php ---> index.php |---> blog post type ---> $custom.php ---> single-post.php --------------------------------------------------|
The archive page is potentially the most complicated one out of all the landing pages a user can land on. Most of the time, theme developers spend very little time on this but the granularity that WordPress provides can be used to your advantage when coding your theme.
There are six potential forks and they are as follows:
Author Archives Page
The author archives page deals specifically with a list of previous posts made by a particular author. It first looks for the
author-$nicename.php file. A WordPress
$nicename is basically a sanitized version of a username, where spaces are replaced with dashes instead. If that doesn’t exist, then WordPress looks for an
author-$id.php file, followed by
archive.php and finally the
index.php as the default if everything else fails.
Here’s what the flow looks like:
archive page ---> author archives page ---> author-$nicename.php ---> author-$id.php ---> author.php ---> archive.php ---> index.php
Category Archives Page
The category archives page shows a list of previously posted items based on a specific category. The flow starts off with WordPress looking for a
category-$slug.php file, followed by
category-$id.php. If none of these exists, it looks for a
category.php, before defaulting to
archive.php and ultimately
This flow is illustrated below:
archive page ---> category archives page ---> category-$slug.php ---> category-$id.php ---> category.php ---> archive.php ---> index.php
Custom Post Type Archives Page
Like a normal post type, custom post type also comes with its own archives page. WordPress sorts this via
archive-$posttype.php. If that doesn’t exist then it looks for
archive.php and then defaults to
archive page ---> custom post type archieves page ---> archive-$posttype.php ---> archive.php --> index.php
Custom Taxonomy Archives Page
A taxonomy is a way of grouping posts together. By default, WordPress comes with tags and categories. You can create your own taxonomies to group your posts by, based on your content type and nature of your WordPress theme.
When a custom taxonomy exists, WordPress looks for a
taxonomy-$taxonomy-$term.php file. If that doesn’t exist, the next one in the hierarchy is
taxonomy-$taxonomy.php. If all else fails to exist,
taxonomy.php is chosen next, followed by
archive.php and finally the default
archive page ---> custom taxonomy archieves page ---> taxonomy-$taxonomy-$term.php ---> taxonomy-$taxonomy.php ---> taxonomy.php ---> archive.php ---> index.php
Date Archives Page
The date archives collate the returned result based on dates. This is often granulated down to week, month and year options. WordPress first looks for a
date.php file to deal with date-related archive content, followed by
archive.php and then
| ---> Week -------| archive page ---> date archive ---| ---> Month ------| ----> date.php ---> archive.php ---> index.php | ---> Year -------|
and finally, Tag Archives Page
The tag archives page works in a similar fashion as the category archives page, with the only difference being that it uses tags as the basis for evaluation. WordPress starts off looking for a
tag-$slug.php file, followed by a specific
tag-$id.php template. If none of these exists, it looks for a less granular template that deals specifically with tags –
If none of these files exists, it falls back on the default
archive.php and then
archive page ---> tag archives page ---> tag-$slug.php ---> tag-$id.php ---> tag.php ---> archive.php ---> index.php
And that’s it!
When it’s in a giant diagram, things can seem daunting and large. However, when we break it down to its different flows, WordPress page hierarchy isn’t that bad. We are able to see that there’s more to it than just an
single.php template page, and that the seemingly complex is actually very linear.
I hope this article has helped you understand how it all fits together and that it will provide you with good reference material in the future.
Thank you for reading!