← Engineering journal

Theme architecture20 min read

BlankSlate. The freedom to build deliberately.

A technical look at BlankSlate: design freedom, inherited behaviour, performance budgets and the engineering responsibility behind a deliberately minimal starting point.

Field notes / WordPress engineering

The basic principle

Most ready-made WordPress themes arrive with decisions about how a website should look and behave. BlankSlate leaves much more of that work to the developer. That can make it easier to build a website around a specific business, its content and its design, while controlling which code the finished pages actually need. The trade-off is that the team must supply the layouts, editing tools, accessibility, testing and ongoing maintenance. Starting with less can help you build something better, but only if the decisions you add are good ones.

A theme can give a project a head start. It can also give it a set of assumptions that the rest of the build spends its life negotiating. BlankSlate is interesting because it leaves much of that visual decision-making to the people building the website.

That freedom is valuable when the brief deserves its own design system, its own content structures and carefully controlled behaviour. It also comes with a bill: the implementation, testing and maintenance that a finished theme might have supplied now belong to your team.

This essay examines BlankSlate as an engineering starting point. The source-specific observations refer to the 2026 release installed in our development environment, reviewed on 17 September 2026. The comparisons concern architecture and workflow; they are not a speed ranking or a claim that one theme will outperform another on every website.

What BlankSlate actually gives you

BlankSlate is a minimalist WordPress starter theme: an installable foundation with relatively little visual styling, intended for developers to build upon. The official theme listing describes an unstyled boilerplate with a CSS reset. Its value is the small amount of finished design it imposes.

The release examined here is a classic PHP theme. It supplies template files, WordPress hooks and a stylesheet rather than a complete visual site-building system. It participates in the normal WordPress template hierarchy. The database, user system, plugin APIs, content processing and request lifecycle remain WordPress. Installing a minimal theme does not bypass that application.

It is also useful to separate the block editor from a block theme. A PHP theme can support block-authored content and can adopt parts of theme.json; that does not automatically turn it into a block theme with editable site templates. WordPress documents these distinctions in its theme structure guide and introduction to theme.json.

BlankSlate does not decide whether your website needs ACF, a component library, a bundler or a page builder. Those are separate architectural choices. An empty-looking homepage is the beginning of the work, not evidence that the work has been completed.

A minimal theme foundation supports an independently designed interface01 / YOUR INTERFACEDESIGNED TO THE BRIEF02 / YOUR SYSTEMTOKENS + COMPONENTS03 / THE FOUNDATIONBLANKSLATE + WORDPRESS
The foundation supplies a starting structure. Your design system and interface remain explicit, separately considered layers.

Compare the kind of starting point, not just the theme name

BlankSlate: a developer-led foundation

Choose this route when your team wants close control over markup, components, CSS and interaction. You begin with relatively few visual commitments and supply the product design yourself. The trade-off is that a polished header, accessible mobile navigation, archive layouts, form treatment and coherent editing experience still have to be delivered.

GeneratePress: an established theme system

GeneratePress offers a developed theme ecosystem with optional capabilities and starter sites. It can be a sensible route when its conventions align with the project and reusing those conventions saves real work. A considered implementation can still be distinctive and fast. The decision is whether its existing system helps the brief or whether you will spend most of the build replacing it.

Twenty Twenty-Five: block templates and editorial composition

Twenty Twenty-Five is a block theme with patterns and style variations. It is a useful comparison when editors need to compose layouts and manage site presentation through WordPress’s block-based tools. Its starting point includes design decisions, but those decisions are configurable. A custom block theme is also a valid way to obtain an original design; BlankSlate has no monopoly on that outcome.

Hello Elementor: a minimal base for a visual builder

Hello Elementor is designed around Elementor’s editing workflow. Its minimal theme layer should be assessed alongside the builder, widgets and integrations that deliver the finished pages. Comparing the ZIP size of Hello with the ZIP size of BlankSlate tells you little about those complete implementations. The attraction here is the visual production workflow; the implementation cost includes the system providing it.

A fully owned custom theme

A standalone custom classic or block theme removes the ongoing parent-theme relationship. You control every shipped theme file, but you also own its upkeep. A starter can help create that first version; it does not remain an independently updatable parent unless you deliberately preserve that architecture.

