WordPress at Your Fingertips

Theme Files Hierarchy

This post is about the names of the WordPress theme files. And it also reviews which file to include for showing the content of a specific page. This is very important and at the same time simple knowledge. Every WordPress developer should know how to manage it. Below you will find fully covered WordPress theme files structure and the order of how these files are connected (their hierarchy).

Theme files connections (theory)

Hierarchy, in this case, is a sequential files search for multiple preprogrammed file names that are suitable for the output of the specific page. I.e. there is a list of filenames that are checked for the existence one by one, and as soon as the file is found (it exists), the check stops and the found file is used as a template for the page; the search is made from the more specific hierarchy to the less one.

For example, we go to the category page "Plugins": http://example.com/category/plugins (the page has slug plugins and id 25). Then, to generate the code of the page, WordPress will start checking for the existence of the following files one by one (the scan will abort on the first existing file):

  • category-plugins.php
  • category-25.php
  • category.php
  • archive.php
  • index.php

The complete diagram for all kinds of pages and their files looks like this:

An interactive version of the diagram

Another diagram (old one), perhaps it is more clear:


Page types and file names

Below is a list of pages and their theme files. In this section, explaining the image of the hierarchy of theme files (which is shown above). Also, you will find different types of site pages and their corresponding list of PHP files. Such files should be located in the folder of the WordPress theme.


Static page

  • {any_name}.php (when the page template is used)
  • page-{post_slug}.php
  • page-{post_id}.php
  • page.php
  • singular.php
  • index.php


  • single-post-{post_slug}.php
  • single-post.php
  • single.php
  • singular.php
  • index.php

Custom post type

  • {any_name}.php (for heirarchical posts with templates support. From WP 4.7)
  • single-{post_type}-{post_slug}.php
  • single-{post_type}.php
  • single.php
  • singular.php
  • index.php


  • {MIME_type_start}.php
  • {MIME_type_end}.php
  • {MIME_type_start}-{MIME_type_end}.php
  • attachment.php
  • single-attachment-{attachment_slug}.php (allows you to specify a template for a single attachment)
  • single-attachment.php (same as attachment.php)
  • single.php
  • singular.php
  • index.php

By the 'start' and 'end' of the MIME type, I mean the first and last part of the MIME which is separated by /. For example, if it is a text file with MIME type 'text/plain', then the existence of the following files will be checked: first text.php, then plain.php, and then text-plain.php.

See the code of wp_get_mime_types() function for a complete list of MIME types.



  • category-{slug}.php
  • category-{id}.php
  • category.php
  • archive.php
  • paged.php (if a pagination page)
  • index.php


  • tag-{slug}.php
  • tag-{id}.php
  • tag.php
  • archive.php
  • paged.php (if a pagination page)
  • index.php


  • taxonomy-{taxonomy_name}-{slug}.php
  • taxonomy-{taxonomy_name}.php
  • taxonomy.php
  • archive.php
  • paged.php (if a pagination page)
  • index.php

Post type archive page

  • archive-{post_type_slug}.php
  • archive.php
  • paged.php (if a pagination page)
  • index.php

Author page

  • author-{nickname}.php
  • author-{id}.php
  • author.php
  • archive.php
  • paged.php (if pagination page)
  • index.php

Archive page of date (day, month, year)

  • date.php
  • archive.php
  • paged.php (if a pagination page)
  • index.php

404 page

  • 404.php
  • index.php

Search page

  • search.php
  • index.php

Main page

  • front-page.php
  • ('page' post type logic if a page is selected as a front page)
  • home.php
  • index.php

Blog page

The blog page appears when the 'page' is selected as a front page.

  • home.php
  • index.php


The embed template file is used to render a post which is being embedded with REST API. Embedding appeared in WP 4.5 and allows you to embed your posts in other sites. See get_post_embed_url().

  • embed-{post-type}-{post_format}.php
  • embed-{post-type}.php
  • embed.php

To change the embedding content only, you can create a embed-content.php file in your theme and describe embed HTML in it. The original embed HTML is in the core file /wp-includes/theme-compat/embed-content.php.

Non-ASCII characters handling

Since WordPress 4.7, any dynamic part of a template name which includes non-ASCII characters in its name actually supports both the un-encoded and the encoded form, in that order. You can choose which to use.

Let's look at the page template hierarchy for a page named Hello World 😀 with the ID of 6:

  • page-hello-world-😀.php
  • page-hello-world-%f0%9f%98%80.php
  • page-6.php
  • page.php
  • singular.php

The same behavior applies to post slugs, term names, and author nicenames.

How it works

For the logic of order in which the files are connected is responsible the core file wp-includes/template-loader.php. If you study it, the file explains everything. But such a study is not so interesting, so I will explain it here in details.

First of all. template-loader.php file is connected after the whole WordPress environment is loaded. After the wp-load.php file is run and the main query is inited (see wp()). I.e. template-loader.php file is connected at the very end of the PHP script.

First runs the hook template_redirect. You can do some kind of checks in this hook and if you need redirect the user to another URL, you must use die() in it. I.e. if the hook changes something, then the work of template-loader.php file ends and the user is redirected.

Next triggers not interesting hook exit_on_http_head. It allows you to make something appear on the screen when there is HTTP HEAD request...

Next there are checks on all Conditional Tags. During these checks, WordPress detects which template file is more suitable for the current request. The conditional tag is checked, then another and another... As soon as one of the conditional tags is triggered, the corresponding function is called, which finds the appropriate template file and returns the path to it. All such functions are described in get_query_template().

Next - path to the theme file is defined! Now it runs through the template_include filter which allows us to modify the template file for the current request.

Next, the file connects to PHP and starts the visual part of the page generation.



You can change the file hierarchy through dynamic filters:

  • (type)_template_hierarchy - filters the array of filenames in the hierarchy by which to search for the desired file. From WP 4.7.

  • (type)_template - filters the path to the template file that has already been defined.

All variants of type parameter can be found in the $type parameter of get_query_template() function. Here they are:

  • index
  • 404
  • archive
  • post_type_archive
  • author
  • category
  • tag
  • taxonomy
  • date
  • home
  • front_page
  • page
  • paged
  • search
  • single
  • singular
  • attachment
  • comments_popup

Example of using such filter see in the answer to this question (rus).


Other theme files

The files below are also used in the theme, but they are simply includable and do not participate in the hierarchy. For example, file sidebar.php is included in any theme file through get_sidebar().

A whole list of such non-hierarchical 'includable' files:

No comments
    Log In