Packaging & Distribution
How to build, package, and distribute OpenGPEX plugins for installation by other users.
Build Tool
Use the built-in packaging script:
pnpm pack-plugin <PluginFolderName> # Standard build
pnpm pack-plugin <PluginFolderName> --minify # Minified production build
Example:
pnpm pack-plugin ColorPickerDrawer
# Output: dist/user-plugin-colorpickerdrawer-1.0.0.zip
ZIP Structure
The packaged ZIP contains:
user-plugin-colorpickerdrawer-1.0.0.zip
├── plugin.json # Plugin metadata (auto-generated from manifest)
├── dist/
│ ├── index.js # ESM bundle (compiled from TypeScript)
│ └── index.css # Extracted CSS (if any)
└── visuals/ # Static assets (auto-copied from source)
└── logo.svg
plugin.json Requirements
The plugin.json must include:
{
"id": "drawers.color_picker",
"displayName": "Color Picker",
"version": "1.0.0",
"description": "A simple color picker tool",
"author": "my-username",
"category": "drawers"
}
Both id and author are required — the packager will refuse to build if either is missing.
External Dependencies (Mandatory)
The following packages are always externalized — they are provided by the host runtime and must NOT be bundled:
| Package | Reason |
|---|---|
react |
Shared single React instance (prevents "Invalid hook call") |
react-dom |
Same as above |
lucide-react |
Shared icon library |
@opengpex/editor/* |
Editor framework APIs |
The pack-plugin script handles this automatically. If your plugin tries to bundle React, it will cause runtime crashes.
Asset Bundling
All subdirectories in your plugin source (excluding node_modules, dist, .git) are automatically copied into the ZIP. Directory naming is not restricted — use assets/, visuals/, icons/, media/, or any name you prefer.
Reference assets in your code via usePluginResource():
const logo = usePluginResource('visuals/logo.svg');
Namespace Protection
- ❌ Plugin
idstarting withbase.→ packager refuses to build - ❌ Plugin
idstarting withcom.gpex.plugins.base.→ upload rejected - ✅ Dynamic loader forces
sourceType: 'user'on all uploaded plugins
Distribution Channels
| Channel | Method |
|---|---|
| GPEX Hub | Upload ZIP via the Hub interface (coming soon) |
| Direct share | Send ZIP file; recipient uploads via Settings > Plugins |
| Git repository | Clone and place in plugins/user/ for static development |
Installation (User Side)
- Download the
.zipfile - Open the editor → GPEX Hub panel → Installed tab → Upload Plugin
- Select the ZIP file
- Plugin appears in the appropriate slot after page reload
Style Isolation
- Custom styles go in
index.css(automatically extracted by packager) - Must use scoped class names or CSS modules — global tag selectors are forbidden
- The plugin inherits the editor's dark/light theme via CSS custom properties
Next Steps
- Your First Plugin — Create a plugin to package
- Asset Management — Bundle static assets
- Security & Isolation — Trust levels for distributed plugins
Last updated: 2026-07-30