These routes solve different organisational problems. An editorial team that needs layout freedom, a small business that needs a good site quickly and an agency implementing an unusual art direction may reasonably make different choices. “Custom” does not automatically mean better, and “prebuilt” does not automatically mean generic.

Designing to the brief instead of negotiating with it

The strongest argument for BlankSlate is often design ownership. Start with the content, brand, reading hierarchy and required interactions, then build the smallest coherent system that expresses them. The navigation can follow the information architecture. The project story can follow the evidence. The spacing and type scales can follow the actual content.

Contrast that with a poorly matched theme where the header is almost right, the card markup is almost right and the mobile breakpoint is almost right. Each exception is manageable in isolation. Together they can produce a second design system layered over the first: selectors overriding selectors, hidden template elements, duplicated spacing rules and JavaScript repairing markup that should have been suitable in the first place.

This is a conditional advantage, not a criticism of customising existing themes. If an existing system already expresses the required design, using it may be the more disciplined engineering choice. The avoidable cost arises when the brief and the foundation disagree at almost every level.

An original design system also needs constraints. Define the heading scale, content widths, spacing rhythm, surface themes, button states and motion vocabulary once. Add exceptions because the content calls for them, not because every page editor has discovered another font-size field. A highly bespoke website can have fewer styling decisions available to editors and still feel more carefully designed.

The performance opportunity—and its limits

A small starting layer makes it easier to account for what the theme contributes. You can inspect its hooks, understand the template path and explain why each stylesheet or script is being sent. With fewer inherited features, there may be less work to remove before building the features the project actually needs.

The important word is may. BlankSlate does not guarantee a small DOM, efficient SQL, good font loading or a responsive main thread. A custom template can issue a query for every item in a loop. A bespoke menu can install an expensive scroll handler. A beautiful SVG can become an enormous document. A minimal theme can still deliver a slow application.

Separate the budgets you are investigating:

  • Server work: PHP execution, database queries, object-cache behaviour and remote services before the response is ready.
  • Delivery: the resources needed to render the page, their dependencies, caching policy and discovery order.
  • Rendering: layout, painting, image decoding, font substitution and the cost of the document itself.
  • Interaction: event handlers, long tasks and the work triggered by an actual click, scroll or form submission.

A theme change can influence several of these budgets, but it will not repair an unrelated slow API call simply by being lightweight. Similarly, removing an unused JavaScript dependency can save transfer and execution work without materially changing server response time. Be precise about the mechanism you are improving.

For a defensible comparison, build equivalent pages with equivalent content and functionality. Hold hosting, PHP, plugins, cache state, device and network conditions constant. Measure repeated cold and warm runs, then inspect the request waterfall and main-thread trace. Include authenticated workflows where relevant. Report the conditions and distribution, not a favourable screenshot from an empty demo.

Our essays on content-aware JavaScript and CSS delivery and logged-in WordPress performance go deeper into those separate responsibilities. No comparative benchmark has been invented for this article.

Audit the parent: minimal does not mean behaviour-free

Read the actual version you are deploying. In our inspected BlankSlate 2026 source, blankslate_enqueue() enqueues a stylesheet using get_stylesheet_uri() and also enqueues WordPress’s jquery handle. In a child-theme context, that stylesheet function resolves to the child’s stylesheet. It does not mean the parent’s reset has automatically been loaded as a second file.

The same source includes a footer script that adds device/browser classes; theme support declarations, including block-related features and WooCommerce support; a filter disabling the big-image threshold; and a filter removing the medium_large, 1536x1536 and 2048x2048 intermediate sizes. These are concrete defaults to review, not proof of a problem on every site. The versioned source is available through the WordPress theme repository.

Image-size changes are especially easy to overlook. If you restore a size later, existing uploads do not spontaneously acquire the missing derivative. Regeneration may be necessary. If you retain the parent’s policy, register and generate the responsive sizes your own layouts actually need, then verify the resulting srcset, sizes and browser-selected resource.

