Gorilla Engine SDK

@moonbase.sh/gorilla-engine adds Moonbase license activation to Gorilla Engine plugins: the activation screens in a panel over your plugin's interface, which lock the plugin, and its MIDI and audio, until it is licensed.

The package is published on npm as @moonbase.sh/gorilla-engine under the MIT license. It is a React component for Gorilla Engine React that runs in your plugin's own JavaScript and draws with Gorilla Engine's native controls. It is built on the Node.js SDK, and has the same screens as the JUCE module.

It supports:

  • Browser-based activations, and offline activations by machine file
  • Trials, with a days-remaining screen and an included-features list
  • Startup validation, online re-validation and a configurable grace period
  • Server-side deactivation, so users can free up an activation seat
  • Add-ons, to try, buy and activate from inside the plugin
  • Licenses that cover some versions, with an upgrade screen
  • In-app update notifications with release notes and an installer download
  • MIDI and audio switched off while the plugin has no license
  • One license shared by every instance of the plugin, in any number of hosts

Here is the first thing a customer sees when they open an unlicensed plugin:

The activation overlay over a Gorilla Engine synth plugin: an "Activate Built-in UI Sample" heading, an "Activate online" button and a "No internet? Activate offline" link, with the plugin's knobs and keyboard dimmed behind it

Requirements

  • A Gorilla Engine plugin with a Gorilla Engine React interface, tested with Gorilla Engine React 1.6 and React 19
  • macOS or Windows

Installation

Add the npm package to your plugin's interface project:

npm install @moonbase.sh/gorilla-engine

Setup

In your project's .ugep file, keep MIDI and audio off until the plugin's JavaScript has checked the license:

{
  "pluginConfig": {
    "audioEnabledOnStartup": false,
    "midiEnabledOnStartup": false
  }
}

Then create the module once, at the top level of your plugin's script rather than in a component, with your account endpoint, product ID and public key. You will find all three in the Implementation guide for your product in the Moonbase app. Render MoonbaseActivation last, so it lies over the rest of your interface:

import { createMoonbase, MoonbaseActivation } from '@moonbase.sh/gorilla-engine'

const moonbase = createMoonbase({
  endpoint: 'https://your-account.moonbase.sh',
  productId: 'your-product',
  publicKey: MOONBASE_PUBLIC_KEY,
  appVersion: '1.2.0',
  ui: {
    manufacturerName: 'Helio Audio',
    logo: 'images/logo.png',
    fonts: {
      regular: 'fonts/Inter-Regular.otf',
      medium: 'fonts/Inter-Medium.otf',
      semibold: 'fonts/Inter-SemiBold.otf',
    },
  },
})
moonbase.start()

function App() {
  return (
    <geLabel width={920} height={590}>
      <PluginUI />
      <MoonbaseActivation moonbase={moonbase} width={920} height={590} />
    </geLabel>
  )
}

Set appVersion to your plugin's version, and keep it in step with pluginConfig.version in the .ugep, since Gorilla Engine has no version of its own for the module to read. It is the version reported to Moonbase, and compared with your releases.

Before you build, check the project with the module's doctor command. It reads your .ugep and assets, and shows any fix as a diff: the startup settings, that appVersion matches the project's version, and that the fonts and logo are among the plugin's assets.

npx @moonbase.sh/gorilla-engine doctor

While the plugin has no license, the overlay comes up by itself, covers the interface, takes every click, and can't be closed. Once the plugin is licensed it gets a close button. To bring it back from a button, optionally on a particular screen (license, update, offline or addons):

<geButton text="Manage license" onClick={() => moonbase.present('license')} />

Branding

Brand the overlay through the ui options:

OptionDefault
productNamethe plugin's nameShown throughout
manufacturerNamenoneUnder the product name, and as the account the customer signs in to
accent#186cdcThe one brand colour: buttons, progress, step numbers
logoa sun mark in the accentThe product mark in the header, as an image among the plugin's assets
fontsthe system fontregular, medium, semibold and mono, as .otf files among the plugin's assets
trialFeaturesnoneThe trial screen's included and excluded lines
trialLengthDays14Shown when the license doesn't say
showAddOnsoffAn Add-ons row in the license details, to try, buy and activate the product's add-ons
stringsbuilt-in copyOverride any heading or body, including the copy for each reason the plugin locked
showMoonbaseBadgeonThe Moonbase footer
autoPresentOnLockonPresent the overlay when the plugin opens unlicensed, and whenever it loses its license
autoPresentUpdateonPresent the update screen when the plugin opens with a newer release it wasn't told to skip
reduceMotionoffSkip the fades and transitions. The license, and MIDI and audio with it, change at once either way

