You grab a fresh theme, crack open the Customizer, and start tweaking—I see this all the time, and it usually ends in a mess. You’re inheriting someone else’s markup choices, their script-loading habits, their half-baked performance fixes, all before you write a single line of your own CSS. A rushed start means you’ll burn hours later picking apart conflicts you could have spotted in the first twenty minutes. I treat every theme like I’m doing a pre-build walkthrough. It’s the same routine I use on jooomshaper.com, and it keeps the site snappy, the block editor feeling solid, and the design system from turning into spaghetti.
Start with the Architecture: Files, Templates, and Hierarchy
Before you do anything else, open that theme folder and just look at how it’s organized. A clean theme lays things out so you can tell at a glance where the templates live, where the assets sit, and where the includes get pulled in. I want to see header.php, footer.php, functions.php, and a template-parts directory if the thing is supposed to play nice with blocks. If I spot a functions.php that’s 800 lines long and loading three dozen unrelated scripts, I know right then I’ve found the first thing to fix.

Check how much of the template hierarchy the theme actually covers. Does it bring a single.php, an archive.php, and a 404.php? No 404.php is a small disaster waiting to happen—you’ll be patching that immediately. On a site with broken routing, you might find yourself staring at a “Nothing Found” message right from the start. I wrote up how I deal with that exact headache here: What to Fix First When a New WordPress Site Says Nothing Found.
Dig into functions.php and see how the theme registers its menus, widget areas, and theme support. I expect clear declarations: add_theme_support('post-thumbnails'), add_theme_support('html5', array('search-form', 'comment-form')). Fuzzy or absent support flags usually mean the theme is old or built by someone who didn’t quite get how the current WordPress stack works. Also, keep an eye out for hardcoded URLs. A direct link to a Google Fonts stylesheet instead of a proper enqueue? Yeah, I’m going to strip that and self-host the fonts before I do anything else.
Audit the CSS and JavaScript Loading Strategy
Performance leaks almost always start in how the assets get queued up. Fire up the browser’s DevTools, flip to the Network tab, and reload a single page. Filter down to CSS and JS. Count the requests. A theme that’s put together well loads one main stylesheet and maybe one or two small JavaScript files on a typical page. If you’re looking at 15 CSS files and 10 JS bundles, the developer went for feature overload instead of sane loading.

Go back to functions.php and hunt for wp_enqueue_style and wp_enqueue_script. I’m looking for three signals: conditional loading, dependency declarations, and version parameters. Scripts should only load on the pages that actually need them. A contact form script that fires on every page is just wasted bandwidth. Dependencies need to be spelled out properly—if a script needs jQuery, list it as a dependency so WordPress sorts the order. Version parameters should lean on the theme’s version constant or filemtime() for cache busting. Hardcoded versions turn into a maintenance headache fast.
Watch for inline scripts. A stray tag sitting in header.php or footer.php is a lazy shortcut. Those can’t be deferred or async’d easily, so they block rendering. I also look for render-blocking CSS. If the theme chucks every stylesheet into the with no media attributes and no critical CSS plan, your First Contentful Paint is going to take a hit. Be ready to extract the critical styles and load the rest asynchronously once you start customizing.
Inspect the Block Editor Integration and Markup Quality
The block editor has to feel like a native part of the theme, not an afterthought. Activate the theme, open the post editor, and check the body class. You should see editor-styles-wrapper and the theme’s editor stylesheet loaded inside that iframe. If the backend looks like a completely different website, the theme skipped proper editor styles, and that disconnect will drive page builders up the wall.
Flip into Code View and look at the HTML that comes out of a few basic blocks: paragraph, heading, image, group. I want markup that’s clean and makes sense. A paragraph should be a plain
tag, not a
after an
, not a random
thrown in because someone liked the font size. Extra wrapper divs are often ghosts of old page builders or obsolete frameworks. They make the DOM heavier and your CSS overrides brittle.

