=== R2 Coming Soon ===
Contributors: rise2studio
Tags: coming soon, maintenance mode, under construction, launch, holding page
Requires at least: 6.0
Tested up to: 6.7
Requires PHP: 8.0
Stable tag: 1.4.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A simple, mobile-first Coming Soon screen you switch on and off from the admin toolbar. Administrators keep browsing the real site.

== Description ==

One switch, one holding page, nothing else to learn.

While Coming Soon is ON, every visitor who is not a logged-in administrator gets a single centred screen — your logo, a title and a short line of text — no matter which URL they open. Administrators keep browsing the real site exactly as usual, so you can keep building while the public sees the holding page.

= What you can set =
* **Logo** — any image from the media library, with a max width.
* **Layout** — classic (logo above the title) or **logo at the bottom**: a large title and text in the upper half, the logo towards the foot, with separate proportions for landscape and portrait screens.
* **Background** — a solid colour, a **gradient** (two colours and an angle, optionally a different one on phones), or a cover photo with an adjustable dark overlay so the text stays readable.
* **Title** and a **short text** (a couple of sentences; `<a>`, `<br>`, `<strong>` and `<em>` are allowed).
* **Text colour**, so light and dark backgrounds both work.
* **Font** — inherit the active theme's typography (default), a system font stack, or **Jost**, which ships with the plugin (no font service is contacted). **Font weight** for the title and the text.
* **Text size** — Small / Medium / Large, scaling the title and text together. Handy when an inherited theme font renders larger or smaller than you expected.

Everything is centred and laid out mobile-first: fluid type, a responsive logo, safe-area padding for notched phones, and a background photo served from the WordPress `srcset` so phones download a phone-sized file.

= On and off, visibly =
The admin toolbar carries a status pill on every screen — front end and back end — with a coloured dot: **amber = Coming Soon is ON** (the public cannot see the site), **green = OFF** (the site is live). One click toggles it, and a warning notice sits in wp-admin the whole time it is on, so nobody forgets and leaves a launched site hidden.

= Go live at a set time =
Set a date and time and, while Coming Soon is on, the holding page switches itself off at that moment: the site becomes visible to everyone and the page caches are cleared. The time is in the site's time zone (Settings → General). The toolbar pill shows it ("Coming Soon: ON until 15 Oct, 09:00"), and so does the admin notice. Leave it empty to go live by hand.

= Built for caching =
Page caches (WP Rocket, LiteSpeed, W3 Total Cache, WP Super Cache, SG Optimizer, Cachify, Kinsta) answer from disk *before* plugins load, so a coming-soon plugin that ignores them will happily serve the wrong page to the wrong audience. This one:

* marks every front-end request non-cacheable while the switch is ON (`DONOTCACHEPAGE` + no-cache headers), so a cache can never hand the holding page to an administrator or the real page to a visitor;
* purges the known page caches whenever you flip the switch, save the design, or activate/deactivate the plugin — otherwise a page cached a minute earlier would bypass the gate entirely.

= Good manners for search engines =
The holding page answers `503 Service Unavailable` with `Retry-After` and `noindex`, which is the correct signal for a site that is not open yet: crawlers come back later instead of indexing your placeholder. Turn the switch off and the real site answers `200` again immediately.

= Nothing leaks out the side =
Hiding the front end is not enough on its own. WordPress serves the REST API and SEO-plugin sitemaps on earlier hooks that a front-end-only gate never sees — so `/wp-json/wp/v2/pages` would hand any anonymous visitor the full content of every published page, and `/sitemap_index.xml` would hand them your whole URL list. While the switch is ON this plugin closes both: anonymous REST calls get `503`, and sitemap requests are sent to the holding page.

Logged-in users are deliberately unaffected by the REST block, so the block editor keeps working for your team while the site is hidden. If a public endpoint genuinely must stay reachable (a payment webhook, say), allow it through the `r2cs_rest_allowed_routes` filter.

= What is never blocked =
`wp-login.php`, wp-admin, AJAX, cron, WP-CLI, `robots.txt` and the site icon. You cannot lock yourself out, and scheduled jobs keep running.

== Installation ==

1. Upload the `r2-coming-soon` folder to `/wp-content/plugins/`.
2. Activate it. The switch starts **OFF** — activating the plugin never takes a live site down by itself.
3. Go to **Coming Soon** in the admin menu, set your logo, background and text, then flip the switch (there, or from the toolbar).
4. Use **Preview the holding page** to see it without logging out.

== Frequently Asked Questions ==

= Who can still see the site? =
Logged-in users with the `manage_options` capability (administrators). Everyone else — logged out or not — gets the holding page.

