Penpot plugins API
    Preparing search index...

    Interface Penpot

    These are methods and properties available on the penpot global object.

    interface Penpot {
        ui: {
            open: (
                name: string,
                url: string,
                options?: { width: number; height: number },
            ) => void;
            size: { width: number; height: number } | null;
            resize: (width: number, height: number) => void;
            sendMessage: (message: unknown) => void;
            onMessage: <T>(callback: (message: T) => void) => void;
        };
        utils: ContextUtils;
        closePlugin: () => void;
        on<T extends keyof EventsMap>(
            type: T,
            callback: (event: EventsMap[T]) => void,
            props?: { [key: string]: unknown },
        ): symbol;
        off(listenerId: symbol): void;
        root: Shape | null;
        currentFile: File | null;
        currentPage: Page | null;
        viewport: Viewport;
        flags: Flags;
        history: HistoryContext;
        library: LibraryContext;
        fonts: FontsContext;
        currentUser: User;
        activeUsers: ActiveUser[];
        theme: Theme;
        localStorage: LocalStorage;
        selection: Shape[];
        shapesColors(shapes: Shape[]): (Color & ColorShapeInfo)[];
        replaceColor(shapes: Shape[], oldColor: Color, newColor: Color): void;
        uploadMediaUrl(name: string, url: string): Promise<ImageData>;
        uploadMediaData(
            name: string,
            data: Uint8Array,
            mimeType: string,
        ): Promise<ImageData>;
        group(shapes: Shape[]): Group | null;
        ungroup(group: Group, ...other: Group[]): void;
        createRectangle(): Rectangle;
        createBoard(): Board;
        createEllipse(): Ellipse;
        createPath(): Path;
        createBoolean(boolType: BooleanType, shapes: Shape[]): Boolean | null;
        createShapeFromSvg(svgString: string): Group | null;
        createShapeFromSvgWithImages(svgString: string): Promise<Group | null>;
        createText(text: string): Text | null;
        generateMarkup(
            shapes: Shape[],
            options?: { type?: "html" | "svg" },
        ): string;
        generateStyle(
            shapes: Shape[],
            options?: {
                type?: "css";
                withPrelude?: boolean;
                includeChildren?: boolean;
            },
        ): string;
        generateFontFaces(shapes: Shape[]): Promise<string>;
        openViewer(): void;
        createPage(): Page;
        openPage(page: string | Page, newWindow?: boolean): void;
        alignHorizontal(
            shapes: Shape[],
            direction: "center" | "left" | "right",
        ): void;
        alignVertical(
            shapes: Shape[],
            direction: "center" | "top" | "bottom",
        ): void;
        distributeHorizontal(shapes: Shape[]): void;
        distributeVertical(shapes: Shape[]): void;
        flatten(shapes: Shape[]): Path[];
    }

    Hierarchy

    • Omit<Context, "addListener" | "removeListener">
      • Penpot
    Index

    Properties

    ui: {
        open: (
            name: string,
            url: string,
            options?: { width: number; height: number },
        ) => void;
        size: { width: number; height: number } | null;
        resize: (width: number, height: number) => void;
        sendMessage: (message: unknown) => void;
        onMessage: <T>(callback: (message: T) => void) => void;
    }

    Type Declaration

    • open: (name: string, url: string, options?: { width: number; height: number }) => void

      Opens the plugin UI. It is possible to develop a plugin without interface (see Palette color example) but if you need, the way to open this UI is using penpot.ui.open. There is a minimum and maximum size for this modal and a default size but it's possible to customize it anyway with the options parameter.

      penpot.ui.open('Plugin name', 'url', {width: 150, height: 300});
      
    • size: { width: number; height: number } | null
    • resize: (width: number, height: number) => void

      Resizes the plugin UI.

      penpot.ui.resize(300, 400);
      
    • sendMessage: (message: unknown) => void

      Sends a message to the plugin UI.

      this.sendMessage({ type: 'example-type', content: 'data we want to share' });
      
    • onMessage: <T>(callback: (message: T) => void) => void

      This is usually used in the plugin.ts file in order to handle the data sent by our plugin

      penpot.ui.onMessage((message) => {if(message.type === 'example-type' { ...do something })});
      

    Provides access to utility functions and context-specific operations.

    closePlugin: () => void

    Closes the plugin. When this method is called the UI will be closed.

    penpot.closePlugin();
    
    root: Shape | null

    The root shape in the current Penpot context. Requires content:read permission.

    const rootShape = context.root;
    console.log(rootShape);
    currentFile: File | null

    Retrieves file data from the current Penpot context. Requires content:read permission.

    Returns the file data or null if no file is available.

    const fileData = context.currentFile;
    console.log(fileData);
    currentPage: Page | null

    The current page in the Penpot context. Requires content:read permission.

    const currentPage = context.currentPage;
    console.log(currentPage);
    viewport: Viewport

    The viewport settings in the Penpot context.

    const viewportSettings = context.viewport;
    console.log(viewportSettings);
    flags: Flags

    Provides flags to customize the API behavior.

    Context encapsulating the history operations

    const historyContext = context.history;
    console.log(historyContext);

    The library context in the Penpot context, including both local and connected libraries. Requires library:read permission.

    const libraryContext = context.library;
    console.log(libraryContext);

    The fonts context in the Penpot context, providing methods to manage fonts. Requires content:read permission.

    const fontsContext = context.fonts;
    console.log(fontsContext);
    currentUser: User

    The current user in the Penpot context. Requires user:read permission.

    const currentUser = context.currentUser;
    console.log(currentUser);
    activeUsers: ActiveUser[]

    An array of active users in the Penpot context. Requires user:read permission.

    const activeUsers = context.activeUsers;
    console.log(activeUsers);
    theme: Theme

    The current theme (light or dark) in Penpot.

    const currentTheme = context.theme;
    console.log(currentTheme);
    localStorage: LocalStorage

    Access to the localStorage proxy

    selection: Shape[]

    The currently selected shapes in Penpot. Requires content:read permission.

    const selectedShapes = context.selection;
    console.log(selectedShapes);

    Methods

    • Adds an event listener for the specified event type. Subscribing to events requires content:read permission.

      The following are the possible event types:

      • pagechange: event emitted when the current page changes. The callback will receive the new page.
      • shapechange: event emitted when the shape changes. This event requires to send inside the props object the shape that will be observed. For example:
      // Observe the current selected shape
      penpot.on('shapechange', (shape) => console.log(shape.name), { shapeId: penpot.selection[0].id });
      • selectionchange: event emitted when the current selection changes. The callback will receive the list of ids for the new selection
      • themechange: event emitted when the user changes its theme. The callback will receive the new theme (currently: either dark or light)
      • documentsaved: event emitted after the document is saved in the backend.

      Type Parameters

      Parameters

      • type: T

        The event type to listen for.

      • callback: (event: EventsMap[T]) => void

        The callback function to execute when the event is triggered.

      • Optionalprops: { [key: string]: unknown }

        The properties for the current event handler. Only makes sense for specific events.

      Returns symbol

      the listener id that can be used to call off and cancel the listener

      penpot.on('pagechange', () => {...do something}).
      
    • Removes an event listener for the specified event type.

      Parameters

      • listenerId: symbol

        the id returned by the on method when the callback was set

      Returns void

      const listenerId = penpot.on('contentsave', () => console.log("Changed"));
      penpot.off(listenerId);
    • Replaces a specified old color with a new color in the given shapes. Requires content:write permission.

      Parameters

      Returns void

      context.replaceColor(shapes, oldColor, newColor);
      
    • Uploads media to Penpot and retrieves its image data. Requires content:write permission.

      Parameters

      • name: string

        The name of the media.

      • url: string

        The URL of the media to be uploaded.

      Returns Promise<ImageData>

      Returns a promise that resolves to the image data of the uploaded media.

      const imageData = await context.uploadMediaUrl('example', 'https://example.com/image.jpg');
      console.log(imageData);

      // to insert the image in a shape we can do
      const board = penpot.createBoard();
      const shape = penpot.createRectangle();
      board.appendChild(shape);
      shape.fills = [{ fillOpacity: 1, fillImage: imageData }];
    • Uploads media to penpot and retrieves the image data. Requires content:write permission.

      Parameters

      • name: string

        The name of the media.

      • data: Uint8Array

        The image content data

      • mimeType: string

      Returns Promise<ImageData>

      Returns a promise that resolves to the image data of the uploaded media.

      const imageData = await context.uploadMediaData('example', imageData, 'image/jpeg');
      console.log(imageData);
    • Groups the specified shapes. Requires content:write permission.

      Parameters

      • shapes: Shape[]

        An array of shapes to group.

      Returns Group | null

      Returns the newly created group or null if the group could not be created.

      const penpotShapesArray = penpot.selection;
      penpot.group(penpotShapesArray);
    • Ungroups the specified group. Requires content:write permission.

      Parameters

      • group: Group

        The group to ungroup.

      • ...other: Group[]

        Additional groups to ungroup.

      Returns void

      const penpotShapesArray = penpot.selection;
      // We need to make sure that something is selected, and if the selected shape is a group,
      if (selected.length && penpot.utils.types.isGroup(penpotShapesArray[0])) {
      penpot.group(penpotShapesArray[0]);
      }
    • Use this method to create the shape of a rectangle. Requires content:write permission.

      Returns Rectangle

      const shape = penpot.createRectangle();
      // just change the values like this
      shape.name = "Example rectangle";

      // for solid color
      shape.fills = [{ fillColor: "#7EFFF5" }];
      // for linear gradient color
      shape.fills = [{
      fillColorGradient: {
      "type": "linear",
      "startX": 0.5,
      "startY": 0,
      "endX": 0.5,
      "endY": 1,
      "width": 1,
      "stops": [
      {
      "color": "#003ae9",
      "opacity": 1,
      "offset": 0
      },
      {
      "color": "#003ae9",
      "opacity": 0,
      "offset": 1
      }
      ]
      }
      }];
      // for a image fill
      const imageData = await context.uploadMediaUrl('example', 'https://example.com/image.jpg');
      shape.fills = [{ fillOpacity: 1, fillImage: imageData }];

      shape.borderRadius = 8;
      shape.strokes = [
      {
      strokeColor: "#2e3434",
      strokeStyle: "solid",
      strokeWidth: 2,
      strokeAlignment: "center",
      },
      ];
    • Use this method to create a board. This is the first step before anything else, the container. Requires content:write permission. Then you can add a gridlayout, flexlayout or add a shape inside the board. Just a heads-up: board is a board in Penpot UI.

      Returns Board

      const board = penpot.createBoard();

      // to add grid layout
      board.addGridLayout();
      // to add flex layout
      board.addFlexLayout();

      // to create a shape inside the board
      const shape = penpot.createRectangle();
      board.appendChild(shape);
    • Use this method to create the shape of an ellipse. Requires content:write permission.

      Returns Ellipse

      const shape = penpot.createEllipse();
      // just change the values like this
      shape.name = "Example ellipse";

      // for solid color
      shape.fills = [{ fillColor: "#7EFFF5" }];
      // for linear gradient color
      shape.fills = [{
      fillColorGradient: {
      "type": "linear",
      "startX": 0.5,
      "startY": 0,
      "endX": 0.5,
      "endY": 1,
      "width": 1,
      "stops": [
      {
      "color": "#003ae9",
      "opacity": 1,
      "offset": 0
      },
      {
      "color": "#003ae9",
      "opacity": 0,
      "offset": 1
      }
      ]
      }
      }];
      // for an image fill
      const imageData = await context.uploadMediaUrl('example', 'https://example.com/image.jpg');
      shape.fills = [{ fillOpacity: 1, fillImage: imageData }];

      shape.strokes = [
      {
      strokeColor: "#2e3434",
      strokeStyle: "solid",
      strokeWidth: 2,
      strokeAlignment: "center",
      },
      ];
    • Use this method to create a path. Requires content:write permission.

      Returns Path

      const path = penpot.createPath();
      path.name = "My path";

      // for solid color
      path.fills = [{ fillColor: "#7EFFF5" }];
    • Creates a Boolean shape based on the specified boolean operation and shapes. Requires content:write permission.

      Parameters

      • boolType: BooleanType

        The type of boolean operation ('union', 'difference', 'exclude', 'intersection').

      • shapes: Shape[]

        An array of shapes to perform the boolean operation on.

      Returns Boolean | null

      Returns the newly created Boolean shape resulting from the boolean operation.

      const booleanShape = context.createBoolean('union', [shape1, shape2]);
      
    • Creates a Group from an SVG string. Requires content:write permission.

      Parameters

      • svgString: string

        The SVG string representing the shapes to be converted into a group.

      Returns Group | null

      Returns the newly created Group containing the shapes from the SVG.

      const svgGroup = context.createShapeFromSvg('<svg>...</svg>');
      
    • Creates a Group from an SVG string. The SVG can have images and the method returns a Promise because the shape will be available after all images are uploaded. Requires content:write permission.

      Parameters

      • svgString: string

        The SVG string representing the shapes to be converted into a group.

      Returns Promise<Group | null>

      Returns a promise with the newly created Group containing the shapes from the SVG.

      const svgGroup = await context.createShapeFromSvgWithImages('<svg>...</svg>');
      
    • Creates a Text shape with the specified text content. Requires content:write permission.

      Parameters

      • text: string

        The text content for the Text shape.

      Returns Text | null

      Returns the new created shape, if the shape wasn't created can return null.

      const board = penpot.createBoard();
      let text;
      text = penpot.createText();
      // just change the values like this
      text.growType = 'auto-height';
      text.fontFamily = 'Work Sans';
      text.fontSize = '12';
      text.fills = [{fillColor: '#9f05ff', fillOpacity: 1}];
      text.strokes = [{strokeOpacity: 1, strokeStyle: 'solid', strokeWidth: 2, strokeColor: '#deabff', strokeAlignment: 'outer'}];
      board.appendChild(text);
    • Generates markup for the given shapes. Requires content:read permission

      Parameters

      • shapes: Shape[]
      • Optionaloptions: { type?: "html" | "svg" }

      Returns string

      const markup = context.generateMarkup(shapes, { type: 'html' });
      console.log(markup);
    • Generates styles for the given shapes. Requires content:read permission

      Parameters

      • shapes: Shape[]
      • Optionaloptions: { type?: "css"; withPrelude?: boolean; includeChildren?: boolean }

      Returns string

      const styles = context.generateStyle(shapes, { type: 'css' });
      console.log(styles);
    • Generates the fontfaces styles necessaries to render the shapes. Requires content:read permission

      Parameters

      Returns Promise<string>

      const fontfaces = context.generateFontFaces(penpot.selection);
      console.log(fontfaces);
    • Changes the current open page to given page. Requires content:read permission.

      Parameters

      • page: string | Page

        the page to open (a Page object or a page UUID string)

      • OptionalnewWindow: boolean

        if true opens the page in a new window, defaults to false

      Returns void

      context.openPage(page);
      
    • Aligning will move all the selected layers to a position relative to one of them in the horizontal direction.

      Parameters

      • shapes: Shape[]

        to align

      • direction: "center" | "left" | "right"

        where the shapes will be aligned

      Returns void

    • Aligning will move all the selected layers to a position relative to one of them in the vertical direction.

      Parameters

      • shapes: Shape[]

        to align

      • direction: "center" | "top" | "bottom"

        where the shapes will be aligned

      Returns void

    • Converts the shapes into Paths. If the shapes are complex will put together all its paths into one.

      Parameters

      • shapes: Shape[]

        to flatten

      Returns Path[]