Skip to content

Creating a Plugin

Aarav Malani edited this page Jun 6, 2026 · 1 revision

Creating a plugin involves several tiny steps, which together form a coherent process. If not already completed, reading the previous pages will be helpful.

1. Design Decisions

At this step, figure out what you're trying to do.

  • Do you need a web and/or runner plugin?
  • Do you need an external plugin and/or installable plugin?
  • What will the plugin(s) do?
  • If there is a distinct web and runner plugin,
    • What message formats will the web and runner plugins send and receive?
    • What channels will the web and runner plugins communicate over?

A brief idea of the above will help in designing your plugin.

An example step-through would be for the Data Visualizer.

  • There needs to be a web (receives and displays data) and runner (sends the data) plugin
  • Both should probably be installable (the host plugin needs the ability to create tabs and the web plugin needs the ability to access variables)
  • The runner plugin will have an abstract method display which receives a value. On calling the function, it sends the value over to the web plugin which displays it.
  • There is a distinct web and runner plugin
    • The runner plugin needs to be able send a language-agnostic value type and the web plugin needs to be able to send nothing.
    • They will communicate over a single data channel.

Note: the goal of the plugin repository and Conductor framework as a whole is to promote language agnosticism and code reuse. Try to ensure data transmitted between your runner plugin and web plugin is language-agnostic, since another evaluator may also benefit from implementing the same runner plugin.

2. Create the common types

The src/common directory contains common types for both the runner and web plugins, including message types, channel IDs and other common configuration details.

Copy the src/common/test directory to src/common/<name>. Then, rename instances of test in the name field of package.json.

Then, edit src/common/<name>/index.ts to add your message types, channel ID, runner plugin ID, etc.

If neither of the packages are installable, you may choose to make the plugin external (TODO: add an internal type)

3. Making plugins external

If in the previous step, or any of the future steps, a plugin needs to be converted from installable to external,

  1. Update the manifest.json to use "type": "external"
  2. Substitute the nodeResolve() plugin in rollup.config.mjs with nodeResolve({ preferBuiltins: false, browser: true })

4. Copy the runner and/or web plugins

Similarly, duplicate src/runner/test and/or src/web/test if required. Update instances of @sourceacademy/common-test and other instances of the test plugin with the new name.

5. Build & Test

After developing a prototype of the plugin, build it and test it out by running the first list of commands from Building & Testing

Clone this wiki locally