Bolt CEP

repository·master·Indexed 19 days ago

https://github.com/hyperbrew/bolt-cep

A high-performance boilerplate for building Adobe Common Extensibility Platform (CEP) extensions using modern web technologies including Vite, TypeScript, and frameworks such as Svelte, React, or Vue. It features end-to-end type safety between JavaScript and ExtendScript via evalTS(), event communication with listenTS() and dispatchTS(), and integrated ZXP packaging. The project includes the vite-cep-plugin for bundling panels with Vite.js.

Tokens
14.7K
Snippets
64
Records
72
Agent score
67%

What's inside bolt-cep

  1. Create invisible or headless panels

    master

    You can create panels that are hidden from the Adobe Extensions menu or run completely without a UI:

    1. Invisible Panel (Hidden from menu): Set panelDisplayName to an empty string "" in cep.config.ts.
    2. Headless Panel (No UI): Set panelDisplayName to "" AND set the type to "Custom".

    To ensure headless panels can be launched, use csi.requestOpenExtension() from another panel or configure startOnEvents in cep.config.ts to trigger on specific Adobe application events.

    // Example of a headless panel configuration
    panels: [
      {
        mainPath: "./main/index.html",
        name: "Invisible Bolt CEP",
        panelDisplayName: "",
        type: "Custom",
        startOnEvents: [
          "com.adobe.csxs.events.ApplicationActivate",
          "com.adobe.csxs.events.ApplicationInitialized",
          "applicationActivate",
        ],
      }
    ]
  2. Configure CEP Panel Structure

    master

    Bolt CEP treats each panel as its own page with shared code. Panels are configured in cep.config.ts.

    Default Structure

    The boilerplate includes main and settings panels:

    src
     └─ js
        ├─ main
        │   ├─ index.html
        │   └─ index.tsx
        └─ settings
            ├─ index.html
            └─ index.tsx

    Adding New Panels

    1. Add a new item to the panels object in cep.config.ts.
    2. Duplicate the folder structure (e.g., src/js/new-panel/) and adjust the files accordingly.
  3. Write and Organize ExtendScript

    master

    ExtendScript is written in ES6 and compiled to ES3. It supports JSON 2 and external library inclusion via the @include directive.

    Including Libraries

    // @include './lib/library.js'

    Application-Specific Modules

    To ensure type-safety and organization, code is split into modules based on the host application name. These are located in src/jsx/:

    • aftereffects $\rightarrow$ aeft/aeft.ts
    • illustrator $\rightarrow$ ilst/ilst.ts
    • animate $\rightarrow$ anim/anim.ts

    Adding Support for New Host Apps

    1. Create a new module file (e.g., photoshop.ts).
    2. Extend the switch() statement in src/jsx/index.ts to include your new module.
    3. Add the host to your cep.config.ts file.
  4. Configure Router basename for CEP context

    master

    In CEP, window.location.pathname resolves to a full system file path (e.g., file:///C:/.../index.html) rather than a web path. If using a router like react-router, you must adjust the basename based on whether the code is running in a CEP context (detected via window.cep_node) or a browser context.

    const posix = (str: string) => str.replace(/\\/g, "/");
    
    const cepBasename = window.cep_node
      ? `${posix(window.cep_node.global.__dirname)}/`
      : "/main/";
    
    ReactDOM.render(
      <React.StrictMode>
        <Router basename={cepBasename}>...</Router>
      </React.StrictMode>,
      document.getElementById("app")
    );
  5. Update an existing Bolt CEP project

    master

    To update to the latest version, create a new project with the same framework (React, Vue, or Svelte) and compare/update the following files:

    1. package.json (Update dependencies and scripts, then re-install).
    2. vite.config.ts and vite.es.config.ts.
    3. cep.config.ts (Check for new properties).
    4. src/js/lib (Update the entire folder).
    5. src/js/main/index.html and the framework-specific index file.
    6. src/jsx/index.ts.
    7. src/shared/universals.d.ts.
  6. Quick Start with Bolt CEP

    master

    To create a new Bolt CEP project, use the create-bolt-cep CLI tool. Follow the prompts to configure your project, then navigate into the directory and install dependencies.

    1. Initialize Project

    • Yarn: yarn create bolt-cep
    • NPM: npx create-bolt-cep
    • PNPM: pnpm create bolt-cep

    2. Install Dependencies

    • yarn (or npm i / pnpm i)

    3. Enable PlayerDebugMode

    Required for testing dev or build modes locally. Only installed ZXP packages work without this.

    4. Development Workflow

    • Build (Initial/Static): Run yarn build (or npm run build / pnpm build) to create the symlink to your extensions folder.
    • Hot Reload (HMR): Run yarn dev (or npm run dev / pnpm dev) for rapid development. View the panel in your browser at localhost:3000/panel/.
    yarn create bolt-cep
    cd project
    yarn
    yarn build
    yarn dev
  7. Build and Package for Distribution

    master

    Once development is complete, use the following commands to package your extension for users.

    Create a ZXP Package

    Generates a .zxp file in the dist/zxp folder. This can be installed using the aescripts ZXP Installer.

    • yarn zxp (or npm run zxp / pnpm zxp)

    Create a ZIP Archive

    Bundles the packaged ZXP file along with any assets specified in the copyZipAssets configuration into a .zip archive in the ./zip folder.

    • yarn zip (or npm run zip / pnpm zip)

    GitHub Actions Automation

    If you add a git tag and push it, GitHub Actions will automatically build a ZXP and add it to your repository's releases:

    git tag 1.0.0
    git push origin --tags
    yarn zxp
    yarn zip
  8. Handle Node.js modules and dependencies

    master

    Bolt CEP provides specific ways to handle Node.js modules:

    • Built-in modules: Import os, path, and fs from src/js/lib/node.ts.
    • 3rd party libraries: Try standard import first. If the module uses the Node.js runtime and fails, use require() syntax.
    • Runtime safety: Place require() calls inside functions so they only execute at runtime, preventing errors during browser-based previews.
    • Missing modules: If the build system fails to detect a module used via require(), explicitly add it to the installModules array in cep.config.ts.
    // Importing built-ins
    import { os, path, fs } from "../lib/node";
    
    // Using require for 3rd party modules
    const unzipper = require("unzipper");
    
    // Explicitly installing a module in cep.config.ts
    installModules: ["unzipper"],
  9. Access the Bolt CEP ExtendScript API via the namespace

    master

    When running in an Adobe ExtendScript environment, Bolt CEP attaches its application-specific API to the global host object (usually $ or window) using a specific namespace. This namespace is defined by the ns constant from the shared configuration.

    Depending on which Adobe application is running, the available API surface will change. For example, if running in After Effects, the ns property on the global object will contain the aeft module. This allows you to write code that targets the correct application-specific commands automatically.

    // Assuming 'ns' is 'bolt' (the value of the ns constant)
    // In After Effects:
    bolt.aeft.someCommand();
    
    // In Photoshop:
    bolt.phxs.someCommand();