Skip to content

Manage plugins

A plugin is a customer-authored npm package that extends Norsk Studio’s node catalog. The plugin tooling lives on the Studio product — it’s an HTTP surface served by the product backend and reached through the runner proxy under /products/norsk-studio/api/plugins/*. norsk-ctl itself carries no plugin commands; it only lists the baked images that plugin build produces and lets a launch select one.

Drop plugin directories under your working directory’s plugins/ subdirectory. Both top-level (plugins/foo/) and scoped (plugins/@scope/bar/) layouts are supported. Each directory must contain a package.json with a non-empty name field — that’s the discovery contract.

<workingDirectory>/
plugins/
my-plugin/
package.json
dist/
@acme/
my-other-plugin/
package.json
dist/

A directory without a readable package.json is skipped with a warning, never a hard error.

Four endpoints cover the lifecycle. All of them shell out to Docker (never to a host npm), so the only host requirement is the same Docker the runner already needs. workingDirectory is always explicit — there is no daemon-side default.

EndpointBody / queryPurpose
GET /products/norsk-studio/api/plugins?workingDirectory=…query paramList plugins discovered under <workingDirectory>/plugins/
POST /products/norsk-studio/api/plugins/create{ name, workingDirectory, studioTag? }Scaffold a new plugin via the Studio SDK
POST /products/norsk-studio/api/plugins/install{ pkg, workingDirectory, studioTag? }Install an npm package as a plugin
POST /products/norsk-studio/api/plugins/build{ tag, workingDirectory, fromImage?, fromTag?, push? }Bake every plugin into a derived studio image

The examples below go through the runner proxy, so they carry whatever authentication your proxy session uses.

Terminal window
curl "https://<host>/products/norsk-studio/api/plugins?workingDirectory=/path/to/wd"

Returns the discovered plugins (name + path), sorted by name.

Terminal window
curl -X POST "https://<host>/products/norsk-studio/api/plugins/create" \
-H "Content-Type: application/json" \
-d '{"name": "my-plugin", "workingDirectory": "/path/to/wd"}'

Runs the Studio SDK scaffold inside the studio image against <workingDirectory>/plugins/my-plugin/. The scaffold writes a working package skeleton plus build scripts. Returns 409 if the target directory already exists.

Terminal window
curl -X POST "https://<host>/products/norsk-studio/api/plugins/install" \
-H "Content-Type: application/json" \
-d '{"pkg": "@acme/my-plugin@1.2.0", "workingDirectory": "/path/to/wd"}'

Runs npm install inside a throwaway studio container, then copies the resolved package into <workingDirectory>/plugins/<name>. Useful for pulling a pre-built plugin off a private registry.

Terminal window
curl -X POST "https://<host>/products/norsk-studio/api/plugins/build" \
-H "Content-Type: application/json" \
-d '{"tag": "my-registry/studio-baked:v1", "workingDirectory": "/path/to/wd"}'

Bakes every plugin under <workingDirectory>/plugins/ into a derived studio image and writes the norsk-ctl.baked-plugins LABEL listing their names. Add "push": true to push to a registry; fromImage / fromTag override the base studio image.

There are two delivery paths:

  • Baked image pinned by a product template. Build a derived image with plugins/build, then create a Studio product template that pins it: in the create-template screen pick the Dev template and put <repository>:<tag> in the Custom studio image field (or pass studioImage to the Studio product’s POST /api/product-template). The product template’s compose pins the image — changing image, like changing version, means creating a new product template. The Media image is unaffected.
  • server.library via the product template. The Studio image loads whatever packages are listed in server.library, which products author via their NODE_CONFIG env. On Studio Dev, plugin package names can be added to the STUDIO_LIBRARIES parameter. See Studio libraries.

There is no launch-time bind-mount or working-directory discovery — instances only see plugins that are in the image (baked) or listed in server.library.

The runner’s Images page lists every locally-built image carrying the norsk-ctl.baked-plugins label, with the baked plugin names parsed from the label. That’s the inventory to pick from when creating a product template around a baked image.

Apply plugin changes to a running instance

Section titled “Apply plugin changes to a running instance”

Plugin changes (new files, version bumps) are picked up by rebuilding the image and launching from a product template that pins it — not while the instance is running. Rebuild via plugins/build under the same tag, create (or keep) a product template pinning that tag, and relaunch.

  • One broken plugin must not block the rest. A plugin directory without a package.json, an unreadable file, or malformed JSON is skipped with a warning; the rest still list and bake.
  • Discovery is alphabetical. The resolved list is sorted by name for deterministic ordering in the baked label. Renaming a plugin changes its position.
  • workingDirectory is always explicit. Every endpoint requires it — there’s no fallback to a configured default. A missing workingDirectory is a 400.
  • The endpoints require Docker. Scaffold, install, and build all run docker against the studio image — there’s no host-side npm path.
  • Studio libraries — Studio’s component packages, configured on the product template
  • Sidecars — extra containers (not extra Studio nodes)