Mattermost Logo
We're hiring!
Edit on GitHub

Best Practices for Plugins - Mattermost

Design Best Practices 

Actions that apply to specific Channels 

  • Recommendation: Have your plugin register the actions to the channel header. This makes it quickly accessible for users and the actions apply on the channel they’re viewing.
  • Example: Zoom meeting posts to a channel

Custom Channel Header Button

You can additionally register a slash command on the server-side to take channel-specific actions.

  • Example: Jira project actions

Slash Command

Actions that apply to specific messages 

  • Recommendation: Have your plugin register a post dropdown menu component with some text, icon and an action function. This adds your action to the “More Actions” post menu dropdown for easy discovery.
  • Examples: Create or attach to Jira issue from a message; copy a message to another channel; report an inappropriate message

Post Dropdown Menu

  • Recommendation: Have your plugin register a file upload method with some text, icon and an action function. This adds your new action to the file upload menu.
  • Examples: File sharing from OneDrive or GDrive; Draw plugin for sketches

File Upload Action

Actions that apply to specific teams 

  • Recommendation: Have your plugin register left sidebar header component with some text, icon and an action function. This adds your action above your team’s channels in the sidebar.
  • Examples: Trello kanban board plugin, GitHub Plugin

left sidebar header

  • Recommendation: Have your plugin register a bottom team sidebar component. This adds icons to the lower left corner of the UI.
  • Examples: GitHub sidebar links with summary of outstanding reviews or unread messages; ServiceNow incident status summary

bottom team sidebar

  • Recommendation: Have your plugin register main menu action with some text, icon for mobile, and an action function. This adds your action to the Main Menu. You can additionally register a slash command on the server-side.
  • Examples: Share feedback plugin in Main Menu; /jira slash commands for quick actions

main menu action

Actions that apply to specific users 

  • Recommendation: Have your plugin register a popover user actions component. This adds your action button to the user profile popover.
  • Examples: Report User plugin; Display extra information about the user from an LDAP server

popover user actions component

Extra information on a user profile 

  • Recommendation: Have your plugin register a popover user attribute component. This adds your custom attributes to the user profile popover.
  • Examples: Custom User Attributes plugin

popover user attribute component

  • Recommendation: Have your plugin add a component to the emoji picker. This is not yet supported, but some work had previously started with the issue currently opened as Help Wanted.
  • Examples: Bitmoji plugin; GIFs via Giphy or Gfycat

Setting up the plugin to properly communicate with the Mattermost server 

Using the Mattermost server’s SiteURL in your web app plugin 

In order to make sure your plugin has full compatibility with your Mattermost server, you should use the server’s configured SiteURL in each API call you send to the server from the webapp. Here’s an example of how to compute the SiteURL:

export const getPluginServerRoute = (state) => {
    const config = getConfig(state);

    let basePath = '';
    if (config && config.SiteURL) {
        basePath = new URL(config.SiteURL).pathname;

        if (basePath && basePath[basePath.length - 1] === '/') {
            basePath = basePath.substr(0, basePath.length - 1);
        }
    }

    return basePath + '/plugins/' + PluginId;
};

Including the server’s CSRF token in your webapp plugin’s requests 

The Mattermost server can be configured to require a CSRF token to be present in HTTP requests sent from the webapp. In order to include the token in each request, you can use the mattermost-redux library’s Client4.getOptions function to add the token to your fetch request. Here’s an example of how to include the CSRF token.

const response = await fetch(url, Client4.getOptions(options));