The template hierarchy picks a file automatically based on a page's slug or ID, but sometimes you want a completely custom layout that has nothing to do with either — a homepage with a hero banner, a landing page with a different structure entirely. That's what a custom page template is for.
Any PHP file in the theme becomes a selectable page template just by adding one comment at the top:
<?php
/**
* Template Name: Home Page
*/
get_header();
?>
<section class="hero">
<?php while ( have_posts() ) : the_post(); ?>
<?php the_content(); ?>
<?php endwhile; ?>
</section>
<?php get_footer(); ?>That single Template Name: line is the entire registration step — no functions.php code needed. A common naming convention is template-{name}.php, but the file name itself doesn't matter to WordPress; only the comment does.
In the editor for any page, the Page Attributes panel has a Template dropdown — every file with a Template Name: comment shows up there by its given name. Pick it, update the page, and that one page now renders through the custom file instead of page.php.
It replaces page.php entirely, for that page only
A custom page template completely replaces page.php for that one page — the hierarchy checks for it first, ahead of everything else. Nothing from page.php carries over automatically; if the custom template needs the same header, footer, or other shared markup, it calls get_header()/get_footer() itself, same as any other template.
The most common real-world use is exactly the example above: a "Home Page" template, assigned to whichever page is set as the site's static homepage in Settings → Reading. It lets the homepage have a completely different structure — a hero section, featured content, whatever the design calls for — without any of that logic leaking into the regular page.php that every other page still uses.
The next lesson steps away from templates for a moment to fix something every one of them has been doing wrong so far — loading CSS and JavaScript the right way, instead of hardcoding <link> and <script> tags directly in header.php.