Building 24 Pages That Don’t Exist in the Database
Yes, you read that correctly. Everyone “knows” WordPress stores pages in wp_posts. Everyone also accepts the slow queries, the meta bloat, the accidental deletions, the import/export nightmares. I don’t. For a SaaS dashboard with 24 different admin screens, relying on database pages is basically architectural self-harm. So I stopped doing it. The Trick WordPress Never

Yes, you read that correctly.
Everyone “knows” WordPress stores pages in wp_posts.
Everyone also accepts the slow queries, the meta bloat, the accidental deletions, the import/export nightmares.
I don’t.
For a SaaS dashboard with 24 different admin screens, relying on database pages is basically architectural self-harm.
So I stopped doing it.
The Trick WordPress Never Told You About
Instead of creating pages in the database…
I just don’t.
I intercept routing before WordPress does anything:
add_action('template_redirect', function() {
$path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
$virtual_pages = [
'app/orders' => 'virtual-pages/all-orders.php',
'app/samples' => 'virtual-pages/all-samples.php',
// ... 20 more
];
if (isset($virtual_pages[$path])) {
global $wp_query;
$wp_query->is_404 = false;
$wp_query->is_page = true;
include get_template_directory() . '/' . $virtual_pages[$path];
exit;
}
});
No posts table.
No queries.
No revisions.
No “who deleted the page?” mysteries.
Just pure, clean routing.
What This Unlocks
1. Pure Performance
Database pages:
SELECT * FROM wp_posts...
SELECT * FROM wp_postmeta...
Virtual pages:
0 queries.
Just vibes.
2. Actual Version Control
virtual-pages/
├── all-orders.php
├── order-details.php
└── edit-sample.php
You edit, commit, deploy.
Your UI is in Git, where it belongs.
3. Zero user screwups
Users can’t delete a page that doesn’t exist.
End of problem.
4. Real SaaS structure
You’re no longer “using WordPress.”
You’re building an app that happens to run on WordPress.
The Full Pattern as Reusable Code
<?php
/**
* Virtual pages loader for WordPress
*
* - Treats PHP files in a folder (e.g. /virtual-pages) as "pages"
* - No entries in wp_posts
* - Works on subdirectory installs (https://example.com/subsite/app/orders)
*
* Usage:
* 1. Put your virtual page templates in: wp-content/themes/your-theme/virtual-pages/
* 2. Create a wrapper template: wp-content/themes/your-theme/virtual-page-wrapper.php
* 3. This class will route /slug to virtual-pages/slug.php
*/
if ( ! class_exists( 'BV_Virtual_Pages_Loader' ) ) {
class BV_Virtual_Pages_Loader {
/**
* Folder (inside the theme) that contains virtual page templates.
*
* @var string
*/
protected $folder;
/**
* Map of slug => file path.
*
* @var array
*/
protected $slugs = [];
/**
* Currently requested virtual page slug (if any).
*
* @var string|null
*/
protected $current_slug = null;
/**
* @param string $folder Relative folder inside the theme (no leading slash).
*/
public function __construct( $folder = 'virtual-pages' ) {
$this->folder = trim( $folder, '/' );
add_action( 'init', [ $this, 'scan_files' ] );
add_filter( 'template_include', [ $this, 'intercept_request' ], 99 );
// Keep titles consistent for virtual pages.
add_filter( 'the_title', [ $this, 'maybe_override_title' ], 10, 2 );
add_filter( 'get_the_title', [ $this, 'maybe_override_title' ], 10, 2 );
}
/**
* Scan the virtual pages folder and register all *.php files as slugs.
*/
public function scan_files() {
$directory = trailingslashit( get_stylesheet_directory() ) . $this->folder;
if ( ! is_dir( $directory ) ) {
return;
}
foreach ( glob( $directory . '/*.php' ) as $file ) {
$slug = basename( $file, '.php' );
$this->slugs[ $slug ] = $file;
}
}
/**
* Get the current request path converted to a slug.
*
* Handles subdirectory installs like /my-site/app/dashboard.
*
* @return string
*/
protected function get_requested_slug() {
$request_uri = parse_url( $_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH );
$site_path = parse_url( home_url(), PHP_URL_PATH );
if ( $request_uri === null ) {
$request_uri = '';
}
if ( $site_path === null ) {
$site_path = '';
}
// Strip the site base path (for subdirectory installs).
if ( $site_path !== '/' && $site_path !== '' && $request_uri !== '' && strpos( $request_uri, $site_path ) === 0 ) {
$request_uri = substr( $request_uri, strlen( $site_path ) );
}
return trim( $request_uri, '/' );
}
/**
* Intercept the template resolution and route to a virtual page if it matches.
*
* @param string $template Default template path.
* @return string
*/
public function intercept_request( $template ) {
$requested_slug = $this->get_requested_slug();
$this->current_slug = $requested_slug;
if ( isset( $this->slugs[ $requested_slug ] ) ) {
// Mark as a valid page, not a 404.
status_header( 200 );
global $wp_query;
$wp_query->is_404 = false;
$wp_query->is_page = true;
// Browser <title>.
add_filter(
'document_title_parts',
function ( $parts ) use ( $requested_slug ) {
$parts['title'] = $this->humanize_slug( $requested_slug );
return $parts;
}
);
// Let title functions know we're on a virtual page.
$GLOBALS['virtual_page_slug'] = $requested_slug;
// Wrapper template: can include header/footer and then load the actual page.
$wrapper = trailingslashit( get_stylesheet_directory() ) . 'virtual-page-wrapper.php';
if ( file_exists( $wrapper ) ) {
return $wrapper;
}
// Fallback: load the virtual page template directly.
return $this->slugs[ $requested_slug ];
}
return $template;
}
/**
* Override the_title() / get_the_title() for virtual pages.
*
* @param string $title
* @param int|string $post_id
* @return string
*/
public function maybe_override_title( $title, $post_id = null ) {
if ( isset( $GLOBALS['virtual_page_slug'] ) && ! is_admin() ) {
return $this->humanize_slug( $GLOBALS['virtual_page_slug'] );
}
return $title;
}
/**
* Get the current virtual slug (optional helper for wrappers).
*
* @return string|null
*/
public function get_current_slug() {
return $this->current_slug;
}
/**
* Convert a slug like "app-orders" to "App Orders".
*
* @param string $slug
* @return string
*/
protected function humanize_slug( $slug ) {
return ucwords( str_replace( '-', ' ', $slug ) );
}
}
// Bootstrap: create loader instance once the theme is ready.
add_action(
'after_setup_theme',
function () {
new BV_Virtual_Pages_Loader( 'virtual-pages' );
}
);
}
You can pair this with a simple virtual-page-wrapper.php like:
<?php
// virtual-page-wrapper.php
get_header();
$slug = isset( $GLOBALS['virtual_page_slug'] ) ? $GLOBALS['virtual_page_slug'] : '';
if ( $slug ) {
$file = trailingslashit( get_stylesheet_directory() ) . 'virtual-pages/' . $slug . '.php';
if ( file_exists( $file ) ) {
include $file;
} else {
echo '<p>Virtual page not found.</p>';
}
}
get_footer();
Real Example: My 24-Page Dashboard
My system has:
- User settings
- Bulk import
- CRM settings
- Order creation
- Order PDFs
- Sample editor
- Notifications
- System config
- Documentation
All inside one folder:
virtual-pages/
├── scan.php
├── manager-dashboard.php
├── create-order.php
└── system-settings.php
Not a single database page.
Deployment is just Git push.
When to Use This
Use it when:
You’re building a SaaS or dashboard
Pages are interface, not “content”
You want Git over database
You want speed
You hate WordPress menus
Avoid it when:
You need the WP editor
Clients manage content
SEO matters
Comments/revisions matter
The Reality Check
WordPress is not an app framework.
But you can bend it.
Hard.
Application pages don’t belong in wp_posts.
They belong in code.
24 pages.
0 posts.
0 database problems.
Maximum control.
Use this pattern and you stop fighting WordPress – you make it work for you.
Bojan