How to Develop a New Extension for Modly: A Complete Guide
You develop a Modly extension by creating a self-contained GitHub repository with a manifest.json file and an entry script—JavaScript for process extensions or Python for model extensions—then installing it via the Models tab using the repository URL.
Modly’s plugin architecture allows developers to extend the application’s capabilities by adding custom process or model extensions that integrate directly into the visual workflow editor. The core application discovers these extensions at runtime by cloning repositories into the local extensions directory and validating their manifests against a strict schema.
Extension Types and Architecture
Modly supports two distinct extension types, each serving different purposes in the workflow pipeline.
Process Extensions
Process extensions handle data transformation and manipulation within workflows. These execute JavaScript or TypeScript code to receive input from previous nodes, perform computations, and return results to downstream nodes. The backend loads these via the IPC bridge defined in electron/preload/electron-api.ts, specifically through the extensions.runProcess method.
Model Extensions
Model extensions provide AI-powered generation capabilities, typically involving Python-based machine learning models. These require a generator.py file containing a class that inherits from Modly’s BaseGenerator interface. The class specified in the manifest’s generator_class field is instantiated by the backend to process inputs and return generated assets like 3D meshes.
Creating the Extension Repository Structure
Every Modly extension must follow a specific repository layout to pass validation and load correctly.
The manifest.json Schema
The manifest.json file in your repository root defines the extension’s metadata and entry points. According to the validation logic in electron/main/extension-install-utils.ts (specifically the validateInstallManifest function), the manifest must include these required fields:
{
"id": "my-awesome-extension",
"type": "process",
"entry": "processor.js",
"generator_class": "MyGenerator",
"nodes": [{ "id": "my-node" }]
}
id: A unique identifier across all installed extensionstype: Either"process"or"model", determining the validation pathentry: The executable file path (defaults toprocessor.js)generator_class: Required only for model extensions; specifies the Python class name to instantiatenodes: An array defining the node types this extension contributes to the workflow editor
Repository Layout Requirements
For process extensions, your repository must contain:
manifest.jsonwith"type": "process"- The entry JavaScript file specified in the
entryfield
For model extensions, your repository must contain:
manifest.jsonwith"type": "model"- A
generator.pyfile containing the generator class - The
generator_classfield matching the class name ingenerator.py
Implementing Process Extensions
Process extensions export an async function named run that receives input data and parameters from the workflow node.
Create a processor.js file implementing this signature:
// processor.js – minimal process extension
export async function run(input, params) {
// input: data from previous node (e.g., image buffer)
// params: node-specific configuration values
const result = await performTransformation(input, params);
return { text: result.summary };
}
The return object’s shape must match the expectations of workflowRunStore, which processes the result and passes it to subsequent nodes. The function runs inside the Electron main process via the IPC bridge exposed in electron/preload/electron-api.ts, allowing access to Node.js APIs and external libraries.
Implementing Model Extensions
Model extensions require Python code that implements the BaseGenerator interface from the modly_api package.
Create a generator.py file with a class matching your generator_class manifest field:
# generator.py – minimal model extension
from modly_api import BaseGenerator
class MyGenerator(BaseGenerator):
def generate(self, image_path: str) -> str:
# Process the input image with your ML model
mesh_path = run_inference_and_export_glb(image_path)
return mesh_path
The backend validates that generator.py exists during installation (checked in extension-install-utils.ts) and dynamically imports the specified class. The generate method receives the input file path and must return the path to a generated asset (typically a .glb mesh file).
Installing and Testing Your Extension
Local Development Testing
To test your extension before publishing:
- Clone your extension repository into the Modly extensions directory at
$HOME/.modly/extensions - Launch Modly in development mode:
npm run dev - Open the Workflow editor and add a node corresponding to your extension type
- Select your extension from the node-type dropdown
- Execute the workflow and monitor the console or UI logs (accessible at
extensions/errors) for validation messages
Installing from GitHub
Once tested, push your repository to GitHub. Users (or yourself on other machines) can install it via the UI:
- Open Modly and navigate to the Models tab
- Click Install from GitHub
- Paste the HTTPS URL of your extension repository
- Modly clones the repo, validates the
manifest.json, compiles the entry file if necessary, and registers the extension
The installation process uses the methods exposed through electron/preload/electron-api.ts, including extensions.installFromGitHub and extensions.reload.
Summary
- Modly extensions are self-contained GitHub repositories with a mandatory
manifest.jsonfile validated byelectron/main/extension-install-utils.ts - Process extensions use JavaScript entry files exporting a
run(input, params)function and integrate viaworkflowRunStore - Model extensions use Python classes inheriting from
BaseGeneratorwith agenerate()method, specified via thegenerator_classmanifest field - Extensions install into
$HOME/.modly/extensionsand are discovered at runtime by the IPC bridge inelectron/preload/electron-api.ts - Testing locally requires cloning to the extensions folder and running Modly in development mode
Frequently Asked Questions
What file structure is required for a Modly extension?
A valid extension requires a manifest.json in the repository root plus an entry file appropriate to the type. Process extensions need a JavaScript file (default processor.js) exporting a run function, while model extensions require a generator.py containing a class that extends BaseGenerator. The manifest.json must declare all required fields including id, type, and either entry or generator_class depending on the extension type.
How does Modly validate extension manifests?
The validateInstallManifest function in electron/main/extension-install-utils.ts validates every manifest against a strict schema. It checks that required fields exist, that the type is either "process" or "model", and that appropriate complementary fields are present (e.g., generator_class for model types). Validation failures surface in the UI through the extensions/errors interface, preventing malformed extensions from loading.
Can I use TypeScript for process extensions?
Yes, you can write process extensions in TypeScript. Modly compiles the entry file during installation if necessary. Ensure your manifest.json points to the compiled JavaScript output or the TypeScript source if the build process handles transpilation. The exported run function must remain the default export regardless of the language used.
How do I debug a Modly extension during development?
Debug by running Modly in development mode (npm run dev) with your extension cloned into $HOME/.modly/extensions. Use the Workflow editor to instantiate your node and execute test runs. Check the Electron console and the dedicated extensions/errors view in the UI for validation errors or runtime stack traces. You can reload extensions dynamically using the extensions.reload method exposed in electron/preload/electron-api.ts without restarting the application.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →