Front-End Loading Pipeline
render_header_scripts() (see Rendering Functions) injects two small system scripts into every page, front-boot.js and css-async.js. Neither is optional, and neither is dead weight — here's what each actually does, and why they're separate files rather than inline <script> tags.
front-boot.js — getting PHP data to front-end JS without inline scripts
The CMS's CSP has no 'unsafe-inline' in script-src (see Security), which means a plain <script>window.CMS_LANG = {...};</script> written directly into the page would simply be blocked by the browser. Instead:
render_header_scripts()emits the data as inert<script type="application/json" id="cms-base-json">/id="cms-lang-json">tags — these aren't executable, so the CSP doesn't need to allow them specially.front-boot.js, loaded as a normal external file (already covered byscript-src 'self'), reads those JSON islands by ID and assigns them towindow.CMS_BASE_URL/window.CMS_LANG/window.appSettings.- It also handles a generic version for plugins: any
<script type="application/json" data-window-var="XX_LANG">on the page gets assigned towindow.XX_LANGautomatically — a plugin's own widget script can read its data the same way core does, without writing its own inline script either.
It's loaded without defer, deliberately — main.js and theme/{active}/script.js are both deferred, so front-boot.js has to run first, synchronously, to guarantee the globals exist before either of them executes.
Why plugins re-include it mid-page
Comments, Booking, Form Builder, Newsletter, and Cookie Consent all output their widget markup directly into the page body (via the output-buffering pattern in Front-End Integration), and each one re-includes front-boot.js right before its own widget script. This isn't a mistake — a widget injected into the body can't rely on the <head> copy having already run by the time the browser reaches it, so each plugin guarantees its own globals are set immediately before its script needs them. A guard (window.__frontBootWired) makes every inclusion after the first a near-no-op for the event-listener setup at the bottom of the file, and the browser only ever downloads the file once regardless of how many <script src> tags reference it — repeat inclusions on the same page cost a cached read, not a network request.
Why it isn't inlined and hash-allowlisted like the theme preference snippet
The dark/light + sidebar-state boot snippet in every theme's header.php is inlined and CSP-allowlisted by SHA-256 hash instead of loaded externally — it has to run before first paint and can't tolerate the round-trip. front-boot.js doesn't have that constraint, and inlining it would cost more than it saves: it would need to repeat the same script text every time it's re-included (up to 6× on a page using several plugins), on every single page load, with none of the far-future caching an external file gets. One small cached file, referenced as many times as needed, is the cheaper option here.
css-async.js — letting non-critical CSS load without blocking render
assets/css/synaptikCSS.php (the combined search/gallery/shortcode stylesheet) is linked with media="print" instead of the default all:
<link rel="stylesheet" class="cms-async-css" href=".../synaptikCSS.php" media="print">
A browser still downloads a media="print" stylesheet in the background, but — since print doesn't match the current (screen) context — it never blocks rendering while waiting for it. css-async.js watches for that download to finish and then flips media from print to all, which is the moment the styles actually start applying to the page. Without this script, that CSS would stay downloaded but permanently inert — never applied, since nothing would ever change it back to all. A <noscript><link ... ></noscript> fallback covers visitors with JavaScript disabled, applying the stylesheet normally for them since the async trick doesn't apply either way.
It's only ever included once, from core — no plugin re-includes it — and like front-boot.js, it stays an external cached file rather than an inline one for the same reason: one small file fetched once and reused for a year beats repeating its contents on every page load for a saving that HTTP/2's connection multiplexing has already made close to zero.