Likewise, declaring WooCommerce support does not complete the design, payment-flow testing or accessibility of a shop. An accessibility-related theme feature does not certify the final site after customisation. These distinctions matter because marketing labels describe a starting product, while visitors experience your finished implementation.

Choose a child theme or a standalone implementation deliberately

A child theme is appropriate when you want a maintained parent dependency and a clearly separated home for your customisations. Keep the parent directory unmodified. A standalone theme is appropriate when you intend to own the foundation itself and maintain it as your product. If you derive it from existing code, preserve the applicable licence and attribution information.

Do not treat copying every parent file into a child as a maintenance strategy. Each copied template becomes your responsibility: a future fix in the parent’s version of that file will not replace your override. Conversely, any template you do not override can still fall back to the parent. That includes less frequently visited routes such as search, archives, attachments or password-protected content.

Document the boundary. Which templates are inherited? Which callbacks have been removed? Which theme supports remain intentional? Which component owns the reset? That inventory is more useful during an upgrade than a vague promise that the site “uses a child theme”. See WordPress’s child-theme guidance and template hierarchy.

Understand the lifecycle before removing a callback

WordPress loads a child theme’s functions.php before the parent’s. Both execute; the child file is not a replacement for the parent file. Calling remove_action() immediately at the top of the child file can therefore be too early: the parent may not yet have registered the callback you are trying to remove. The theme-functions documentation explains this loading order.

The following is a scoped example for the inspected BlankSlate release. It removes the parent’s asset callback after the theme files have loaded, then supplies one deliberate stylesheet and one dependency-free script. It assumes those files exist in the child theme and WordPress 6.3 or later for the script-strategy argument. It is illustrative code, not an instruction to replace a working site’s enqueue system wholesale.

add_action('after_setup_theme', function () {
    remove_action('wp_enqueue_scripts', 'blankslate_enqueue');
}, 20);

add_action('wp_enqueue_scripts', function () {
    $directory = get_stylesheet_directory();
    $uri       = get_stylesheet_directory_uri();

    wp_enqueue_style(
        'acme-site',
        $uri . '/assets/site.css',
        [],
        (string) filemtime($directory . '/assets/site.css')
    );

    wp_enqueue_script(
        'acme-site',
        $uri . '/assets/site.js',
        [],
        (string) filemtime($directory . '/assets/site.js'),
        ['strategy' => 'defer', 'in_footer' => true]
    );
}, 20);

This removes one source of a jQuery enqueue. It does not deregister jQuery from WordPress. A form or another plugin can still request it legitimately through its dependency declarations. That is a much narrower change than globally removing a shared library and hoping that nothing needs it.

Provide your own reset if you are no longer loading the parent stylesheet. Declare real script dependencies in the array; an empty array is correct only when the script has none. WordPress evaluates loading strategies in the context of those dependencies, as described in the enqueue API. For a distributed production release, a build-generated content hash can replace the illustrative filemtime() version.

Make the CSS system smaller than the design

A distinctive interface does not require a unique heading selector for every section. Put shared decisions into tokens, define a readable type scale and give components clear boundaries. Prefer a section changing the values it supplies to its children over a collection of selectors reaching through several ancestors to restyle them.

@layer tokens, base, components;

@layer tokens {
    :root {
        --paper: #f5f3ed;
        --ink: #242620;
        --accent: #ed492b;
        --surface: var(--paper);
        --text: var(--ink);
        --heading-2: clamp(2rem, 4vw, 3.5rem);
        --space-section: clamp(3rem, 7vw, 7rem);
    }
}

@layer base {
    :where(h2) {
        font-size: var(--heading-2);
        line-height: 1.12;
        text-wrap: balance;
    }

    :where(a, button, input, select, textarea):focus-visible {
        outline: 2px solid currentColor;
        outline-offset: 4px;
    }
}

@layer components {
    .section {
        background: var(--surface);
        color: var(--text);
        padding-block: var(--space-section);
    }

    .theme-dark {
        --surface: var(--ink);
        --text: var(--paper);
    }
}

The example demonstrates ownership, not a complete reset or an accessibility audit. Accent colours still need appropriate contrast for their particular use. Test focus indicators against every actual surface, including nested controls and third-party forms.

