Skip to content

Plugin basics ​

The @luna-park/plugin package provides the tools needed to create plugins. It also re-exports LogicType, makeLogicNode, and the Luna Park types.

A plugin exports an object defined with makePlugin:

ts
import { makePlugin } from '@luna-park/plugin';
import myIcon from './my-icon.svg';

export default makePlugin({
    id: 'my-plugin',
    name: 'My Plugin',
    icon: myIcon,
    description: 'What my plugin does.'
});

Required properties:

  • id: unique identifier across all plugins.
  • name: display name.
  • icon: URL string or SVG string.

Optional metadata: description, color, and llm (instructions given to Sidekick and AI agents on how to use your plugin).

Overview ​

PropertyDescription
configConfiguration form, see below.
internalsHidden plugin state, see below.
settingsCustom settings tabs, see below.
lifecyclemount, update, and unmount hooks.
injectCSS or JavaScript injected into the editor.
windowsStandalone windows, see below.
editor.componentsCustom components.
editor.wrapperA component wrapping the whole app, see Custom components.
editor.nodesCustom logic nodes.
editor.tokensDesign tokens.
editor.templatesTemplates.
editor.guardsRoute guards.
hooksBackend and database hooks.
buildDependencies, environment variables, and code injections for the compiled app.

Configuration ​

The config property defines a form displayed in the plugin's top bar button (Config). Values are saved with the project.

config is a LogicType (see Typing).

ts
makePlugin({
    /* ... */
    config: LogicType.object({
        name: LogicType.string({ default: "Marty McFly" })
    })
});
Plugin configuration form

The config object is available in hooks and option functions (e.g. config.name).

Internal state ​

internals stores plugin data that is not exposed in the configuration form. A default value is required.

ts
makePlugin({
    /* ... */
    internals: {
        tutorial: true
    }
});

Available like config in hooks and option functions (e.g. internals.tutorial). It is saved with the project.

Option format ​

The editor, build, and inject options accept either:

  • a direct value,
  • a function that returns the value (can be asynchronous).

When a function is used, it receives the plugin environment:

PropertyDescription
configThe current configuration.
internalsThe current internal state.
modebuild or editor, depending on the environment.
appThe project's application.
getFile(id)Reads a file of the project.
addFile(file, parentId?)Adds a file to the project (a database, a store...).
log(message, severity?)Writes to the editor console.
backend.cookiesThe cookies of the editor's backend.

The same environment is passed to the lifecycle hooks.

Lifecycle hooks ​

Mount ​

Called when the plugin is mounted in the editor (installation or project load). This is the place to create the files your plugin needs, with addFile.

ts
makePlugin({
    lifecycle: {
        mount: ({ app, addFile }) => { console.log("Plugin mounted!") }
    }
});

Unmount ​

Called when the plugin is uninstalled.

ts
makePlugin({
    lifecycle: {
        unmount: () => { console.log("Goodbye!") }
    }
});

Update ​

Called on every plugin configuration update.

ts
makePlugin({
    lifecycle: {
        update: ({ config }) => { console.log("New config:", config) }
    }
});

Injections ​

inject injects CSS or JavaScript into the editor:

ts
makePlugin({
    inject: {
        css: `#app { background-color: red; }`,
        js: `alert("Hey!");`
    }
});

Each entry can be a string or a function that returns a string. To inject code into the compiled app, use build.injections.

Settings tabs ​

For settings that a form can't express, add your own Vue components as tabs of the plugin's Settings:

ts
import { shallowRef } from 'vue';
import { faGear } from '@fortawesome/pro-solid-svg-icons';
import MySettings from './MySettings.vue';

makePlugin({
    settings: [
        { label: 'General', icon: faGear, component: shallowRef(MySettings) }
    ]
});

Custom windows ​

A plugin can provide standalone pages, opened in a separate browser window (an OAuth callback, a tool...). Declare them in windows:

ts
import MyWindow from './MyWindow.vue';

makePlugin({
    windows: {
        MyWindow
    }
});

A window is reachable at https://luna-park.app/plugin?plugin=<package>&window=<name>, for example with window.open(). Windows of plugins outside @luna-park/ ask for confirmation before loading.

Templates ​

A plugin can provide ready-made layout blocks. They appear in the Templates tab of the editor's bottom panel, and users drag them into their layouts.

ts
makePlugin({
    editor: {
        templates: [
            {
                name: 'Login form',
                preview: 'https://example.com/preview.png',
                template: loginFormFile
            }
        ]
    }
});

template is a component file in the Luna Park project format, and preview an optional image URL.


INFO

Components, logic nodes, tokens, and backend features are covered in the following pages.