Why Plugin Count Is a Weak Proxy for Site Health

The same discussion lands in a project chat or client inbox every few months. Someone runs a quick audit, skims the plugin list, and decides the site is in trouble because the number feels high. Maybe it’s 35 plugins. Maybe it’s 52. The number turns into the diagnosis. That instinct is wrong, and it pushes teams to waste hours on the wrong fixes while the actual structural problems sit there untouched.

Plugin count is a lazy metric. It reveals almost nothing about how a WordPress site performs under load, how maintainable it stays over time, or how wide the security surface really is. I build and repair WordPress installations for a living, and I’ve picked apart sites with 18 plugins held together by brittle custom code and sites with 70 plugins that ran clean benchmarks on modest hardware. The difference is never the integer. It’s the engineering discipline behind the stack.

Server rack with blinking lights, representing the infrastructure layer that matters more than plugin count

The Number Itself Tells No Story

When you stare at a plugin list showing 45 entries, what do you actually know? You don’t know how many database queries each one tacks onto a typical page load. You don’t know if those queries are indexed or scanning entire tables. You don’t know if three of those plugins are practically dormant, providing small utility functions that fire only in the admin area. You don’t know if one plugin carries the heavy lifting for an entire feature set while five others are lightweight wrappers.

A plugin is a container. Some containers are huge, loading their own React build, registering custom post types with inefficient meta queries, and enqueuing assets on every front-end request regardless of context. Others are a single PHP file with one filter hook. Counting them equally is like judging a city’s traffic by counting vehicles without distinguishing between bicycles and freight trucks.

The real questions are architectural. What’s the query overhead per request? How many external HTTP calls fire on critical paths? Are the plugins that run on the front end properly scoped to their context, or are they initializing on every page whether they’re needed or not? These are the measurements that correlate with time-to-first-byte, server memory pressure, and the slow degradation that makes users grumble.

What Actually Degrades Performance

Performance problems in WordPress almost always trace back to a small set of root causes. The most common is unindexed or poorly structured database queries. A plugin that stores session data in the options table without an autoload strategy can add milliseconds to every uncached request. A plugin that runs a complex meta query on a non-indexed key across thousands of posts will tug the database server down under moderate traffic. Neither problem is visible from the plugin count.

Next up is asset loading discipline. Many plugins enqueue CSS and JavaScript globally because it’s easier than writing conditional logic. A site with 30 plugins might load over 40 stylesheets and 30 script files on the homepage, even though only a fraction are actually used. But a site with 15 plugins could do the same damage if each one is careless. Flip it around: a site with 50 plugins where every asset is conditionally loaded and concatenated through a build process might deliver a lean bundle.

The third factor is external service dependency. Plugins that phone home to license servers, pull in remote fonts, or load third-party chat widgets introduce network latency that no amount of server tuning can erase. A single poorly implemented external call can block rendering for seconds. That’s one plugin, not a count problem.

Close-up of a database server screen showing query logs, representing real performance analysis

Then there’s the PHP execution profile. Some plugins hook into init or wp_head and run heavy logic on every request. Others use lazy loading, only booting their code when a specific shortcode or block is encountered. You can’t see this from the plugins screen. You need a profiler like Query Monitor or Xdebug to trace what’s actually happening during a request lifecycle.

Security Surface: More Layered Than a Count

The security conversation around plugin count usually goes like this: more plugins mean more code, and more code means more potential vulnerabilities. That’s true in the abstract, but it’s not a useful risk model. The risk isn’t the number of plugins. It’s the maintenance posture of each one, the quality of the vendor’s security practices, and how tightly the plugin’s capabilities are scoped.

A site running 25 plugins, all from reputable developers with consistent update histories and minimal privilege requirements, sits in a far better position than a site running 8 plugins where two are abandoned, one has known unpatched vulnerabilities, and another requests administrator-level capabilities it doesn’t need. The count-based approach would flag the first site and ignore the second. That’s not security thinking; it’s numerology.

What matters is the update cadence. Check when each plugin was last updated. Check the changelog for security-specific entries. Check whether the plugin is still actively supported in the repository. A plugin that hasn’t been updated in two years and has open support threads about compatibility with current WordPress versions is a risk, regardless of how many other plugins are installed.