Cascade layers also have an important integration rule: normal unlayered author CSS takes precedence over normal declarations in named layers. Wrapping your own components in a layer does not automatically give them control over an unlayered plugin stylesheet. Plan the vendor boundary, use a supported plugin integration point, or introduce a small scoped adapter. Do not resolve every conflict with another !important. The ordering is documented in MDN’s layer reference.

Build the editing model as carefully as the frontend

BlankSlate does not supply a finished content-composition system. Decide what the people maintaining the website actually need to edit. For a project story, that might be the outcome, supporting evidence, deliverables, image and external URL. A section theme should usually be a controlled choice, not a text field that invites arbitrary CSS classes.

ACF can provide structured fields and reusable composition. Native blocks can provide editorial flexibility within patterns and constraints. Either can be appropriate, and they can coexist when the ownership rules are clear. The criterion is whether the stored content expresses meaning and whether the interface makes the valid choices easy.

Avoid turning a flexible-content repeater into an ungoverned page builder with dozens of nearly identical layouts. Two layouts with the same structure and a different colour may be one component with a theme choice. Two superficially similar cards with genuinely different data contracts may deserve separate components. Reuse should follow shared meaning, not just matching rectangles.

Keep ACF field definitions reviewable in source control. ACF Local JSON stores supported configuration locally and provides a synchronisation workflow; it is not a backup of all the editorial values entered into those fields. Deploying schema files and migrating content are separate operations. Preserve field keys, test older records and give schema changes an explicit migration path.

Content, presentation and assets meet at an explicit rendering contractEditorial modelCONTENT + STRUCTUREDesign tokensSHARED DECISIONSRender contractVALIDATE / COMPOSEHTML + CSSVISIBLE OUTPUTBehaviourREQUIRED ASSETS
Content and design choices enter a known rendering contract. The output determines both the interface and the assets that are justified on that page.

Let page composition determine asset requirements

A custom theme gives you a useful opportunity: the same composition that decides which components render can help decide which resources load. A page with a comparison slider needs its controller. A page without that component has no reason to download it merely because another page uses one.

Prefer an explicit capability map resolved before the document head is rendered. It can examine the selected template and structured content, then enqueue the union of the required component assets once. A render-only decision discovered after wp_head() is too late to assume an ordinary stylesheet enqueue will appear in the head without additional handling.

A simple, transparent first step is a dedicated page template:

add_action('wp_enqueue_scripts', function () {
    if (!is_page_template('templates/project-explorer.php')) {
        return;
    }

    $directory = get_stylesheet_directory();
    $uri       = get_stylesheet_directory_uri();

    wp_enqueue_style(
        'acme-project-explorer',
        $uri . '/assets/project-explorer.css',
        ['acme-site'],
        (string) filemtime($directory . '/assets/project-explorer.css')
    );

    wp_enqueue_script(
        'acme-project-explorer',
        $uri . '/assets/project-explorer.js',
        ['acme-site'],
        (string) filemtime($directory . '/assets/project-explorer.js'),
        ['strategy' => 'defer', 'in_footer' => true]
    );
}, 30);

This example assumes the preceding base assets, named template and component files exist. The script dependency is appropriate only if the explorer actually uses the base script. If editors can place the explorer in other templates, broaden the capability resolver to inspect that composition; the template check alone is no longer the contract.

The same principle applies to CSS and JavaScript. Keep first-render layout styles available when they are needed; reserve deferred imports for optional behaviour that can wait. A bundler such as Webpack, Vite or another suitable build tool can implement parts of that delivery strategy. BlankSlate does not require a particular bundler, and adding a build step without a concrete benefit creates another thing to maintain.

Be equally careful about subtraction. Removing all block styles because the homepage happens not to use blocks can break a journal, a widget or plugin output elsewhere. Make absence of a resource a property you can demonstrate across the supported routes, not a guess based on one screenshot.

Keep presentation separate from the application

A theme is a reasonable home for templates, visual tokens and presentation-specific behaviour. Business rules, integration policies, durable background jobs and content types that should survive a redesign need a more independent home, commonly a purpose-built site plugin. WordPress’s theme-functions guidance makes the same distinction for functionality that must remain available across theme changes.

