Building a WordPress theme from a static HTML template: what nobody tells you
Most tutorials on converting static HTML to WordPress themes focus on the easy parts: splitting the HTML into header.php, footer.php, and index.php, then swapping hardcoded text for template tags like the_title() and the_content(). That’s about 20% of the actual work. The other 80% — the part that determines whether your theme is production-ready or a fragile mess — rarely gets discussed.
Here are the three traps that catch most developers, in the order they’ll hit you.
Trap 1: Leaving asset tags in header.php
Every static template comes with a stack of CSS and JavaScript files linked directly in the HTML head. The wrong move is to leave those <link> and <script> tags in header.php.
The right move is to strip all of them out and register every file through wp_enqueue_style() and wp_enqueue_script() in your functions.php. This isn’t bureaucracy — it’s what makes your theme compatible with plugins, caching systems, and the WordPress admin. Skip this step and your theme will break the moment someone activates a common plugin like WooCommerce.
function mytheme_enqueue_assets() {
$ver = wp_get_theme()->get( 'Version' );
$uri = get_template_directory_uri();
wp_enqueue_style( 'mytheme-main', $uri . '/assets/css/main.css', array(), $ver );
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'mytheme-main', $uri . '/assets/js/main.js', array( 'jquery' ), $ver, true );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_assets' );
Trap 2: Bundling your own jQuery
WordPress ships with its own version of jQuery. If your template bundles another copy — which most Bootstrap-based templates do — you’ll have two jQuery instances fighting each other. You’ll spend hours debugging why your navigation dropdown “sometimes” works and “sometimes” throws $ is not a function in the console.
The fix: delete the bundled jQuery from your template and declare 'jquery' as a dependency when enqueueing your theme’s main JavaScript file. WordPress handles the rest.
Trap 3: Ignoring the template hierarchy
Static templates have everything hardcoded into one file. WordPress needs you to split that content into appropriate template files:
front-page.php— the homepagesingle.php— single blog postpage-{slug}.php— custom page templatessingle-{cpt}.php— single custom post typearchive-{cpt}.php— CPT archiveindex.php— fallback for everything else
Get this wrong and WordPress will render the wrong template for the wrong URL. You’ll be left wondering why your portfolio page is showing your homepage content.
Focus on the infrastructure first
If you’re converting a template right now, focus on these three areas before anything else. The pretty parts — the hero, the animations, the layout — are the easy 20%. The infrastructure is what separates a theme that works for one person from a theme that works for everyone.
Build the plumbing right, and the rest follows naturally.