Equally important is the principle of least privilege. Does a contact form plugin really need to manage options across the entire site? Does a gallery plugin need to write files outside the uploads directory? These are architectural security questions. They don’t appear in a plugin count, but they define the actual attack surface.

Maintainability: The Real Cost Driver

The strongest argument for keeping plugin numbers low isn’t performance or security in the immediate sense. It’s long-term maintainability. Every plugin is a dependency. It has its own update cycle, its own compatibility requirements, its own potential for conflicting with other plugins or with theme code. More dependencies mean more things that can break during a WordPress core update or a PHP version bump.

But even here, the count is a weak substitute for real analysis. What you actually want to gauge is dependency complexity. Three plugins that each do one small, well-defined thing with no overlap in functionality are simpler to maintain than one monolithic plugin that does everything through tangled code with side effects across the admin, the REST API, and the front end.

I’ve worked on sites where a single “all-in-one” plugin caused more maintenance overhead than ten smaller, focused plugins combined. When that monolithic plugin needed an update, it risked breaking the page builder, the SEO markup, and the custom fields all at once. The smaller plugins could be updated individually, tested in isolation, and rolled back without collateral damage.

This is where systematic troubleshooting habits pay off. When something breaks, you want to isolate the cause fast. A site built from small, single-purpose plugins with clear boundaries makes that possible. A site built from a few sprawling plugins turns every problem into a multi-hour archaeology dig.

What to Measure Instead

If plugin count is off the table, what should you actually track? Start with these signals. They tell you more about site health than any integer ever will.

Time to First Byte and Server Response Profile

Measure TTFB under load, not just from a cold cache on a quiet server. Use a tool like Siege or k6 to send concurrent requests and watch how the server’s response time degrades. A site that stays flat under 50 concurrent users is well-built, regardless of plugin count. A site that spikes to multi-second response times with 10 concurrent users has a structural problem that needs profiling.

Query Count and Slow Query Log

Enable the slow query log in MySQL or MariaDB and actually read it. Look for queries that appear frequently, scan large tables, or lack proper indexes. A single plugin generating an unindexed meta_value query on every page load does more damage than twenty plugins that only run targeted queries against indexed columns.

Update Health and Abandonment Rate

Track the percentage of installed plugins that have been updated within the last three months. Track the number of plugins that are no longer receiving updates from their authors. A site with 40 plugins where 38 are actively maintained is healthier than a site with 15 plugins where 5 are abandoned. This is a ratio, not a count, and it’s actionable.

Developer reviewing code and update logs on a laptop, representing active maintenance practices

Asset Weight and Critical Path Blocking

Run Lighthouse or WebPageTest and look at the render-blocking resources. Count the kilobytes of CSS and JavaScript loaded before first paint. A site with many plugins that all defer their assets or load them inline only when needed may have a smaller blocking footprint than a site with few plugins that all enqueue globally. The number on the plugins screen won’t whisper any of this.

Building a Health Model That Works

The way out of the plugin-count trap is to build a health model based on observable behavior, not a static inventory. When I evaluate a site, I look at the request waterfall first. I profile the database. I check update logs. I look at what’s actually executing, not what’s installed. The plugin list is a starting point for that investigation, not a conclusion.

This matters because teams make real resource decisions based on these assessments. I’ve watched development sprints get derailed by a mandate to “reduce plugins to under 20,” which led to weeks of refactoring that produced no measurable improvement in page speed or server load. The time would have been better spent adding a missing database index, implementing a proper object cache, or conditionally dequeueing assets that didn’t belong on certain pages.

There’s also a design-aware dimension here. When a site is built with intention, each plugin earns its place. The plugin list should read like a deliberate architecture, not an accumulation. That’s a qualitative assessment, not a quantitative one. You can feel it when you look at a site that’s been composed thoughtfully versus one assembled through trial and error. The plugin count alone doesn’t distinguish between those two states.

FAQ

Is there any number of plugins that is objectively too many?

