Skip to main content
Pascal plugins add new kinds of objects to a scene. A plugin can define how its objects are validated, rendered in 3D, drawn in floor plans, edited, and exposed to AI tools. It can also provide a panel in the editor.
Today, a Pascal host must review and bundle a plugin before it can be enabled. The Plugins sidebar toggles bundled code for one project; it does not download code from GitHub or npm. Runtime installation from the hosted catalog is planned, but is not part of Plugin API v1 yet.
Start with the open-source Nature plugin. It is a complete, standalone example that adds trees, flowers, and grass to Pascal. Clone it when you want a working package to modify instead of starting from an empty repository.
Follow the repository’s README for its current build, test, and local integration commands.

Prepare a publishable repository

Keep the plugin in its own public repository and make one release reproducible before asking a Pascal host to load it. A reviewable repository should include:
  1. One npm package with a unique plugin ID and an explicit Pascal API compatibility range.
  2. @pascal-app/*, React, React DOM, and Three.js as peer dependencies rather than bundled duplicate runtimes.
  3. An immutable commit or release artifact, a lockfile, a license, and commands for type checking, tests, and building.
  4. No required install-time scripts and no undeclared network calls.
  5. A README that identifies the publisher, repository, support contact, capabilities, external origins, persisted project data, and any account or personal data used.
  6. Lazy UI and renderer entry points so loading plugin metadata does not initialize external services or expensive runtime code.
The Pascal CLI manages a persistent local editor, but it does not validate or package plugins yet. Until a machine-readable artifact format ships, Nature’s package and README are the reference layout.

Plugin structure

Every plugin exports a manifest with a globally unique ID, the Pascal plugin API version it targets, and its node definitions:
Use a namespaced ID such as company:plugin-name. The current apiVersion is 1; Pascal rejects plugins that target an incompatible version. Declare the @pascal-app/* packages used by your plugin as peer dependencies. The host must provide these packages so your plugin and the editor share one node registry. Bundling another copy of @pascal-app/core creates a separate registry and the plugin will not load correctly.

Define a node

The manifest’s nodes array contains NodeDefinition objects. Each definition starts with a schema and defaults, then opts into only the Pascal capabilities it needs.
A definition can contribute any combination of: Keep renderer and editor modules lazy, as shown above. This lets hosts avoid loading plugin UI and rendering code until it is needed.

Add an editor panel

The core manifest is independent of any editor UI. Export an EditorHostPanel separately if your plugin needs a sidebar panel:
Register the panel with registerEditorHostPanel. Pascal uses creator and pluginUrl on the plugin detail page and loads the panel component inside an error boundary.

Keep the plugin independent

Plugin source belongs in the publisher’s repository, not in the Pascal editor repository. Publish or pin an immutable package version and keep every @pascal-app/*, React, and Three.js import as a peer dependency. A host currently reviews and bundles the package before making it available; the Plugins sidebar only enables code the host already has. Do not require a change to a built-in node switch, host store, or Pascal package to add your plugin. Host-specific wiring should be limited to discovery, optional panel registration, styling/build configuration, and any explicitly reviewed server adapter.

Load the plugin in a host

The host decides where plugins come from. Register discovery before importing the Pascal bootstrap module:
Plugin loading is add-only for the browser session. Duplicate node kinds fail at startup instead of silently replacing each other.
The Plugins sidebar controls whether an already loaded plugin is enabled for the current project. Installing or uninstalling there does not download or remove an npm package. Uninstalling hides the plugin’s panel, tools, renderers, systems, and floor-plan output while preserving its nodes in the scene graph, so no project data is deleted.

Connected services and personal data

Plugin API v1 does not discover or mount server routes. A host may separately add a reviewed server adapter for a plugin that connects to an external service, but that adapter is host integration—not a portable plugin contribution. Before a host enables an account-connected plugin, the plugin and adapter must:
  1. List every OAuth scope, external origin, account field read, user-provided field sent, provider field persisted into a Pascal project, and browser/server storage location.
  2. Ask the user to connect explicitly and explain the data exchange before authorization.
  3. Keep access and refresh tokens in HttpOnly, Secure production cookies or an equivalent server-side credential store; plugin JavaScript must not receive them.
  4. Bind the external-service session to the active Pascal user so switching Pascal accounts in one browser cannot expose the previous user’s external account.
  5. Proxy only allowlisted upstream paths and headers, enforce same-origin checks on mutations, avoid logging credentials or personal data, and provide logout and revocation behavior.
  6. Document who owns OAuth client registration and register every exact production, preview, and local callback before release. Confirm the client ID, public versus confidential client type, PKCE method, grants, scopes, resource audience, and token authentication method with the provider.
  7. Run the complete production flow after registration: connect, callback, refresh, provider API access, logout or revocation, and switching between two Pascal accounts in the same browser.
If the provider displays Unknown client, the authorization server does not recognize the configured client ID. If it displays a redirect mismatch, the client exists but the exact callback is not allowlisted. Both are provider-side provisioning failures; changing Pascal’s callback dynamically would weaken the OAuth boundary and is not a workaround. An external model or asset URL still discloses ordinary request metadata such as the user’s IP address and user agent to that asset host. Include that provider in the plugin’s data disclosure.

Test your plugin

Before integrating a plugin into a host:
  1. Validate every node against its schema and test any geometry or floor-plan functions as pure functions.
  2. Add a registry test that loads the manifest and confirms each expected node kind is registered.
  3. Load the plugin in a Pascal host with setPluginDiscovery and confirm the development console reports its ID and node count.
  4. Create, save, reload, uninstall, and reinstall its nodes to check the complete project lifecycle.
The Nature plugin source demonstrates the manifest, node definitions, shared rendering systems, placement tools, editor panel, and tests together in one package.

Current API boundaries

Plugin API v1 does not add routes, application pages, host stores, or new material and floor-plan primitive types. A plugin can use its own state and can create materials inside its renderer or system, but it does not extend Pascal’s global stores. A reviewed host may mount a separate server adapter as described above; the manifest itself cannot request or register one. Keeping this boundary narrow lets the same plugin contract work for first-party and external nodes.

Run a local editor with the CLI

The Pascal CLI lets you run the standalone editor without cloning the Pascal repository:
This installs a versioned editor runtime and preserves local projects in ~/.pascal/data/pascal.db. It does not install a plugin repository. To test a plugin, continue to use the reviewed host integration described in Load the plugin in a host. pascal plugin list can inspect the local managed-plugin lock. Plugin discovery, validation, packaging, installation, removal, and catalog commands are not available in the current CLI release.