For example, changing the visual theme should not unexpectedly unregister the project records your editors rely on. The records may still be in the database, but losing their registration can remove the editing interface and routes until that functionality returns. Portability is about operational continuity as well as retaining the rows.

At the rendering boundary, validate the field type and escape for the output context: plain text, an attribute, a URL or an explicitly permitted HTML fragment. A visually simple theme is still executing PHP over editor-supplied and potentially external data. For state-changing endpoints, permissions, request validation and nonce checks have separate roles; presentation code is not a substitute for authorisation.

Choose one owner for SEO metadata and structured-data policy. On this site, Yoast owns titles and descriptions. Our theme should preserve the WordPress head and footer hooks and avoid introducing a second metadata system. Clean HTML is useful, but an “SEO-friendly” starter does not supply a content strategy or guarantee search visibility.

The cons are mostly responsibilities you now own

More initial production work. The absence of ready-made layouts means someone must design and implement them. For a conventional brief with a modest budget, a suitable established theme may deliver a better result sooner.

A higher engineering floor. You need competence in the WordPress lifecycle, PHP templates, responsive CSS, accessibility and browser behaviour. Copying snippets until a page looks correct is a fragile substitute for understanding the system.

A larger testing obligation. Menus, focus, forms, errors, archives and responsive states become part of your delivery. A starter’s minimalism does not excuse missing states or inconsistent editor previews.

Ongoing ownership. Parent updates, plugin markup changes and new content combinations can expose assumptions. A child theme protects your files from being overwritten; it does not protect your assumptions from becoming wrong.

Potential developer dependence. A well-designed editing interface gives clients useful control. A poorly designed one makes every content change a developer request. BlankSlate supplies neither outcome automatically.

The temptation to reinvent settled problems. Building a custom disclosure widget when native details would do, or recreating a mature form system for the sake of a lower plugin count, can increase both code and risk. Custom code should earn its place just as a third-party dependency should.

Test the finished system and the update path

Exercise more than the hero and a portfolio card. Test empty archives, search with no results, long titles, password-protected posts, pagination, 404s, missing images and the content types the client actually uses. Trace which template WordPress selected when a route behaves differently.

Use real keyboard navigation, zoom and narrow screens. Check the skip link reaches an existing main-content target, focus remains visible, a modal menu returns focus correctly and form validation communicates its errors. Test long translated labels where multilingual support is in scope. Preserve useful content and links when optional JavaScript is unavailable.

Before a parent update, compare the changed source with your dependency inventory. Then run visual and functional checks in staging against inherited templates and retained callbacks. Keep the previous release and a recovery path. Automatically accepting every parent change without inspection and refusing every update indefinitely are both weak maintenance strategies.

Record the assets expected on representative routes. A future edit that quietly loads a booking library on every page should be visible in review. Likewise, test that a field-schema change does not blank older content and that your SEO output still contains one intended title, description and canonical URL.

Why it fits Enjin—and when we would choose differently

Enjin’s own website uses a BlankSlate child theme. The design tokens, structured ACF sections, project presentation, journal schematics and native interactions are our implementation. The parent theme’s default enqueue and browser-class footer callback are intentionally removed; our own assets have defined owners, and journal, case-study and enquiry resources are loaded through their relevant contexts.

That arrangement gives us room to build a visual identity around the content: drafting instruments, fine registration marks, controlled motion and an editorial format that supports technical depth. The Enjin case study shows the result and the reasoning behind it. Those details are evidence of the implementation, not features supplied by installing BlankSlate.

We would choose differently if another foundation served the editing needs, budget, maintenance team or delivery constraints better. A well-configured block theme or an established theme system can be the right answer. The goal is to reduce unnecessary decisions while keeping the important ones under deliberate control.

BlankSlate is most useful when the freedom it provides is matched by the engineering discipline to use it. Its benefit is not simply how little it brings. It is how clearly you can explain everything you choose to add.

Code examples illustrate the architecture and identify application-specific interfaces. Adapt them to your environment and test the failure paths before deployment. Sources are linked alongside the relevant discussion.