No fixed number works as a universal threshold. I’ve seen stable, fast sites running 80+ plugins on well-tuned infrastructure. The limit isn’t the count but the cumulative engineering quality of the plugins, the server resources available, and the caching strategy in place. If every plugin is well-written, actively maintained, and properly scoped, the number itself is irrelevant.

How can I quickly identify which plugins are actually causing performance problems?

Use Query Monitor to profile a representative set of pages. Look for plugins generating slow or duplicate queries. Check the HTTP API calls tab for external requests blocking the page load. Then flip to the “Scripts and Styles” tab to see which plugins are enqueuing assets globally. These three data points will identify the real offenders much faster than guessing based on plugin names or counts.

Should I avoid plugins that do many things in favor of many single-purpose plugins?

Generally, yes, but with an important caveat. Single-purpose plugins are easier to audit, replace, and maintain in isolation. But if they come from unreliable vendors or have overlapping functionality that causes conflicts, the benefit evaporates. The principle is to choose plugins with clear boundaries and minimal side effects, whether they’re single-purpose or multi-feature. The architecture matters more than the feature count inside each plugin.

What’s the first thing I should fix when a site has too many plugins?

Don’t start by removing plugins. Start by profiling the site to find actual bottlenecks. Often, the biggest performance win comes from database indexing, object caching, or fixing one problematic plugin’s asset loading behavior. If you do need to reduce the plugin footprint, begin with plugins that haven’t been updated in over a year or that duplicate functionality already handled elsewhere in the stack. For a deeper walkthrough on diagnosing a troubled site, see what to fix first when a new WordPress site says nothing found.

The next time someone points at a plugin count and declares a site unhealthy, ask them what the slow query log says. Ask them what the TTFB distribution looks like under load. Ask them how many of those plugins have been updated this quarter. Those are the conversations that lead to better systems. The integer on the plugins screen leads nowhere.

How to Build a WordPress Homepage That Does More Than List Posts

Clean WordPress homepage layout on a laptop screen

The stock WordPress homepage is a lazy river of posts in reverse chronological order. That’s fine if you run a simple diary. But if you’re juggling a product, a service, a knowledge base, or some weird hybrid publication, that timeline turns into noise fast. You need a front page that routes attention, surfaces the right blocks, and works like a dispatcher—not a default feed.

We’re not talking about grabbing a page builder and dragging widgets around. This is about how WordPress decides what a homepage is, where the levers are, and how you design a front door that points people toward different corners of the site. I’ll walk through the guts, the template logic, and the exact moves that make a homepage actually earn its keep.

Stop Treating the Homepage as a Blog Feed

Out of the box, WordPress leans on home.php or index.php to loop through your posts. Handy for a daily journal. But most sites carry static payloads—landing sections, featured case studies, doc hubs, product grids—that deserve a spot on the front page. A post list buries those assets beneath a stack of pagination links.

The first real fork in the road: static page or posts page. Go to Settings → Reading and you’ll find the toggle. Picking a static homepage opens things up. Now you can assign a custom page template, inject dynamic content with blocks or PHP, and quit pretending your freshest article is the most important thing on the site.

Even a static page can land like a wet blanket if it’s just a text wall. The homepage should be a route map. Someone lands and immediately clocks the pathways: “I want to read about X,” “Where’s the contact page,” “Show me the specs.” Every chunk of the page should steer intent somewhere useful.

Map Content Zones Before You Touch Code

Before you crack open a template file, scratch out the zones your homepage needs. Typical ones include:

  • Hero or masthead: value prop, a main call-to-action, maybe a search bar.
  • Featured content block: hand-picked posts, pages, or custom post types.
  • Dynamic query section: latest from a specific category, popular this week, stuff tied to a sticky tag.
  • Static resource grid: links to docs, tools, landing pages.
  • Social proof or activity stream: testimonials, client logos, a tight feed of updates.

Each zone is a query or a chunk of markup. Treat them like modules. In classic themes, they become template parts or custom loops. In block themes, they’re group blocks with query loop blocks tucked inside. This mapping step stops you from building a Frankenstein page that tries to do ten things and fails at nine of them.

Wireframe sketch of homepage content zones with a pen and markers

Build a Custom Page Template That Pulls Its Weight

