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.
Where plugins live
Section titled “Where plugins live”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.
The Studio product API
Section titled “The Studio product API”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.
| Endpoint | Body / query | Purpose |
|---|---|---|
GET /products/norsk-studio/api/plugins?workingDirectory=… | query param | List 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.
List discovered plugins
Section titled “List discovered plugins”curl "https://<host>/products/norsk-studio/api/plugins?workingDirectory=/path/to/wd"Returns the discovered plugins (name + path), sorted by name.
Scaffold a plugin
Section titled “Scaffold a plugin”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.
Install an npm package as a plugin
Section titled “Install an npm package as a plugin”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.
Bake plugins into a custom studio image
Section titled “Bake plugins into a custom studio image”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.
How plugins reach an instance
Section titled “How plugins reach an instance”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 passstudioImageto the Studio product’sPOST /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.libraryvia the product template. The Studio image loads whatever packages are listed inserver.library, which products author via theirNODE_CONFIGenv. On Studio Dev, plugin package names can be added to theSTUDIO_LIBRARIESparameter. 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.
Baked images on the Images page
Section titled “Baked images on the Images page”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.
Gotchas
Section titled “Gotchas”- 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
namefor deterministic ordering in the baked label. Renaming a plugin changes its position. workingDirectoryis always explicit. Every endpoint requires it — there’s no fallback to a configured default. A missingworkingDirectoryis a400.- The endpoints require Docker. Scaffold, install, and build all run
dockeragainst the studio image — there’s no host-sidenpmpath.
See also
Section titled “See also”- Studio libraries — Studio’s component packages, configured on the product template
- Sidecars — extra containers (not extra Studio nodes)