Test how the theme behaves at three breakpoints: 480px, 768px, and 1200px. Grab the browser corner and drag it while watching for layout breaks, overflow weirdness, and fonts that don’t scale. A theme that uses relative units like rem and % will adjust more smoothly than one built on fixed pixels. I also turn off JavaScript for a moment and see if the content still reads. If the navigation collapses into a useless lump without JS, you need a CSS fallback or a sturdier progressive enhancement approach.
Evaluate Accessibility and Semantic Structure
Run a quick keyboard-only test. Tab through the page. Can you reach every link, button, and form field? Is there a visible focus ring? If the theme kills the default outline and forgets to add its own style, it’s failing the most basic accessibility check. On any client project, that’s a hard stop.
Check the heading hierarchy on a sample page—use a browser extension or just scan the source. There should be exactly one
, usually the post or page title. Subheadings should nest in order. Screen readers depend on that structure to make sense of the page. If the theme uses headings for visual styling instead of document structure, you’re going to be rewriting those templates.
Look for ARIA landmarks. The theme should use HTML5 sectioning elements—
,
,
—or explicit ARIA roles. A missing element is a common slip that breaks skip-to-content links. While you’re in the code, check how alt text gets handled. The theme should output featured image alt attributes without making you tweak every template manually.
Test Plugin Compatibility and Update Mechanisms
You haven’t finished the audit until you see how the theme deals with plugin output. Install WooCommerce or a forms plugin, even if you don’t plan to keep them around. Visit the shop page, a single product page, the cart. Does the theme force its own markup around plugin content, or does it leave the plugin’s default templates alone? Overly aggressive theme wrappers break plugin styling and make updates a gamble.
Watch for bundled plugins. Some commercial themes arrive with 12 required plugins for sliders, page builders, portfolio types—the whole circus. That’s not a theme; it’s a locked room. I get suspicious of any theme that demands more than one or two focused plugins. The more plugins it forces on you, the heavier the maintenance load and the slower the site.
Look at how the theme handles updates. If it’s from the WordPress.org repo, updates come through the dashboard cleanly. For a premium theme, check for a built-in update class that pings the author’s server. That class should connect over HTTPS and fail quietly if the server is unreachable. A poorly written update checker can white-screen your admin if the author’s site goes offline.
Review the Enqueued Data and REST API Exposure
Open the page source and search for wp-json. Plenty of themes now reach for the REST API for lazy loading or live search. I check which endpoints are exposed and whether the theme passes nonces properly. A theme that leaks user data through an unauthenticated endpoint is a security hole. Also, look for inline JSON objects that hand PHP data to JavaScript. These should be localized with wp_localize_script() and contain only what that component actually needs. I’ve seen themes dump entire post objects into a script tag—content, author emails, metadata, all of it. That’s a data leak, plain and simple.
Scan for hardcoded API keys or credentials. A leftover Google Maps key in a template file is more common than you’d think. Even if the key is restricted, it doesn’t belong in theme code. Keys live in wp-config.php or environment variables, never in version-controlled template files.
Frequently Asked Questions
How long should a theme audit take before customization?
For a standard brochure site, I usually spend 45 to 90 minutes. That covers the file structure, asset loading, editor integration, basic accessibility, and a quick plugin test. If the theme has custom post types or heavy JavaScript, I block out two to three hours. The time you put into auditing always comes back to you during the build, when you sidestep hours of debugging weird conflicts.
What's the single biggest red flag in a theme audit?
A functions.php that loads scripts and styles on every single page, no conditions, no questions asked. That pattern tells you the developer wasn’t thinking about performance or context. It usually brings friends: inline CSS, hardcoded external font URLs, no editor stylesheet. When I see that, I know I’m going to spend a chunk of the customization phase just cleaning up the asset mess before any real design work starts.
Can I fix a poorly built theme, or should I start over?
It depends on the markup. If the HTML is semantic and the problems are mostly about asset loading and missing editor styles, you can rehab the theme. If the markup is a soup of nested divs and the templates ignore the WordPress hierarchy, you’ll burn more time patching than building. In that case, I grab a solid base like a block-first starter theme. The audit tells you which road you’re on.
Should I audit a theme differently if I'm using a page builder?
Yeah. With a page builder, the theme’s job shrinks to providing a clean canvas. I focus on the header and footer templates, the default body classes, and how the theme handles the builder’s full-width templates. The theme shouldn’t inject its own container divs into builder content areas. I also check if the theme enqueues its own CSS that overrides builder styles. A good builder-friendly theme gets out of the way completely.
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.

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.

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.

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

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.

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__inandignore_sticky_postsset 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_keyandorderbyset tometa_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.

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
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.

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.

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.