If you’re in a classic theme, make a file like page-home.php. WordPress grabs it automatically for a page slugged home or when you set it as the static front page. Inside, you can sidestep the default loop completely.

Here’s a stripped-down skeleton:

<?php
/* Template Name: Homepage */
get_header();
?>

<main class="homepage">
  <?php get_template_part( 'template-parts/home/hero' ); ?>
  <?php get_template_part( 'template-parts/home/featured' ); ?>
  <?php get_template_part( 'template-parts/home/dynamic-latest' ); ?>
  <?php get_template_part( 'template-parts/home/resource-grid' ); ?>
</main>

<?php get_footer(); ?>

Each template part handles one zone. featured.php might run a WP_Query loop pulling posts with a certain tag or from a custom post type. dynamic-latest.php could show the three newest items from a “News” category. Keeping things modular means you can shuffle, replace, or conditionally load zones without rewriting the whole page.

For block themes, the approach shifts but the idea sticks. Use the site editor to craft a custom front page template. Drop a Query Loop block inside a group, filter by category or tag, and set the layout to a grid. Stack multiple query loops for different content buckets. The block editor is mature enough now to build a fully dynamic homepage without touching PHP—though complex filtering or custom field display still hits its ceiling.

Design the Hero to Convert, Not Just Decorate

A hero section that just says “Welcome to My Site” is dead weight. It needs to answer two questions inside two seconds: What is this place? and What should I do next? A clean heading, a single supporting sentence, and one primary action—a button, a search input, a signup form.

Technically, the hero can be a cover block with an overlay, a hand-coded section in your template part, or even a reusable block pulled in via get_template_part. If you need the background to shift dynamically—say, grabbing a featured image from a sticky post—write a tiny function that fetches the image URL and hands it off to the template.

When you link that primary action, think hard about where it sends people. If a critical landing page is currently throwing a 404 or a soft “Nothing Found” message, you’re torching trust right out of the gate. I’ve poked at that exact scenario in What to Fix First When a New WordPress Site Says Nothing Found—same principles apply to any high-traffic destination you link from the homepage.

Query Loops That Do More Than “Latest Posts”

The loop is where most homepages get lazy. One query for the ten most recent posts ignores the rest of your content structure. Instead, run several focused queries:

  • Sticky posts as featured: stick 2–3 posts and pull them with post__in and ignore_sticky_posts set to 0 in a secondary query.
  • Category-specific latest: a grid of the newest from “Tutorials” and a separate list from “Case Studies.”
  • Popular or high-traffic: if you track views, store counts in post meta and query with meta_key and orderby set to meta_value_num.
  • Manual curation: use a custom field like “featured_on_homepage” (boolean) and query posts where that field is true. Editors get direct control without touching code.

Set no_found_rows to true on each query if pagination isn’t needed. It lightens the database hit. And always, always reset postdata with wp_reset_postdata() after a custom WP_Query loop so you don’t trash later template tags.

Code editor showing a WordPress query loop with syntax highlighting

Stitch in Static Resources Without Hardcoding Chaos

Your homepage probably needs to point to pages that aren’t blog posts: an About page, a docs hub, a tools directory, a contact form. Hardcoding those links in a template is brittle—one slug change or a deleted page and things snap.

Lean on menu locations and customizer settings instead. Register a “Homepage Resources” menu in functions.php and let site admins fill it with links. For more structured stuff, spin up a custom post type like “Resource” with fields for title, description, icon, and URL. Loop through them on the homepage. Content stays editable without poking template files.

If you’re in the block editor, a simple group block with paragraph links works, but it’s still a manual chore. A sharper move: create a synced pattern (the old reusable block) with a grid of buttons or cards linking to key pages. Update the pattern once, and it ripples everywhere—including the homepage.

Performance Is a Feature of Homepage Design

A homepage with five custom queries, fat background images, and third-party embeds will hammer your Largest Contentful Paint score. Design has to account for that from the jump.

  • Query caching: use the object cache or a plugin to stash results of expensive queries for a few minutes. The homepage rarely needs real-time freshness.
  • Image sizing: if your hero pulls a full-width image, register a custom image size that matches the exact container dimensions. Don’t serve a 2000px-wide image in a 1200px slot.
  • Lazy loading: native lazy loading on below-the-fold images keeps off-screen assets from blocking the first render.
  • Conditional loading: if a zone needs a heavy script (a slider, an interactive map), only enqueue that script when the homepage template is active.

