Move default page templates to sub directory

I think I got it working.

Took this from the Sage starter theme from the people over at Roots.

/**
 * Here's what's happening with these hooks:
 * 1. WordPress detects theme in themes/sage
 * 2. When we activate, we tell WordPress that the theme is actually in themes/sage/templates
 * 3. When we call get_template_directory() or get_template_directory_uri(), we point it back to themes/sage
 *
 * We do this so that the Template Hierarchy will look in themes/sage/templates for core WordPress themes
 * But functions.php, style.css, and index.php are all still located in themes/sage
 *
 * themes/sage/index.php also contains some self-correcting code, just in case the template option gets reset
 */
add_filter('stylesheet', function ($stylesheet) {
    return dirname($stylesheet);
});
add_action('after_switch_theme', function () {
    $stylesheet = get_option('stylesheet');
    if (basename($stylesheet) !== 'templates') {
        update_option('stylesheet', $stylesheet . '/templates');
    }
});
add_action('customize_render_section', function ($section) {
    if ($section->type === 'themes') {
        $section->title = wp_get_theme(basename(__DIR__))->display('Name');
    }
}, 10, 2);

I’m only doing this on a fresh project so I have no idea if it will mess things up on an existing site. Though I highly doubt it, but at your own risk.

When you paste this in your functions.php you will have to go reactivate your theme. Doesn’t look like any settings changed after doing so. Everything seems to be working fine.

I tested the behavior and it basically looks for the template in the templates folder. If not there it will look for it in the default location (theme root) just like normal. If not there it will move on in the template hierarchy just like normal.