The screens, all driven by the license state:

  • Welcome. Activate online through the browser, or activate offline. Once the plugin has lost its license, it says why.
  • Waiting for activation. The browser is open, with a link to copy if it didn't, and Cancel.
  • Success. A confirmation with a mini license card.
  • Offline activation. Save the machine file, then drop or pick the license file the customer got back.
  • Trial and Trial expired. Days left, the included and excluded features, and an unlock action.
  • Upgrade needed. The license doesn't cover this version of the plugin. It says what the license covers, and offers the upgrade.
  • License details. Who the license is issued to, the plan and expiry, the license ID with a Copy button, a seat counter, and a deactivate action that releases the seat server-side.
  • Add-ons. The product's add-ons, each with a Try free, Buy or Activate action, when showAddOns is on.
  • Update available. The release notes, a download of the installer for this platform into the Downloads folder, and Skip this version.

MIDI and audio

The module turns your plugin's MIDI and audio off when it starts, on once the stored license checks out, with a license or a trial, and off again whenever the license is lost. The .ugep settings from Setup cover the moment before your script runs. Pass lockAudioAndMidi: false to handle it yourself.

To gate parts of your interface, read the license state with the useMoonbaseState hook, which re-renders your component whenever it changes:

import { useMoonbaseState } from '@moonbase.sh/gorilla-engine'

function PluginUI() {
  const state = useMoonbaseState(moonbase)
  return (
    <geLabel width={920} height={590}>
      <MainPanel />
      {state.activeSubProducts.includes('drum-kit') && <DrumKitPanel />}
    </geLabel>
  )
}

state.licensed says whether there is a valid license right now, state.activeSubProducts lists the add-ons to unlock, and state.status is one of loading, unlicensed, activating, licensed, trial, trialExpired or notCovered. Outside a component, check moonbase.isLicensed() and moonbase.hasSubProduct(id). The activation controller describes each status, and every one of its methods is on moonbase too.

Instances

Every instance of your plugin, in any number of hosts, shares one license. Activating in one unlocks the others within a few seconds, and deactivating locks them. By default the license is kept in your manufacturer folder:

  • macOS: ~/Library/Application Support/<manufacturer>/<plugin>/license.mb
  • Windows: %APPDATA%\<manufacturer>\<plugin>\license.mb

The folder is named after the plugin as it was built, so renaming the plugin would lose your customers' licenses. Set storage to name the folder for good, and previousLicenseFiles to bring a license over from where an earlier version kept it:

const moonbase = createMoonbase({
  // ...
  storage: { manufacturer: 'Helio Audio', plugin: 'Solstice' },
  previousLicenseFiles: [path.join(os.homedir(), 'Library/Application Support/Helio Audio/Solstice 1/license.mb')],
})

A previous license is copied over only when the plugin has none of its own, and is checked like any stored license. Pass licenseFile to keep the license somewhere else entirely.

Licenses that cover some versions

A license bought outright can cover only some versions of your plugin, such as 12 months of updates or every version up to 2.x. When the license doesn't cover appVersion, the plugin locks on the Upgrade needed screen. The license stays stored, since it still covers the versions it did, and the screen offers the customer the upgrade.

Validation and offline use

The stored license is validated when the plugin opens, and online at most every 5 minutes (checkInterval). Without a network, a license activated online keeps working for 7 days after its last successful online check (gracePeriod), and then locks until it can be checked again. Both options take milliseconds.

Offline activation is built into the Welcome and Offline activation screens, and uses Gorilla Engine's file dialogs for the machine file and the license file, so there is no code to write for it. See Offline activations for the customer-facing side of the flow.

Device identity

The module identifies the device with the cross-SDK Moonbase device fingerprint of the Node.js SDK. A license activated through any Moonbase SDK, such as a JUCE build of the same product, validates in your Gorilla Engine plugin, and the other way round.

Support reports

moonbase.diagnostics() returns a report to paste into a support request: the module and SDK versions, where the license is kept, what the host can do, and whether MIDI and audio are on. It contains no license, names, emails or device identity. Pass onError to hear about anything the overlay couldn't do, such as open the browser.

Sample plugins

The Gorilla Engine sample repository has two synth plugins, made with create-gorilla-engine-plugin and wired to the public Moonbase demo account, so they activate out of the box. One uses this SDK's built-in overlay. The other draws its own activation panel on the activation controller of the Node.js SDK.

Gorilla Engine plugins licensed through Moonbase, with the built-in activation overlay or a panel of your own.

Was this page helpful?