Appearance
Extension Manifest Reference
Status: this page describes the designed sandboxed extension API, which does not run today. Only native extensions run. See what actually runs.
The extension manifest (extension.json) is the declaration file that tells BluePLM everything about your extension. This document covers every field in complete detail.
Quick Reference
json
{
"$schema": "https://blueplm.io/schemas/extension-v1.schema.json",
"id": "publisher.extension-name",
"name": "Display Name",
"version": "1.0.0",
"publisher": "publisher",
"description": "What your extension does",
"icon": "icon.png",
"repository": "https://github.com/...",
"license": "MIT",
"keywords": ["sync", "integration"],
"categories": ["sync"],
"category": "sandboxed",
"engines": { "blueplm": "^1.0.0" },
"extensionDependencies": [],
"extensionPack": [],
"main": "client/index.js",
"serverMain": "server/index.js",
"activationEvents": ["onExtensionEnabled"],
"contributes": { ... },
"permissions": { ... }
}Identity Fields
id (required)
Type: string
Pattern: ^[a-z][a-z0-9-]*\.[a-z][a-z0-9-]*$
Unique identifier for your extension. Must be in publisher.name format.
json
"id": "blueplm.google-drive"
"id": "mycompany.erp-connector"
"id": "johndoe.file-watcher"Rules:
- Must start with your publisher slug
- Only lowercase letters, numbers, and hyphens
- Cannot be changed after publishing
- Must be unique across all extensions
name (required)
Type: string
Min Length: 1
Max Length: 100
Human-readable display name shown in the UI and store.
json
"name": "Google Drive"
"name": "ERP Connector"version (required)
Type: string
Pattern: Semantic versioning (e.g., 1.2.3, 1.0.0-beta.1)
Extension version following semver.
json
"version": "1.0.0"
"version": "2.1.0-beta.1"
"version": "0.9.0+build.123"Version Bumping Guidelines:
- MAJOR (1.0.0 → 2.0.0): Breaking changes
- MINOR (1.0.0 → 1.1.0): New features, backward compatible
- PATCH (1.0.0 → 1.0.1): Bug fixes
publisher (required)
Type: string
Pattern: ^[a-z][a-z0-9-]*$
Publisher identifier. Must match the prefix of your extension id.
json
"publisher": "blueplm"
"publisher": "mycompany"Metadata Fields
description
Type: string
Max Length: 500
Short description shown when the extension is installed.
json
"description": "Sync your engineering files with Google Drive. Supports automatic sync, conflict resolution, and shared drive access."icon
Type: string
Path to the extension icon (relative to package root).
json
"icon": "icon.png"
"icon": "assets/icon.png"Requirements:
- PNG format
- 128×128 pixels recommended
- Square aspect ratio
- Transparent background supported
repository
Type: string (URL)
Source code repository URL. Required for store submission.
json
"repository": "https://github.com/mycompany/blueplm-extension"license (required)
Type: string
OSI-approved license identifier. All BluePLM extensions must be open source.
json
"license": "MIT"
"license": "Apache-2.0"
"license": "GPL-3.0"Common Licenses:
| License | Description |
|---|---|
MIT | Permissive, simple |
Apache-2.0 | Permissive with patent grant |
GPL-3.0 | Copyleft |
BSD-3-Clause | Permissive |
keywords
Type: string[]
Keywords for store search.
json
"keywords": ["sync", "cloud", "backup", "google"]categories
Type: string[]
Categories for filtering.
json
"categories": ["sync", "integration", "productivity"]Available Categories:
sync— File synchronizationintegration— Third-party integrationsproductivity— Workflow toolscad— CAD software integrationserp— ERP system connectorsdevtools— Developer toolsthemes— Visual themeslanguage— Localization
changelog
Type: string
Inline changelog or release notes (markdown supported).
json
"changelog": "## 1.1.0\n- Added batch sync\n- Fixed memory leak\n\n## 1.0.0\n- Initial release"Extension Category
category
Type: "sandboxed" | "native"
Default: "sandboxed"
Determines execution environment and trust requirements.
json
"category": "sandboxed"| Category | Environment | Trust Level | Use Case |
|---|---|---|---|
sandboxed | Extension Host + V8 isolate | Community or Verified | Most extensions |
native | Main Electron process | Verified only | SolidWorks, native code |
native
Type: object
Required when: category is "native"
Configuration for native extensions.
json
"native": {
"platforms": ["win32", "darwin"],
"electronMain": "main/native.js",
"requiresAdmin": false,
"nativeDependencies": ["solidworks-sdk.dll"]
}Properties:
| Field | Type | Description |
|---|---|---|
platforms | ("win32" | "darwin" | "linux")[] | Supported platforms (required) |
electronMain | string | Entry point for main process code |
requiresAdmin | boolean | Needs elevated privileges |
nativeDependencies | string[] | Bundled native binaries |
Dependency Fields
engines (required)
Type: { blueplm: string }
Required BluePLM application version.
json
"engines": {
"blueplm": "^1.0.0"
}Version Ranges:
| Pattern | Meaning |
|---|---|
^1.0.0 | Compatible with 1.x.x (≥1.0.0, <2.0.0) |
~1.2.0 | Patch updates only (≥1.2.0, <1.3.0) |
>=1.5.0 | 1.5.0 or higher |
1.0.0 | Exactly 1.0.0 |
extensionDependencies
Type: string[]
Other extensions this extension depends on.
json
"extensionDependencies": [
"blueplm.core-utils@^1.0.0",
"blueplm.oauth-helper@^2.0.0"
]Format: publisher.name@version-range
The system ensures dependencies are installed and activated before your extension.
extensionPack
Type: string[]
Bundle multiple extensions together as a pack.
json
"extensionPack": [
"blueplm.google-drive",
"blueplm.dropbox",
"blueplm.onedrive"
]Installing the pack installs all listed extensions.
Entry Points
main
Type: string
Client-side entry point (runs in Extension Host).
json
"main": "client/index.js"Must export:
typescript
export function activate(context: ExtensionContext, api: ExtensionClientAPI): void | Promise<void>
export function deactivate?(): void | Promise<void>serverMain
Type: string
Server-side entry point (runs in V8 isolate on org's API).
json
"serverMain": "server/index.js"Used as a default handler or for initialization. Individual route handlers are specified in contributes.apiRoutes.
Activation Events
activationEvents (required)
Type: string[]
Min Items: 1
Events that trigger extension activation. Extensions are lazy-loaded for performance.
json
"activationEvents": [
"onExtensionEnabled",
"onCommand:myext.doThing",
"onNavigate:settings/extensions/myext"
]Available Events:
| Event | When Triggered |
|---|---|
onExtensionEnabled | User enables the extension |
onStartup | BluePLM application starts |
onCommand:commandId | Command is executed |
onNavigate:route | User navigates to route |
onView:viewId | View is opened |
onFileType:extension | File with extension is opened |
Examples:
json
"activationEvents": [
"onExtensionEnabled",
"onCommand:google-drive.sync",
"onNavigate:settings/extensions/google-drive",
"onView:google-drive.panel",
"onFileType:.sldprt"
]Best Practice: Use specific events for faster startup. Avoid onStartup unless necessary.
Contributions
The contributes object declares what your extension adds to BluePLM.
contributes.views
Type: ViewContribution[]
UI views (panels, sidebar items, dialogs).
json
"contributes": {
"views": [
{
"id": "myext.main-panel",
"name": "My Extension",
"icon": "box",
"location": "panel",
"component": "client/components/MainPanel.js",
"when": "vault.isOpen"
},
{
"id": "myext.sidebar-item",
"name": "My Extension",
"icon": "puzzle",
"location": "sidebar",
"component": "client/components/SidebarView.js"
}
]
}View Properties:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | ✓ | Unique view identifier |
name | string | ✓ | Display name |
icon | string | Lucide icon name | |
location | "sidebar" | "panel" | "settings" | "dialog" | ✓ | Where to render |
component | string | ✓ | React component path |
when | string | Condition expression |
Locations:
sidebar— Main sidebar navigationpanel— Content panel areasettings— Settings pagedialog— Modal dialog
contributes.commands
Type: CommandContribution[]
Executable commands for command palette and keybindings.
json
"contributes": {
"commands": [
{
"id": "myext.sync-now",
"title": "Sync Now",
"icon": "refresh-cw",
"keybinding": "Ctrl+Shift+S",
"category": "My Extension",
"when": "vault.isOpen"
},
{
"id": "myext.open-settings",
"title": "Open Settings",
"category": "My Extension"
}
]
}Command Properties:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | ✓ | Unique command identifier |
title | string | ✓ | Display name in command palette |
icon | string | Lucide icon name | |
keybinding | string | Keyboard shortcut | |
category | string | Grouping in command palette | |
when | string | When command is enabled |
Keybinding Format:
Ctrl+Shift+S // Windows/Linux
Cmd+Shift+S // macOS
Ctrl+Alt+K // Modifier combinations
F5 // Function keyscontributes.settings
Type: SettingsContribution[]
Settings pages in the Settings panel.
json
"contributes": {
"settings": [
{
"id": "myext.settings",
"name": "My Extension",
"description": "Configure My Extension",
"icon": "settings",
"component": "client/components/Settings.js",
"category": "extensions"
}
]
}Settings Properties:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | ✓ | Unique settings page ID |
name | string | ✓ | Display name |
description | string | Description text | |
icon | string | Lucide icon name | |
component | string | ✓ | React component path |
category | "account" | "organization" | "extensions" | "system" | Parent category |
contributes.apiRoutes
Type: ApiRouteContribution[]
Server-side HTTP endpoints.
json
"contributes": {
"apiRoutes": [
{
"method": "POST",
"path": "sync",
"handler": "server/sync.js"
},
{
"method": "GET",
"path": "status",
"handler": "server/status.js"
},
{
"method": "POST",
"path": "webhook",
"handler": "server/webhook.js",
"public": true,
"rateLimit": 10
}
]
}Route Properties:
| Field | Type | Required | Description |
|---|---|---|---|
method | "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | ✓ | HTTP method |
path | string | ✓ | Route path (relative to /extensions/{id}/) |
handler | string | ✓ | Handler file path |
public | boolean | No auth required (admin approval needed). Not honoured yet — see Public Endpoints | |
rateLimit | number | Requests per minute (overrides default) |
Final URLs:
POST /extensions/myext/sync → handler: server/sync.js
GET /extensions/myext/status → handler: server/status.js
POST /extensions/myext/webhook → handler: server/webhook.js (public)contributes.configuration
Type: ConfigurationContribution
Extension settings schema (auto-generates UI).
json
"contributes": {
"configuration": {
"title": "My Extension Settings",
"properties": {
"syncInterval": {
"type": "number",
"default": 300,
"minimum": 60,
"maximum": 3600,
"description": "Sync interval in seconds"
},
"autoSync": {
"type": "boolean",
"default": true,
"description": "Enable automatic sync"
},
"excludePatterns": {
"type": "array",
"items": { "type": "string" },
"default": ["*.tmp"],
"description": "File patterns to exclude"
},
"logLevel": {
"type": "string",
"enum": ["debug", "info", "warn", "error"],
"enumDescriptions": [
"All messages",
"Info and above",
"Warnings and errors",
"Errors only"
],
"default": "info",
"description": "Logging verbosity"
}
}
}
}Property Types:
| Type | UI Control | Example |
|---|---|---|
string | Text input | "hello" |
number | Number input | 300 |
boolean | Checkbox | true |
array | List editor | ["a", "b"] |
object | Nested form | { key: "value" } |
Property Options:
| Field | Types | Description |
|---|---|---|
default | all | Default value |
description | all | Help text |
enum | string, number | Allowed values (shows dropdown) |
enumDescriptions | string, number | Labels for enum values |
minimum | number | Minimum value |
maximum | number | Maximum value |
items | array | Schema for array items |
properties | object | Schema for object properties |
order | all | Display order (lower = first) |
deprecationMessage | all | Deprecation warning |
Permissions
permissions (required)
Type: { client?: string[], server?: string[] }
Required permissions for API access. Users see these before installing.
json
"permissions": {
"client": [
"ui:toast",
"ui:dialog",
"ui:progress",
"storage:local",
"network:orgApi",
"commands:register",
"commands:execute",
"workspace:files",
"workspace:vaults",
"telemetry"
],
"server": [
"storage:database",
"secrets:read",
"secrets:write",
"http:domain:api.googleapis.com",
"http:domain:accounts.google.com"
]
}See Permissions Reference for complete documentation.
Complete Example
json
{
"$schema": "https://blueplm.io/schemas/extension-v1.schema.json",
"id": "blueplm.google-drive",
"name": "Google Drive",
"version": "1.2.0",
"publisher": "blueplm",
"description": "Sync engineering files with Google Drive. Supports automatic sync, shared drives, and conflict resolution.",
"icon": "icon.png",
"repository": "https://github.com/bluerobotics/blueplm-google-drive",
"license": "MIT",
"keywords": ["sync", "cloud", "google", "drive", "backup"],
"categories": ["sync", "integration"],
"category": "sandboxed",
"engines": {
"blueplm": "^1.0.0"
},
"main": "client/index.js",
"serverMain": "server/index.js",
"activationEvents": [
"onExtensionEnabled",
"onCommand:google-drive.sync",
"onNavigate:settings/extensions/google-drive"
],
"contributes": {
"views": [
{
"id": "google-drive.panel",
"name": "Google Drive",
"icon": "cloud",
"location": "panel",
"component": "client/components/DrivePanel.js"
}
],
"commands": [
{
"id": "google-drive.sync",
"title": "Sync with Google Drive",
"icon": "refresh-cw",
"keybinding": "Ctrl+Shift+G",
"category": "Google Drive"
},
{
"id": "google-drive.disconnect",
"title": "Disconnect Google Account",
"category": "Google Drive"
}
],
"settings": [
{
"id": "google-drive.settings",
"name": "Google Drive",
"description": "Configure Google Drive sync",
"icon": "cloud",
"component": "client/components/Settings.js",
"category": "extensions"
}
],
"apiRoutes": [
{
"method": "POST",
"path": "connect",
"handler": "server/connect.js"
},
{
"method": "POST",
"path": "sync",
"handler": "server/sync.js"
},
{
"method": "GET",
"path": "oauth-callback",
"handler": "server/oauth-callback.js",
"public": true
}
],
"configuration": {
"title": "Google Drive",
"properties": {
"syncInterval": {
"type": "number",
"default": 300,
"minimum": 60,
"maximum": 3600,
"description": "Automatic sync interval in seconds"
},
"autoSync": {
"type": "boolean",
"default": true,
"description": "Enable automatic synchronization"
},
"conflictResolution": {
"type": "string",
"enum": ["ask", "local", "remote", "newest"],
"enumDescriptions": [
"Ask for each conflict",
"Keep local version",
"Keep remote version",
"Keep newest version"
],
"default": "ask",
"description": "How to handle sync conflicts"
}
}
}
},
"permissions": {
"client": [
"ui:toast",
"ui:dialog",
"ui:status",
"ui:progress",
"storage:local",
"network:orgApi",
"commands:register",
"workspace:files"
],
"server": [
"storage:database",
"secrets:read",
"secrets:write",
"http:domain:googleapis.com",
"http:domain:accounts.google.com"
]
}
}Validation
Use the JSON Schema for editor autocomplete and validation:
json
{
"$schema": "https://blueplm.io/schemas/extension-v1.schema.json"
}Validate with the CLI:
bash
blueplm-ext validate extension.json