Taking Back Control: Building a Custom, Secure Netlify Deploy Plugin for Headless WordPress

A desk with a computer decorated with roses.

4 minutes read time.

If you read my previous article on Headless WordPress architecture with Gatsby and Netlify, you already know I’m a huge fan of this approach. It’s fast, modern, and the backend/frontend decoupling offers incredible flexibility.

But let’s be honest: the “honeymoon phase” comes to a screeching halt the first time your Netlify build crashes with an Out-Of-Memory (OOM) error just because you fixed three typos in under a minute.

In this article, we’ll see how I took back control of my deployments, ditched the chaotic automated webhooks, and built my very own lightweight WordPress plugin from scratch.

The Problem with Automated Webhooks

The default workflow in the Headless WP ecosystem relies on a simple premise: you hook up a webhook, and every time you trigger a Create, Update, or Delete (CRUD) action, WordPress nudges Netlify to start a new build.

In theory, it sounds perfect. In practice? It’s a recipe for chaos.

  1. Resource Asphyxiation: If you hit “Save Draft” 5 times in 10 minutes, Netlify queues up 5 builds. The Gatsby workers go crazy, memory maxes out, and you end up with an exit code 2 and a failed deploy. After all the sweat and tears we put into building that deeply nested, 100% accessible React navigation menu, having the site crash over a missing comma in the backend is, frankly, tragic.
  2. The Cache “Ghosts”: Gatsby’s Cache on Netlify is notoriously aggressive. Often, you delete a post in WordPress, but the incremental build completely ignores the action, leaving your deleted post floating around live.
  3. Fire-and-Forget: Webhooks are asynchronous. You hit “Publish,” WordPress cheerfully tells you “Everything is awesome!”, but your Netlify build might silently crash 3 minutes later.

The Decision: Let’s Build a Plugin.

If you prefer to read through the code before you continue reading more, check out the freshly launched repository on GitHub: Explore the netlify-manual-deploy on GitHub.

Are there existing solutions in the WordPress repository? Yes. Are they often abandoned plugins bloated with unnecessary features, database-heavy settings pages, and clunky UIs? Also yes.

Since writing clean code and exploring new architectural setups is the fun part of the job, I decided to write a custom, lightweight plugin.

My requirements were strict:

  • Manual trigger directly from the Admin Bar.
  • The ability to choose between a “Standard Deploy” and a “Clear Cache Deploy”.
  • A visual indicator (Live Status) so I know what Netlify is doing without opening new tabs.
  • Absolute security (Zero Database Footprint).

The Architecture of “Netlify Manual Deploy”

Instead of creating yet another Settings Page that stores a secret Webhook URL in the wp_options database table, I opted for an secure approach: environment variables.

The plugin pulls the Webhook URL and the Netlify Project ID directly from wp-config.php.

// Inside wp-config.php
define('NETLIFY_BUILD_HOOK_URL', 'https://api.netlify.com/build_hooks/your-secret-hook');
define('NETLIFY_SITE_ID', 'your-project-id');

By doing this, the secret keys are never exposed to the front-end, they don’t exist in the database, and the plugin remains entirely stateless.

The UI and the Status Badge

Using the WordPress admin_bar_menu action, I added two sleek buttons:

  1. 🚀 Deploy (Turquoise): Sends a standard POST request to the webhook. Perfect for lightning-fast, incremental builds.
  2. 🧹 Deploy – Clear Cache (Red): Appends a magic ?clear_cache=true parameter to the webhook URL. Netlify intercepts this and forces a clean build from scratch. Ghostbusting complete!

To solve the “fire-and-forget” anxiety, I integrated the Netlify Status Badge directly into the Admin bar. A tiny JavaScript function (setInterval) refreshes the SVG badge every 10 seconds, bypassing the browser cache. Now, I can literally watch the status turn from Building to Success or Failed right from my WordPress dashboard.

Bonus: The “Soft Delete” Trick for Gatsby

Even with a shiny “Clear Cache” button, running full rebuilds just to delete a single post is overkill. WPGatsby (which monitors these events) frequently misses deletions when you send a post directly to the Trash.

Here is the secret workflow I use to handle this gracefully:

  1. Change the post status from Published to Draft and hit Update.
  2. Click the standard 🚀 Deploy button. Gatsby perfectly catches the status change and removes the node via a super-fast incremental build.
  3. Once the deploy succeeds, you can safely move the Draft to the Trash at your own pace.

Conclusion

Sometimes, the best solution isn’t to add another bloated third-party tool to your stack, but to write 150 lines of highly targeted code. With this new manual deploy workflow, the server breathes easily, security is maximized, and control is right back where it belongs.

Share this article:


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.