Test the page with query monitoring switched on. If a single zone adds 200ms to the server response, either cache it or simplify the query. A homepage that loads in under 1.5 seconds is a conversion engine; one that drags past 4 seconds is a bounce factory.

Make the Homepage Editable Without Breaking It

A hard-coded template is fast and clean, but it locks content editors out. The middle path is to use WordPress’s block template system or to expose controls through the Customizer or block editor.

For classic themes, add a handful of Customizer settings: hero heading, hero subtext, hero background image. Those populate the template parts without anyone touching PHP. For block themes, build the homepage template with a mix of dynamic blocks (Query Loop, Site Title, Navigation) and static blocks editors can tweak. Lock the template so they can’t delete the skeleton, but let them swap the featured post or update the hero copy.

One pattern I keep coming back to: create a dedicated “Homepage” custom post type with meta fields for each zone. The homepage template queries that single post and uses its meta values to populate the page. Editors get a single screen to steer the entire front page, with validation on each field. It’s more upfront work, but it wipes out the “I broke the homepage” support tickets.

FAQ: WordPress Homepage That Works Harder

How do I set a static homepage in WordPress?

Head to Settings → Reading in the dashboard. Under “Your homepage displays,” pick “A static page.” Select a page you’ve already created for the homepage, and optionally choose a different page for blog posts. Save. If you’re using a custom page template, assign it to that homepage page in the page editor.

Can I mix static content and dynamic post lists on the same homepage?

Sure. In a classic theme, write a page template that blends hard-coded HTML with custom WP_Query loops. In a block theme, stack paragraph, image, and group blocks alongside Query Loop blocks that pull posts by categories, tags, or other filters. The trick is arranging the page so static and dynamic sections don’t step on each other’s toes.

Why is my custom homepage template not showing up?

First, check that the template file has the /* Template Name: Your Name */ comment at the top. Second, confirm the page set as the static homepage actually has that template selected in the page editor. If you’re on a block theme, templates live in the site editor under Appearance → Editor, not as individual page templates. Also verify you didn’t accidentally name the file front-page.php, which WordPress grabs automatically and would override your assignment.

How many queries is too many for a homepage?

No hard ceiling, but every custom WP_Query adds database weight. For a typical site, three to four focused queries (hero, featured, latest, resources) is reasonable if they’re properly indexed and cached. If you catch yourself running six or seven, look for ways to consolidate—fetch multiple post types in a single query using an array of post types, or stash results in a transient for an hour. Keep Query Monitor open during development so you can see the real cost.

What to Fix First When a New WordPress Site Says Nothing Found

Close-up of WordPress admin dashboard showing permalink settings

You launch a fresh WordPress install. You create a test post. You click “View Post” — and the screen stares back with a blank, gray “Nothing Found.” No error codes, no stack traces, just that quiet, design-less void. For a systems engineer who builds sites from the ground up, this moment is equal parts irritating and telling: something in the stack isn’t resolving requests the way WordPress expects. The fix is almost never inside the content itself. It’s in the wiring.

I’m Jonas Venn, and on jooomshaper.com I work through the structural layer of WordPress — how requests flow from the web server through PHP, how rewrite rules turn pretty permalinks into query variables, and why a misstep in any of those layers produces exactly this symptom. This article walks through the first three things to check, in order, when a new WordPress site returns “Nothing Found.” No guesswork. No generic advice. Just the technical sequence that resolves the problem in the majority of cases.

Check One: Permalink Structure and Rewrite Flush

WordPress serves content by translating a URL like /hello-world into an internal query that looks something like ?p=1. That translation happens through a set of rewrite rules stored in the database. On a brand-new install, those rules might be empty, stale, or misconfigured — especially if the site was set up via a script, a migration, or a one-click installer that didn’t complete the standard post-installation flush.

