Displays a Coming Soon page to visitors while allowing logged-in users or anyone with a secret preview link to view the site.

11/19/2025
Back to Gists
<?php
/**
 * Plugin Name: Coming Soon Mode
 * Description: Displays a Coming Soon page to visitors while allowing logged-in users or anyone with a secret preview link to view the site.
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * Enable Coming Soon mode on the front end.
 */
function knolaust_enable_coming_soon_mode() {

    // Toggle Coming Soon mode on/off
    $enabled = true; // set to false when launching the site

    if ( ! $enabled ) {
        return;
    }

    // Secret preview token — change this to anything unique
    $secret_key = 'preview-access-key';

    /**
     * Allow:
     * - Logged-in users
     * - Admin area and login pages
     * - REST API, WP-CLI, Cron, Feeds
     */
    if (
        is_user_logged_in() ||
        is_admin() ||
        ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ||
        ( defined( 'WP_CLI' ) && WP_CLI ) ||
        ( defined( 'DOING_CRON' ) && DOING_CRON ) ||
        is_feed() ||
        knolaust_is_login_request()
    ) {
        return;
    }

    /**
     * Secret preview link
     * Example: https://example.com/?preview_key=preview-access-key
     */
    if ( isset( $_GET['preview_key'] ) && $_GET['preview_key'] === $secret_key ) {

        setcookie(
            'knolaust_preview',
            $secret_key,
            time() + DAY_IN_SECONDS,
            COOKIEPATH ? COOKIEPATH : '/',
            COOKIE_DOMAIN,
            is_ssl(),
            true
        );

        return;
    }

    // If they already have the preview cookie, let them through
    if ( isset( $_COOKIE['knolaust_preview'] ) && $_COOKIE['knolaust_preview'] === $secret_key ) {
        return;
    }

    // Show Coming Soon page to everyone else
    status_header( 503 );
    nocache_headers();

    ?>
    <!DOCTYPE html>
    <html <?php language_attributes(); ?>>
    <head>
        <meta charset="<?php bloginfo( 'charset' ); ?>">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title><?php esc_html_e( 'Coming Soon', 'coming-soon-mode' ); ?></title>
        <style>
            html, body {
                margin: 0;
                padding: 0;
                height: 100%;
                font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
                background: #0b1b2b;
                color: #ffffff;
            }
            .csm-wrapper {
                min-height: 100vh;
                display: flex;
                align-items: center;
                justify-content: center;
                text-align: center;
                padding: 2rem;
            }
            .csm-inner {
                max-width: 480px;
            }
            .csm-title {
                font-size: 1.75rem;
                margin-bottom: 0.75rem;
                letter-spacing: .05em;
                text-transform: uppercase;
            }
            .csm-text {
                font-size: 1rem;
                line-height: 1.6;
                opacity: 0.85;
            }
        </style>
    </head>
    <body>
        <div class="csm-wrapper">
            <div class="csm-inner">
                <h1 class="csm-title"><?php esc_html_e( 'Coming Soon', 'coming-soon-mode' ); ?></h1>
                <p class="csm-text">
                    <?php esc_html_e( 'Our site is almost ready. Please check back soon.', 'coming-soon-mode' ); ?>
                </p>
            </div>
        </div>
    </body>
    </html>
    <?php

    exit;
}
add_action( 'template_redirect', 'knolaust_enable_coming_soon_mode', 0 );

/**
 * Detect if the current request is wp-login.php or wp-register.php
 */
function knolaust_is_login_request() {
    $script = basename( $_SERVER['PHP_SELF'] ?? '' );
    return ( $script === 'wp-login.php' || $script === 'wp-register.php' );
}