• Document Up to Date
  • Updated On 4.0.1

Plugin Host

The Plugin Host is a special route within Studio that provides an empty canvas for custom authoring apps (Crafter Studio Full Screen Plugin Example) to render.

Apps developed to run on the plugin host are solely responsible for rendering the entire UI of the page and are able to access all of Studio UI components and apis through the window.craftercms global variable on the browser or when using a development stack, through the @craftercms/studio-ui npm package.

The plugin host can be accessed when logged in to Studio at /studio/plugin. For example, in your local environment, http://localhost:8080/studio/plugin. In order to render a plugin, the plugin host requires three to five query string arguments.

Plugin Host Arguments

Name

Default

Description

site

(required)

The id of the project where the plugin is installed

type

(required)

The name of the category directory inside {sandbox}/config/studio/plugins directory

name

(required)

The name of the plugin directory inside {sandbox}/config/studio/plugins/{type} directory

file

index.js

The name of the file you want the PH to load. Can be either an HTML or JavaScript file

id

The plugin id when the app is nested under a plugin id directory

Visiting this page without any arguments would show a message stating the arguments are missing. You must supply the above arguments for it to load and run your plugin.

The plugin host loads a single file which can either be a JavaScript (JS) or an HTML file. This single file is responsible for bootstrapping the application.

  • JS entry file

    • When loading a JS file, the plugin host loads Studio UI runtime scripts followed by your entry file. Your JS file is able to access all of Studio’s runtime through window.craftercms.

    • You can do plain JS or you can have some sort of dev stack with transpilation that outputs the final JS that will be loaded to the browser. For example if you wanted to use JSX or Typescript.

  • HTML entry file

    • When you load a HTML file the page is exactly the HTML file you specified and hence, the CrafterCMS runtime is not available (e.g. you can’t access window.craftercms) unless you add it yourself. If you want to leverage UI apis or components, you should use the @craftercms/studio-ui npm package. It is not recommended to manually copy and print Studio <script src="" /> tags since these change with CrafterCMS version upgrades.

    • When using an HTML entry file, you can load additional scripts, stylesheets, images, etc. using the plugin file loader api in combination with regular the HTML tags. For example, to load a JS file you can simply use the script tag: <script src="/studio/1/plugin/file?siteId={SITE_ID}&type={CATEGORY}&name={NAME}&filename={FILE_NAME}"></script>

If you have an app that requires building (e.g. transpilation), you can keep your sources inside your CrafterCMS project or in a separate repository — up to you. The important piece is that the final build of your plugin is placed into the plugins file directory as detailed here

Using Front-end Development Toolchain

When you develop your application using a toolchain such as webpack (e.g. including CRA) or similarly, you should note that the base url of your application isn’t just / as it would typically be. Consider the following structure for a site called “Skateboard Shop” and a plugin called “bulk-edit”…

skateboard-shop/authoring/static-assets/{pluginIdPath} <== Plugins root directory
  apps/                                                <== Category directory
    bulk-edit/                                         <== Plugin root directory
      static/
        index.js
        css/
          index.css
        index.html

In order to load the index.js file, a build tool might print out static/index.js which would result in a 404. You need to configure your tool’s base url to be /studio/1/plugin/file?siteId=skateboard-shop&type=apps&name=bulk-edit&filename= so that the final url would become /studio/1/plugin/file?siteId=skateboard-shop&type=apps&name=bulk-edit&filename=static/index.js for the file load to succeed.

When using CRA, you can do the above by adding a .env.production and using the PUBLIC_URL configuration to specify the base url.

PUBLIC_URL=/studio/1/plugin/file?siteId=skateboard-shop&type=apps&name=bulk-edit&filename=

We recommend using React and Material UI to develop your apps and widgets since these will provide the most coherent integration and seamless experience for the end user provided that CrafterCMS’ UI is developed in those technologies. This will also allow you to leverage all of Studio UI components, utilities and apis. See examples below for sample apps developed using these technologies.

When you build an app using @craftercms/studio-ui package, don’t be surprised if the build is large. You’re essentially building another Studio. 🙂

Displaying a Plugin Host App in Studio

At times your requirements demand the use of a standalone app but it may come useful for end-users to be able to display the App in a modal dialog without leaving Studio UI.

CrafterCMS exports a special component named PluginHostIFrame which allows displaying an iFrame showing the plugin host with a specified app. This plugin in conjunction with the WidgetDialog, allows displaying a pop up with your plugin host app at a time of your choosing in Studio UI.

import { showWidgetDialog } from '@craftercms/studio-ui/state/actions/dialogs';
import { useDispatch } from 'react-redux';

const dispatch = useDispatch();
dispatch(
  showWidgetDialog({
    title: 'Bulk Edit',
    widget: {
      id: 'craftercms.components.PluginHostIFrame',
      configuration: {
        plugin: { type: 'apps', name: 'bulk-edit', file: 'index.html' }
      }
    }
  })
);

By default, PluginHostIFrame will use the active project but it can also receive a sie argument if you wish to show an iFrame with a PH app from a specific project.

Case Study

Consider a site called “Skateboard Shop”, whose id is skateboard-shop. We create a plugin category called apps (i.e. {yourPluginDirectory}/authoring/static-assets/{pluginId}/apps) and deployed an app to perform bulk content edits at a directory called bulk-edit (i.e. {sandbox}/config/studio/plugins/apps/bulk-edit). At this point, our app is fairly simply, consisting of a single JavaScript file called index.js which does everything we need.

After configuring our plugin files/directories using the JavaScript file from above and installing via the crafter-cli command copy-plugin, we can now view the Bulk Edit plugin at /studio/plugin?site=skateboard-shop&type=apps&name=bulk-edit.

As the app requirements evolved, and the UI became more complex, we might decide to use Create React App, the Angular CLI, etc. to convert our simple plugin to a full application with hash routing. At this point, the entry point will become an index.html which these tools tend to generate. In order to run this application now, we’ll want to load the index.html instead of the index.js.

We can now view the Bulk Edit plugin at /studio/plugin?site=skateboard-shop&type=apps&name=bulk-edit&file=index.html.

Examples

  • CRA example: illustrates a plugin host app using a dev toolchain with dev server.

  • Vanilla example: illustrates the simplest use of a single JS entry point without transpilation or anything special.