The symptom is predictable: you can see posts in the admin list, they’re published and public, but visiting their permalink returns “Nothing Found.” Meanwhile, the default plain permalink structure — ?p=123 — works fine when you type it directly in the browser. That tells you the content exists; the rewrite engine just isn’t mapping the pretty URL to it.

Step-by-Step Diagnosis

Start in the admin panel under Settings → Permalinks. If the selected option is “Plain,” switch it to “Post name” (the most common choice for clean URLs) and click Save Changes. WordPress will call flush_rewrite_rules() behind the scenes, rebuild the rewrite array, and update the .htaccess file on Apache servers or the internal rewrite store on Nginx. Don’t just save without changing; the act of selecting something and hitting save triggers the flush. If it’s already set to “Post name,” select “Plain,” save, then select “Post name” again and save. This forces a full rebuild.

After saving, visit a post’s permalink. If “Nothing Found” disappears, you’ve solved it in under a minute. If it persists, the issue sits deeper — likely in the web server configuration or a plugin that’s intercepting the query before WordPress can process it.

When Rewrite Flush Isn’t Enough

Some managed hosting environments and custom Docker setups cache rewrite rules aggressively. If you’re using an object cache like Redis or Memcached, the flush might not propagate immediately. Run wp rewrite flush from WP-CLI if you have shell access; it bypasses the admin UI and directly resets the rules. For sites without WP-CLI, adding $wp_rewrite->flush_rules(); temporarily to a theme’s functions.php (and removing it afterward) achieves the same effect. But approach that cautiously — you’re touching the theme file, and a syntax error there can lock you out of the admin.

Lines of code in a text editor representing WordPress rewrite rules

Check Two: Web Server Rewrite Rules

If the permalink structure is correct and the rewrite flush didn’t help, the next stop is the web server. WordPress relies on the server to pass requests through a single entry point — index.php — with the original request URI intact. When that mechanism breaks, WordPress receives a mangled or empty request and can’t map it to any post, page, or archive. The result is the same “Nothing Found” message, but the cause is now a configuration issue, not a database issue.

Apache: The .htaccess File

On Apache, look inside the site’s root directory for .htaccess. A standard WordPress block looks like this:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

If the file is missing entirely, WordPress can’t write it — often because the file system permissions won’t allow it. Create it manually with the block above, making sure the file is readable by the web server user. If the file exists but the rules are different, a security plugin or a previous developer may have modified them. Restore the default block, then flush permalinks again from the admin.

Also check that Apache’s mod_rewrite module is enabled. On Ubuntu or Debian, sudo a2enmod rewrite followed by sudo systemctl restart apache2 activates it. Without that module, the .htaccess file is ignored, and pretty permalinks simply won’t work.

Nginx: Try Files and Location Blocks

Nginx doesn’t use .htaccess. Instead, the site’s server block must include a directive that sends all non-static-file requests to index.php. The standard configuration looks like this:

location / {
    try_files $uri $uri/ /index.php?$args;
}

If your Nginx config uses an older or incomplete pattern — like try_files $uri $uri/ =404; — WordPress will never receive the request for a pretty permalink, and “Nothing Found” will appear. Edit the server block, test with nginx -t, and reload Nginx. In some setups, the location ~ \.php$ block also needs to include fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; and other standard FastCGI parameters. A missing PATH_INFO parameter can cause similar symptoms on certain PHP configurations.

After adjusting the server config, flush permalinks once more. The combination of correct rewrite rules in WordPress and a correct server setup almost always resolves the issue at this stage.

Check Three: Query Interference and Home URL Mismatches

If the permalink structure is flushed and the server rules are verified, the problem is likely in how WordPress interprets the request. Two common culprits stand out: a plugin (or theme function) that modifies the main query through pre_get_posts incorrectly, and a mismatch between the WordPress Address (URL) and Site Address (URL) settings.

The pre_get_posts Trap

Developers use the pre_get_posts action to alter the default query — for example, to change the number of posts shown on an archive page or to exclude a category from the home page. But if the action doesn’t check is_main_query() or applies conditions that accidentally affect single post requests, it can wipe out the query’s ability to find a post. The function might set a meta query that returns zero results, or it might alter the post type parameter so that the requested post type is excluded. The result is “Nothing Found” on every single post, while pages and archives work normally. I’ve wasted an afternoon on this exact scenario. You start doubting the database, the server, your career choices — and it’s just an overeager callback in a forgotten plugin.

