WordPress can publish without serving every page.
Keeping WordPress and ACF as the editorial authority while building a dependency-aware, versioned system for public delivery.
WordPress can remain the place where a website is edited without being the application that assembles every public response.
Editors can keep ACF fields, familiar publishing controls and structured relationships while selected public pages are built into versioned HTML and assets. A separate delivery layer serves those artefacts. Personalised or transactional operations can continue through appropriately authenticated application endpoints.
The useful engineering question is what happens between “Update” in WordPress and a consistent public release. Extracting some JSON is straightforward. Knowing what to rebuild, how to preview it and how to remove something urgently is where the architecture earns its complexity.
Separate editorial authority from delivery
Define which system owns content and which system owns the currently published representation. WordPress can own the editorial records; a release manifest can identify the public artefacts currently selected for delivery. Avoid allowing both systems to independently edit the same content.
WordPress’s REST API provides a structured interface for external applications, but it is only one transport choice. A build worker might use a tightly scoped export endpoint or a controlled command-line task. Returning arbitrary raw post metadata is not a content contract and can expose fields that were never intended to be public.
Model the export deliberately: published fields, relationships, resolved URLs, required assets and a content version. Keep presentation choices that editors need in ACF. Keep deployment credentials and implementation secrets outside editable content.
A content change can affect more than its own URL
Changing a project can affect its detail page, the homepage selection, the Work listing and a related-services panel. A shared contact detail can affect every page. Rebuilding only the edited record is incomplete; rebuilding the whole site on every edit may be unnecessarily expensive.
Record dependencies while resolving the content that a page will render. An edge means “this output depends on that input”. Maintain a reverse index so a change can find the outputs that depend on it, including outputs reached through shared intermediate components.
This pure PHP function walks a small reverse-dependency graph. Keys and values are application-owned identifiers such as project:42, component:selected-work and page:home. It follows transitive relationships and tolerates cycles.
function enjin_affected_pages(string $changed, array $reverse): array {
$queue = [$changed];
$seen = [];
$pages = [];
for ($i = 0; $i < count($queue); $i++) {
$node = $queue[$i];
if (isset($seen[$node])) {
continue;
}
$seen[$node] = true;
if (str_starts_with($node, 'page:')) {
$pages[] = $node;
}
foreach ($reverse[$node] ?? [] as $dependent) {
$queue[] = $dependent;
}
}
sort($pages, SORT_STRING);
return $pages;
}In production, validate graph identifiers, bound traversal work and provide a conservative broader rebuild if the dependency record is incomplete. A graph is useful only if its edges describe the current composition.
Query dependencies are different from record dependencies
A page showing “the three latest projects” depends on a query, not just the three projects currently displayed. Publishing a fourth project can change the result even though that project had no existing edge to the page.
Represent collection queries as dependency nodes too. Re-evaluate affected queries when membership, ordering, publication status or taxonomy assignments change. Consider both the old and new state: removing a project from a category must invalidate the category page it used to belong to.
Navigation menus, global options, translations and template releases also participate in the graph. A CSS or rendering change can affect outputs even when no editorial record changed. Include the renderer and asset-manifest versions in build identity.
Build a coherent generation
A release should not accidentally combine a homepage built before an edit with a detail page built after an incompatible edit. Choose a content snapshot or an explicit version set for the build. Reading paginated REST responses over time does not automatically provide a transactionally consistent export.
One approach is to assemble immutable build inputs, then produce content-addressed artefacts and a manifest referencing them. Validate internal links, required assets, redirects and public-data boundaries before making that manifest active. Failed builds leave the established release selected.
For an incremental build, reuse unchanged artefacts only when their dependency versions remain valid. An incremental release is still a complete description of what is public, not just a bag of recently changed files.
Switch releases without pretending the network is atomic
A single origin can change a release pointer atomically while distributed caches continue serving older responses. Treat release selection and cache propagation as separate concerns. Use immutable asset URLs and keep old assets available for clients holding old HTML.
If pages fetch JSON after loading, give the HTML a release identity and resolve compatible data for that identity. Otherwise an old page can request a new data shape that its JavaScript does not understand. Set a deliberate retention window and a fallback when an old generation is no longer supported.
Cache directives describe how responses may be stored and reused; they do not establish an application-wide release transaction. The HTTP caching specification is the underlying reference. Verify the actual behaviour of the delivery platform and its purge mechanisms.
Preview and withdrawal are first-class publishing operations
An editor needs to review unpublished content in the real layout. Provide an authenticated preview that selects draft inputs without writing them into the public release. Keep preview artefacts access-controlled and outside public cache keys. A hard-to-guess URL alone is not an authorisation system.
Removing content can be more urgent than publishing it. Define what an unpublish or deletion does to the active manifest, redirects, cache entries, feeds, sitemaps and derived listings. Record withdrawal work durably and monitor completion rather than assuming that a successful save hook means every copy disappeared.
Do not put private documents in a public static bucket and rely on a future purge to protect them. Content that requires immediate access revocation belongs behind a delivery boundary capable of enforcing that policy.
Keep transactional operations in the application
A public profile page can be an artefact. Booking its last appointment still requires an authoritative state transition. A generated form can describe an operation; it cannot safely embed a long-lived user-specific nonce and assume that every later visitor shares the same identity or session.
Resolve authentication and request-specific tokens through an appropriate live flow. Keep validation, authorisation, rate limits and concurrency controls at the endpoint that performs the operation. Our concurrency essay explains why a cached display of availability cannot be the final booking decision.
Choose this architecture for a reason you can measure
This model can suit public content with heavy read traffic, controlled publishing frequency and a need to separate delivery from the editorial application. It can be an awkward fit for pervasive personalisation, rapid permission changes or plugin features tightly coupled to server-rendered sessions.
Compare the complete system: publishing latency, preview quality, release consistency, failure recovery, infrastructure cost and developer effort. A conventional WordPress theme with disciplined resource loading and suitable caching may meet the requirements with much less operational machinery.
The interesting capability is optionality. WordPress can be the editorial authority inside a broader delivery architecture, provided the publication contract is engineered as carefully as the pages themselves.
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.