= Does it work with WP Rocket? =
Yes. While the switch is on, front-end pages are marked non-cacheable, and the plugin purges WP Rocket (and the other supported caches) whenever the switch or the design changes. When the site goes live — by hand or at the scheduled time — it clears WP Rocket like its own "Clear cache" button does: the page cache and the minified and cache-busted CSS and JS, and WP Rocket's preload starts again. No manual cache clearing needed. If Cloudflare sits in front with a "Cache Everything" rule, purge it after an automatic launch yourself: WP Rocket's Cloudflare add-on only purges for a logged-in administrator.

= Why does the page return 503 instead of 200? =
Because the site genuinely is not available yet. `503` plus `Retry-After` tells Google to come back rather than index a placeholder, which is what you want before launch. It has no effect on what visitors see.

= Can I keep the holding page at the URL the visitor opened? =
Yes — turn off **Behaviour → Redirect to home**. The holding page is then rendered in place at whatever URL they opened, instead of redirecting them to the home page first.

= The fonts do not match my theme =
The **Font** setting inherits the theme's typography by loading its stylesheet. If a theme's CSS interferes, switch it to **System font** — and use **Text size** to fine-tune.

== Changelog ==

= 1.4.1 =
* Fixed: while Coming Soon was on, WPML reported "The REST API test endpoint … is not responding correctly". WPML tests the REST API by calling it from the server with your cookies but without a REST nonce, which WordPress treats as logged out, so the holding page answered 503. Requests this site makes to itself while someone is logged in are now signed and let through; visitors still get 503.
* Fixed: a visitor with the preview password got 503 from the REST API, so parts of the site that load through it did not work for them.

= 1.4.0 =
* Added: layout "Logo at the bottom" — a large title and text in the upper half and the logo towards the foot, in the proportions of a reference design for landscape (1920×1080) and portrait (1080×1920) screens; sizes follow the screen width (title 80 px on a 1920 px screen, about 30 px on a phone).
* Added: gradient background — two colours and an angle, optionally a different gradient on portrait screens (phones).
* Added: Jost font, shipped with the plugin (SIL Open Font License; no font service is contacted), and a font weight for the title and the text.
* Fixed: the logo's "Max width" and the photo's "Dark overlay" only accepted steps of 10 and 5 — any other value (392, say) stopped the whole settings form from saving.

= 1.3.0 =
* Going live — at the scheduled time or by switching the holding page off — now clears WP Rocket like its own "Clear cache" button: the page cache and the minified and cache-busted CSS and JS (minified copies are named after the file, so a theme changed while the site was hidden would otherwise launch with the old CSS). WP Rocket's preload starts again. Switching on and saving the design still purge the page cache only.

= 1.2.0 =
* Added: scheduled go-live. Set a date and time in the status card and, while Coming Soon is on, the holding page switches itself off at that moment and the site becomes visible to everyone; the page caches are cleared. The time is in the site's time zone (Settings → General). The toolbar pill and the admin notice show when it will happen.
* A time that is not a real date, or has already passed, is refused with a message and the previous one is kept. While a time is set, the holding page tells search engines to come back by then (`Retry-After`), at most in an hour.

= 1.1.0 =
* Added: password preview. Switch it on, set a password, and a password field appears on the holding page — anyone who knows it browses the whole site normally while it stays hidden from everyone else. Meant for a reviewer who has to see the finished site before launch: a payment provider or card processor, a bank, a client's legal team. No account required.
* The password is stored hashed (never in plain text, so it cannot be read back from the settings) and verified with WordPress's own password check. Access is granted by a signed cookie derived from your site's salts — it cannot be forged or reused on another site — and lasts 7 days. Changing or removing the password immediately revokes every existing grant. Wrong guesses are rate-limited per IP, and the form is nonce-protected.

= 1.0.0 =
* First release. On/off switch with an admin-toolbar status pill and one-click toggle; centred mobile-first holding page with logo, title, short text, solid-colour or cover-photo background (with overlay), text colour, theme-inherited or system font, and three text sizes. Administrators keep browsing the real site; everyone else is redirected to the home page and served the holding page on every URL.
* Closes the side doors a front-end-only gate misses: anonymous REST reads (`/wp-json/wp/v2/*`, which would otherwise expose every published page's full content) return `503`, and SEO-plugin sitemaps are redirected. Logged-in users keep full REST access so the block editor still works; `r2cs_rest_allowed_routes` re-opens specific endpoints.
* Cache-safe by design (`DONOTCACHEPAGE` + automatic purging of WP Rocket, LiteSpeed, W3TC, WP Super Cache, SG Optimizer, Cachify, Autoptimize and Kinsta). `503` + `Retry-After` + `noindex` while hidden. Login, wp-admin, AJAX, cron, WP-CLI and `robots.txt` are never blocked.