To test, temporarily switch to a default theme (Twenty Twenty-Four or similar) and deactivate all plugins. If the problem disappears, reactivate them one by one until it returns. When you find the offending plugin, look at its pre_get_posts callback. The fix is often a simple conditional: if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) — the key being that it only runs on the specific query you intend to modify, not on every query across the site.

Home and Site URL Mismatch

Under Settings → General, two fields define the site’s address. If the “WordPress Address (URL)” points to a different domain or subdirectory than the “Site Address (URL),” and the server isn’t configured to handle that split, WordPress may generate permalinks that don’t match the request path. For example, if WordPress is installed in a subdirectory but the site address is set to the root domain, the rewrite rules might expect a prefix that isn’t present in the actual URL. The query fails to find the post, and “Nothing Found” appears.

Verify that both URLs are correct and that the site is accessible at the address you expect. If you need to change them, do it through the admin UI if you can still access it, or directly in the wp_options table (siteurl and home rows) if you can’t. After changing, flush permalinks one more time.

Person typing on a laptop keyboard, focusing on web development tasks

When It’s Not a Standard Install

Some setups introduce variables that break the usual debugging sequence. Multisite networks, Bedrock-style directory structures, and Composer-based installations all move core files away from the web root. In these cases, the .htaccess or Nginx config must point to the correct index.php location. A Bedrock site, for instance, expects the web root to be /web, not the project root. If the server block points to the wrong directory, WordPress never loads, and the request falls through to a 404 handler that displays “Nothing Found” from the theme’s index template.

Similarly, sites behind reverse proxies or load balancers can lose the original request URI. If the proxy forwards requests without setting the X-Forwarded-Host or X-Forwarded-Proto headers, WordPress may reconstruct the URL incorrectly. In wp-config.php, adding explicit definitions for WP_HOME and WP_SITEURL — and sometimes adjusting $_SERVER['HTTPS'] — gives WordPress the information it needs to build correct permalinks and process the query.

Why the Order Matters

I’ve watched developers jump straight to database repair plugins or core file replacements when a site says “Nothing Found.” That’s like rebuilding an engine because the car won’t start, without checking the battery first. The permalink structure and rewrite flush are the fastest, least invasive checks — they solve the problem in under a minute for a large chunk of new sites. Server rewrite rules come next because they’re the transport layer: if the request never reaches WordPress in a recognizable form, no amount of admin tweaking will help. Query interference and URL mismatches are the third tier because they’re more layered and require understanding how a specific plugin or configuration alters the default behavior. Skip the order, and you’ll burn hours chasing ghosts.

Following this sequence keeps you grounded in the request lifecycle. It turns a vague, frustrating error into a straightforward debugging path that respects the architecture you’ve built.

FAQ

Why does “Nothing Found” appear only on custom post types?

Custom post types need their rewrite rules registered before the permalink flush. If you registered the post type in a plugin or theme’s functions.php but forgot to flush permalinks afterward, WordPress doesn’t know how to route those post type URLs. Go to Settings → Permalinks and click Save Changes to rebuild the rules. If the post type uses a custom slug or archive, confirm that the has_archive and rewrite arguments are set correctly in the registration code.

Can a caching plugin cause the “Nothing Found” message?

Yes, especially if the cache holds a stale page where the content wasn’t yet published or the rewrite rules changed after the cache was generated. Clear the cache from the plugin’s settings and disable the plugin temporarily to see if the issue resolves. Some object caching systems also store rewrite rules; if you’re using Redis or Memcached, flush the object cache after changing permalink settings.

What if my site uses a static front page and the blog page says “Nothing Found”?

This usually happens when the “Posts page” setting under Settings → Reading points to a page that doesn’t exist or was deleted. WordPress tries to load that page as the blog archive, but without a valid page object, the query returns no results. Check the reading settings and make sure the selected posts page is published and not in the trash. If you don’t need a separate blog page, set “Posts page” to “— Select —” and rely on the default archive behavior.