When WordPress runs updates to core, plugins, or themes it briefly goes into maintenance mode. Visitors are greeted with a plain, unstyled message: “Briefly unavailable for scheduled maintenance. Check back in a minute.” It works, but it’s a long way from the polished experience your brand deserves.
For block themes, there’s a clean solution that splits the work sensibly. First, a hook to the theme. From there, the maintenance page is created and managed entirely in the Site Editor. No file editing, no code, just blocks. Maintenance mode is activated and deactivated in whatever way suits your workflow best.
Table of Contents
The hook
Add the following to your theme’s functions.php. This is a one-time task, once it’s in place, no code changes are needed to manage maintenance mode.
The minimal hook approach
This is fully functional for most sites doing routine update windows:
/**
* Serve the template titled "Maintenance" if the template exists.
*
* @param string $template The path to the template.
* @return string The maintenance template path, or the original template.
*/
function your_theme_force_maintenance_template( $template ) {
if ( is_user_logged_in() ) {
return $template;
}
if ( ! current_theme_supports( 'block-templates' ) ) {
return $template;
}
// Look for template(s) titled exactly "Maintenance".
$maintenance_posts = get_posts(
array(
'post_type' => 'wp_template',
'title' => 'Maintenance',
'post_status' => array( 'publish', 'draft' ),
'posts_per_page' => -1,
'no_found_rows' => true,
)
);
$maintenance_post = null;
foreach ( $maintenance_posts as $post ) {
$theme_slugs = wp_get_post_terms( $post->ID, 'wp_theme', array( 'fields' => 'names' ) );
if ( in_array( get_stylesheet(), $theme_slugs, true ) ) {
$maintenance_post = $post;
break;
}
}
if ( ! $maintenance_post ) {
return $template;
}
$slug = $maintenance_post->post_name;
return locate_block_template( $template, $slug, array( $slug ) );
}
add_filter( 'template_include', 'your_theme_force_maintenance_template', 99 );
locate_block_template() checks for a maintenance template in the right order of precedence, and it checks the database first. That means a template created in the Site Editor will be found, provided it uses the name maintenance. Any logged-in user bypasses maintenance mode entirely, so your team can review the live site during an update without hitting the maintenance page.

The SEO-friendly headers approach
If your site has meaningful search traffic or maintenance windows tend to run longer, it’s worth adding three headers that tell search engine crawlers the downtime is temporary:
/**
* Serve the template titled "Maintenance" if the template exists.
* Includes headers to signal temporary unavailability to search engines.
*
* @param string $template The path to the template.
* @return string The maintenance template path, or the original template.
*/
function your_theme_force_maintenance_template( $template ) {
if ( is_user_logged_in() ) {
return $template;
}
if ( ! current_theme_supports( 'block-templates' ) ) {
return $template;
}
// Look for template(s) titled exactly "Maintenance".
$maintenance_posts = get_posts(
array(
'post_type' => 'wp_template',
'title' => 'Maintenance',
'post_status' => array( 'publish', 'draft' ),
'posts_per_page' => -1,
'no_found_rows' => true,
)
);
$maintenance_post = null;
foreach ( $maintenance_posts as $post ) {
$theme_slugs = wp_get_post_terms( $post->ID, 'wp_theme', array( 'fields' => 'names' ) );
if ( in_array( get_stylesheet(), $theme_slugs, true ) ) {
$maintenance_post = $post;
break;
}
}
if ( ! $maintenance_post ) {
return $template;
}
$slug = $maintenance_post->post_name;
$maintenance_template = locate_block_template( $template, $slug, array( $slug ) );
if ( ! empty( $maintenance_template ) ) {
nocache_headers();
status_header( 503 );
header( 'Retry-After: 3600' );
return $maintenance_template;
}
return $template;
}
add_filter( 'template_include', 'your_theme_force_maintenance_template', 99 );
status_header( 503 ) sends a “Service Unavailable” response so crawlers know the downtime is temporary rather than a permanent change. Retry-After: 3600 suggests they check back in an hour. nocache_headers() prevents the response from being stored by CDNs or proxies, so the live site is served immediately once maintenance mode is disabled. None of these affect what visitors see.
Note that in this version the headers are sent inside the template check so they are not being set unless a maintenance template is actually being served.
Creating the maintenance template
With the hook in place, the maintenance page is created entirely in the Site Editor.
Navigate to Appearance Editor Templates and add a new template. Name it Maintenance, and WordPress will assign it the slug maintenance, which is what the hook is looking for.

Build it out like any other template. It has full access to your theme’s Global Styles, so your fonts, colours, and spacing are all available. Include your header and footer template parts for the full site frame, or leave them out for a more focused page. Add a heading, a message, a logo, whatever reflects your brand.
Once saved, the template is stored in the database and the hook will find it automatically.
Activating and deactivating maintenance mode
The fastest switch is renaming the template itself. Since the hook checks for a template named maintenance, creating it (as described above) turns maintenance mode on. To turn it off, go to Appearance Editor Templates, find the Maintenance template, and rename or delete it — no file access, code, or configuration needed.

Testing
Create the Maintenance template in the Site Editor, then log out and visit the site. You should see your maintenance page. Log back in and confirm the live site loads normally. When you’re satisfied, delete the template.
Conclusion
A maintenance page is a small detail, but it’s one visitors notice. The approach here keeps the work where it belongs: a developer adds the hook once and it stays out of the way, while the people responsible for the site’s content and brand own the maintenance page entirely through the Site Editor. No static files to manage, no code to touch when the message needs updating, just a template that’s there when you need it and gone when you don’t.
Props to @sumitsingh and @bph for reviewing this article and offering feedback.
Leave a Reply