Running BuilderJS self-hosted, on-prem, and air-gapped
If your deployment sits behind a firewall, inside a private VPC, on a customer's on-prem hardware, or on a network with no outbound internet at all, most embeddable builders are a non-starter: they phone home to a vendor cloud SDK for licensing, asset hosting, or telemetry. BuilderJS is built the opposite way. It is a vanilla-JavaScript, framework-agnostic drag-and-drop editor for HTML email and web pages that you buy once (CodeCanyon, Regular $52 / Extended $99), self-host as source, and run with no runtime dependency on any vendor service. There is no account check, no usage meter, and no callback to a license server. This guide explains exactly how to run it fully offline — including the one knob that matters, loadAssets:false, which opts out of the two CDN peer-dependencies the engine would otherwise auto-inject so you can serve them from your own origin instead.
Mount it
// Air-gapped mount: opt out of the CDN peer-deps and self-host them.
// builder.js + builder.css are served from YOUR origin (no npm import);
// loading builder.js attaches the global window.Builder.
//
// In your HTML <head>, self-host the two peer-deps instead of the CDN:
// <link rel="stylesheet" href="/vendor/material-symbols-rounded.css">
// (href must keep the "Material+Symbols+Rounded" family token)
// <script src="/vendor/bootstrap.bundle.min.js"></script>
// (must define window.bootstrap with Bootstrap's Modal)
// <link rel="stylesheet" href="/builderjs/builder.css">
// <script src="/builderjs/builder.js"></script>
const builder = new window.Builder({
mainContainer: '#bjs-canvas', // REQUIRED — CSS selector string
widgetsContainer: '#bjs-widgets', // optional — CSS selector string
settingsContainer: '#bjs-settings', // optional — CSS selector string
loadAssets: false, // skip CDN auto-injection (air-gap)
});
// load(themeJson, themeTemplatesJson, themeConfigData, mediaUrl) — 4 args.
// mediaUrl points at YOUR internal asset host, not a public CDN.
builder.load(themeJson, themeTemplatesJson, themeConfigData, '/internal-media/');
// Persist offline: POST getData() JSON to your own backend route.
const json = builder.getData();
// There is NO destroy(); React discards the DOM on unmount.
What "air-gapped" actually requires from a builder
An air-gapped or strict on-prem environment has no outbound internet, so anything the editor fetches at runtime from a third-party origin will simply fail. The audit you have to pass is: does the editor make any network call you don't control? BuilderJS itself ships as two static files you serve from your own origin — builder.js and builder.css — and stores nothing remotely; getData() hands the design JSON back to your code and your backend owns persistence. There is no licensing handshake, no telemetry beacon, and no hosted asset store. The single thing to be aware of is that the engine has two runtime peer-dependencies it normally pulls from a CDN. That auto-injection is the only outbound touch, and it is exactly what loadAssets:false turns off.
loadAssets:false — opt out of the CDN peer-deps
By default the constructor runs in 'auto' mode: at construction time it checks whether the host page already loaded its two peer-deps and, if missing, injects them. Those peers are Material Symbols Rounded (the icon font used across the chrome, referenced from Google Fonts) and Bootstrap's JS bundle (used for the Change-Theme, Asset-Upload, and Alert modals, fetched from jsDelivr). On a connected page that is a convenience. In an air-gapped deployment it is a broken request. Pass loadAssets:false and the engine skips both injections entirely — this behavior is explicit in the source, commented for 'Air-gap / China deployments.' You then self-host those two assets and add your own <link>/<script> tags pointing at your origin. Nothing else in the editor reaches the network.
Self-host the two peer assets
With loadAssets:false set, you become responsible for the icon font and Bootstrap JS. Download both once on a connected machine, vendor them into your project, and serve them from the same origin as builder.js / builder.css. The detection BuilderJS uses is deliberately loose, so self-hosted variants are recognized fine: it looks for any stylesheet whose href contains 'Material+Symbols+Rounded', and for window.bootstrap.Modal being a function. As long as your self-hosted font stylesheet keeps that family token in its URL and your Bootstrap bundle defines window.bootstrap, the chrome renders correctly and the Change-Theme / upload / alert modals work — with no request ever leaving your network.
What you own, and what stays your job
Because BuilderJS is the editor you embed — not a platform — self-hosting is the default, not an enterprise upsell. You own the full source under a one-time license, run it on your own server, and the design data is plain JSON in your own database, file, or object store. The boundary is the same as anywhere else: BuilderJS builds the markup (page HTML, or Outlook-safe email HTML via its export pipeline) and round-trips designs as JSON through getData() / load(); it does not send email, host pages, or publish anything. In an air-gapped setup that division is a feature — the editor produces artifacts your own internal sending or hosting layer consumes, and no part of the workflow assumes outbound connectivity.
Frequently asked questions
-
Does BuilderJS phone home, check a license, or send telemetry?
No. There is no license-server handshake, no usage meter, and no telemetry beacon. You buy the source once (Regular $52 / Extended $99) and run it on your own origin. The only outbound touch is the default CDN auto-injection of two peer-dependencies, which loadAssets:false disables entirely.
-
What exactly does loadAssets:false turn off?
It skips the construction-time auto-injection of the engine's two runtime peer-deps: the Material Symbols Rounded icon font (normally from Google Fonts) and the Bootstrap JS bundle used for modals (normally from jsDelivr). With it set, the engine makes no peer-dep network request — you self-host those two assets and add your own link/script tags. This path is explicitly source-commented for air-gap and China deployments.
-
Will the editor look or behave wrong if I block the CDN?
Only if you block the CDN without self-hosting the peers. Without the icon font, glyphs render as raw ligature text (like 'edit' or 'code'); without Bootstrap JS, the Change-Theme / Asset-Upload / Alert modals throw. Set loadAssets:false and serve both assets from your own origin and the chrome renders correctly with no outbound calls.
-
Where does my design data go in an offline deployment?
Wherever you put it. BuilderJS is JSON-first: getData() returns the design as JSON and your backend persists it — MySQL, Postgres, SQLite, a file, or an internal object store. The package ships reference PHP backends you copy and own (portable to Node, Go, or Python). Nothing is stored on a vendor server, so there is no remote dependency to fail offline.
-
Is self-hosted / on-prem an extra-cost tier?
No. Self-hosting is the default model, not a paid upgrade. The one-time CodeCanyon license (item 27146783, Regular $52 / Extended $99) ships the full source for you to run on your own infrastructure. Air-gapped and on-prem use are covered by the same license — there is no separate enterprise deployment SKU.