BuilderJS

An embeddable builder for LMS and course platforms — own the editor, not rent it

If you are building your own LMS, course platform, or membership product — not running courses on top of WordPress — you eventually hit the same fork in the road: how do creators design their sales pages, lay out lessons, and write drip and reminder emails? Stitching in Elementor or Divi means renting someone else's plugin, living inside their WordPress assumptions, and explaining their UI to your users as if it were yours. BuilderJS offers the other path: a framework-agnostic, vanilla-JavaScript drag-and-drop editor you license once, self-host, and embed directly inside your platform. One canvas builds two things from a single JSON model — web/landing HTML for course sales pages and lesson layouts, and Outlook-safe HTML for drip and reminder email templates. You extend it for your domain (quiz blocks, video embeds, progress widgets) by registering custom Elements through the public Builder.registerElement API, without forking the source. The design your creators make is plain JSON you store next to the course or module record in your own database. Honest scope up front: this is for teams shipping their own product and willing to self-host. If your platform is happy on the Elementor/Divi/WordPress path, that path is fine — BuilderJS is for when you want to own the editor instead. It is the editor only: it builds the markup; your platform still owns sending the emails, hosting the pages, and the LMS itself.

Mount it

// LMS: mount one editor that builds course pages AND reminder emails,
  // extended with your own course block. builder.js attaches window.Builder
  // (no npm package). Render the three containers, mount client-side.
  
  // 1) Register a course-specific ELEMENT ONCE, before mounting — no fork.
  //    registerElement adds Elements only; the element's getControls()
  //    builds its property panel by subclassing the core Control classes.
  window.Builder.registerElement('QuizBlockElement', QuizBlockElement);
  // (Custom Widgets -> builder.widgetsBox.addWidget() in the load() callback;
  //  custom Controls -> subclass + instantiate inside getControls().
  //  There is no registerWidget/registerControl.)
  
  // 2) Mount the editor in your LMS screen.
  const builder = new window.Builder({
    mainContainer: '#bjs-canvas',       // REQUIRED — CSS selector string
    widgetsContainer: '#bjs-widgets',   // optional
    settingsContainer: '#bjs-settings', // optional
  });
  
  // 3) Seed from the lesson/course record's saved JSON (4 positional args).
  builder.load(lesson.themeJson, themeTemplatesJson, themeConfigData, mediaUrl);
  
  // 4) Persist the design next to the course/module record in YOUR database.
  //    Same getData() JSON whether it renders as a page or an email later.
  const json = builder.getData();
  await fetch('/api/lessons/' + lesson.id + '/design', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(json),
  });
  // No destroy() exists; your framework discards the DOM on unmount.

One canvas, two outputs: course pages and reminder emails

Course platforms need two kinds of design surface, and most teams end up bolting on two separate tools. BuilderJS collapses them into one editor. The same drag-and-drop canvas produces modern-CSS HTML for the web side — course sales/landing pages, module overview pages, lesson layouts — and Outlook-safe HTML for the email side: welcome sequences, drip lessons, and the 'you haven't logged in for 3 days' reminder. The email path runs through the EmailExportPipeline, which converts flexbox/grid layouts to nested tables, rasterizes SVG to PNG, adds MSO conditional comments and ghost tables for Outlook, applies @media (max-width:600px) mobile stacking, makes images fluid, and inlines the CSS. The package ships 30+ templates and 200+ samples that were Litmus-tested across 22 email clients, so your creators' lesson reminders actually render in real inboxes. The honest boundary: BuilderJS builds the markup for both. It does not send the drip email and it does not host the course page — your platform's delivery and hosting layer does that, the same as it already does.

Extend it for your domain with registerElement — no fork

A generic page builder doesn't know what a quiz, a video lesson, or a course-progress bar is. BuilderJS lets you teach it without forking the library. Use the public Builder.registerElement API to add custom element types that sit in the palette alongside the built-in 42 element types — a quiz block, an embedded video player, a 'mark lesson complete' button, a curriculum/module list. Each custom element brings its own property panel by overriding getControls() and subclassing the same control system the core uses (59 property controls), so creators configure your quiz block the way they configure a heading. Because these element classes live in your own codebase against a stable public API rather than as patches inside the source, they survive updates instead of breaking on every version. That is the difference between owning an editor you can shape to a course platform and renting a plugin you have to bend your product around. (To be precise about the extension surface: custom Elements register through this static registerElement API; custom Widgets are added in your load() callback via builder.widgetsBox.addWidget(); and custom Controls are subclassed inline inside an element's getControls() — there is no separate registerControl or registerWidget call.)

JSON-first: store the design next to the course record

Every design in BuilderJS — page or email — is a plain JSON tree. You read it with getData() and restore it losslessly with load(), so save → reload → keep editing produces no drift. For an LMS that data model is the whole point: a lesson's layout JSON lives in the same row (or the same document) as the lesson; a course's sales-page JSON sits next to the course; a drip template's JSON belongs to the sequence step. Your backend owns persistence end to end — MySQL, Postgres, SQLite, a file, or S3 — there is no proprietary store you get evicted from and no usage meter counting designs. Because the design is text, you can version templates in git, diff a curriculum-page change in code review, and write a migration that rewrites a property across thousands of saved lessons in CI. The rendered HTML is a derivative you regenerate on demand; the JSON is the canonical artifact you keep.

Multi-tenant by construction, owned by a one-time license

A course platform serves many creators, and BuilderJS is multi-tenant capable through closure-captured configuration — you can run an isolated editor instance per creator or per workspace from the same self-hosted bundle. The honest caveat, stated plainly: BuilderJS supplies the embeddable editor; your platform still owns tenant isolation, seats, and billing. On cost, this is the wedge against renting an editor. BuilderJS is sold under a one-time CodeCanyon license (item 27146783), Regular or Extended, paid once — you get the full source, self-host builder.js and builder.css from your own origin, and embed it in your platform with no SaaS account, no monthly fee, no per-seat charge, no usage metering, and no phone-home. If your creators are charged end users, Extended is the tier to choose. The honest boundary on ownership: the code is yours to keep and run perpetually, but author support and version updates are time-boxed (roughly 6–12 months under CodeCanyon's standard window), after which you self-maintain the source you own. We never call support or updates 'lifetime.'

When BuilderJS fits — and when it honestly doesn't

Be honest with yourself about which platform you are. BuilderJS fits when you are building your own LMS, course, or membership product — non-WordPress or a custom stack — and you want one ownable canvas for sales pages, lesson layouts, and reminder emails, embedded so it looks like your product and extended with your own quiz/video blocks. It mounts unchanged in React, Vue, Svelte, Angular, Next.js, Laravel, or plain HTML, so it survives your stack choices. It does not fit if your platform lives on WordPress and your creators are happy designing in Elementor or Divi — that ecosystem is mature and there is no reason to rebuild it. BuilderJS is also the editor, not the platform: it does not run the LMS, enrol students, gate content, send the email, or host the page. It builds the page and email markup; you bring (or already have) the delivery, hosting, auth, and course logic. If that division of labor matches how you think about your product, the one-time-license, own-the-editor model is the reason to choose it. You can try the getData()/load() round-trip on the live demo at builder.emotsy.com before you commit, then read /one-time-license/ for the ownership model and /embed/react/ for the framework-specific mount guide.

Frequently asked questions

Explore