Create add-in commands with the unified manifest for Microsoft 365

Add-in commands provide an easy way to customize the default Office user interface (UI) with specified UI elements that perform actions. For an introduction to add-in commands, see Add-in commands.

This article describes how to configure the Unified manifest for Microsoft 365 to define add-in commands and how to create the code for function commands.

Tip

Instructions for creating add-in commands with the add-in only manifest are in Create add-in commands with the add-in only manifest.

Note

Office Add-ins that use the unified manifest for Microsoft 365 are directly supported in Office on the web, in new Outlook on Windows, and in Office on Windows connected to a Microsoft 365 subscription, Version 2304 (Build 16320.00000) or later.

When the app package that contains the unified manifest is deployed in AppSource or the Microsoft 365 Admin Center then, if the manifest has a valid "alternateIcons" property, an add-in only manifest is generated from the unified manifest and stored. This add-in only manifest enables the add-in to be installed on platforms that don't directly support the unified manifest, including Office on Mac, Office on mobile, subscription versions of Office on Windows earlier than 2304 (Build 16320.00000), and perpetual versions of Office on Windows.

Starting point and major steps

Both of the tools that create add-in projects with a unified manifest — the Office Yeoman generator and Teams Toolkit — create projects with one or more add-in commands. The only time you won't already have an add-in command is if you are updating an add-in which previously didn't have one.

Two decisions

  • Decide which of two types of add-in commands you need: Task pane or function
  • Decide which kind of UI element you need: button or menu item. Then carry out the steps in the sections and subsections below that correspond to your decisions.

Add a task pane command

The following subsections explain how to include a task pane command in an add-in.

Configure the runtime for the task pane command

  1. Open the unified manifest and find the "extensions.runtimes" array.

  2. Ensure that there is a runtime object that has an "actions.type" property with the value "openPage". This type of runtime opens a task pane.

  3. Ensure that the "requirements.capabilities" array contains an object that specifies a Requirement Set that supports add-in commands. For Outlook the minimum requirement set for add-in commands is Mailbox 1.3.

    Note

    When support for the unified manifest is extended to other Office host applications, the minimum requirement set for add-in commands in those other hosts will be AddinCommands 1.1.

  4. Ensure that the "id" of the runtime object has a descriptive name such as "TaskPaneRuntime".

  5. Ensure that the "code.page" property of the runtime object is set to the URL of the page that should open in the task pane, such as "https://localhost:3000/taskpane.html".

  6. Ensure that the "actions.view" of the runtime object has a name that describes the content of the page that you set in the preceding step, such as "homepage" or "dashboard".

  7. Ensure that the "actions.id" of the runtime object has a descriptive name such as "ShowTaskPane" that indicates what happens when the user selects the add-in command button or menu item.

  8. Set the other properties and subproperties of the runtime object as shown in the following completed example of a runtime object. The "type" and "lifetime" properties are required and in Outlook Add-ins (which is the only host that currently supports the unified manifest) they always have the values shown in this example.

    "runtimes": [
        {
            "requirements": {
                "capabilities": [
                    {
                        "name": "Mailbox",
                        "minVersion": "1.3"
                    }
                ]
            },
            "id": "TaskPaneRuntime",
            "type": "general",
            "code": {
                "page": "https://localhost:3000/taskpane.html"
            },
            "lifetime": "short",
            "actions": [
                {
                    "id": "ShowTaskPane",
                    "type": "openPage",
                    "view": "homepage"
                }
            ]
        }
    ]
    

Configure the UI for the task pane command

  1. Ensure that the extension object for which you configured a runtime has a "ribbons" array property as a peer to the "runtimes" array. There is typically only one extension object in the "extensions" array.

  2. Ensure that the array has an object with array properties named "contexts" and "tabs", as shown in the following example.

    "ribbons": [
        {
            "contexts": [
                // child objects omitted
            ],
            "tabs": [
                // child objects omitted
            ]
        }
    ]
    
  3. Ensure that the "contexts" array has strings that specify the windows or panes in which the UI for the task pane command should appear. For example, "mailRead" means that it will appear in the reading pane or message window when an email message is open, but "mailCompose" means it will appear when a new message or a reply is being composed. The following are the allowable values:

    • "mailRead"
    • "mailCompose"
    • "meetingDetailsOrganizer"
    • "meetingDetailsAttendee"

    The following is an example.

    "contexts": [
        "mailRead"
    ],
    
  4. Ensure that the "tabs" array has an object with a "builtInTabId" string property that is set to the ID of ribbon tab in which you want your task pane command to appear. Also, ensure that there is a "groups" array with at least one object in it. The following is an example.

    "tabs": [
        {
            "builtInTabID": "TabDefault",
            "groups": [
                {
                    // properties omitted
                }
            ]
        }
    ]
    

    Note

    The only allowed value for the "builtInTabID" property is "TabDefault", which in Outlook is either the Home, Message, or Meeting tab. When support for the unified manifest is added to other Office host applications, there will be other possible values.

  5. Ensure that the "groups" array has an object to define the custom control group that will hold your add-in command UI controls. The following is an example. Note the following about this JSON:

    • The "id" must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters.
    • The "label" appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the "label" to 16 characters.
    • One of the "icons" appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs.
    "groups": [
        {
            "id": "msgReadGroup",
            "label": "Contoso Add-in",
            "icons": [
                {
                    "size": 16,
                    "url": "https://localhost:3000/assets/icon-16.png"
                },
                {
                    "size": 32,
                    "url": "https://localhost:3000/assets/icon-32.png"
                },
                {
                    "size": 80,
                    "url": "https://localhost:3000/assets/icon-80.png"
                }
            ],
            "controls": [
                {
                    // properties omitted
                }
            ]
        }
    ]
    
  6. Ensure that there is a control object in the "controls" array for each button or custom menu you want. The following is an example. Note the following about this JSON:

    • The "id", "label", and "icons" properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to a specific button or menu within the group.
    • The "type" property is set to "button" which means that the control will be a ribbon button. You can also configure a task pane command to be run from a menu item. See Menu and menu items.
    • The "supertip.title" (maximum length: 64 characters) and "supertip.description" (maximum length: 128 characters) appear when the cursor is hovering over the button or menu.
    • The "actionId" must be an exact match for the "runtimes.actions.id" that you set in Configure the runtime for the task pane command.
    {
        "id": "msgReadOpenPaneButton",
        "type": "button",
        "label": "Show Task Pane",
        "icons": [
            {
                "size": 16,
                "url": "https://localhost:3000/assets/icon-16.png"
            },
            {
                "size": 32,
                "url": "https://localhost:3000/assets/icon-32.png"
            },
            {
                "size": 80,
                "url": "https://localhost:3000/assets/icon-80.png"
            }
        ],
        "supertip": {
            "title": "Show Contoso Task Pane",
            "description": "Opens the Contoso task pane."
        },
        "actionId": "ShowTaskPane"
    }
    

You've now completed adding a task pane command to your add-in. Sideload and test it.

Add a function command

The following subsections explain how to include a function command in an add-in.

Create the code for the function command

  1. Ensure that your source code includes a JavaScript or Typescript file with the function that you want to run with your function command. The following is an example. Since this article is about creating add-in commands, and not about teaching the Office JavaScript Library, we provide it with minimal comments, but do note the following:

    • For purposes of this article, the file is named commands.js.
    • The function will cause a small notification to appear on an open email message with the text "Action performed".
    • Like all code that call APIs in the Office JavaScript Library, it must begin by initializing the library. It does this by calling Office.onReady.
    • The last thing the code calls is Office.actions.associate to tell Office which function in the file should be run when the UI for your function command is invoked. The function maps the function name to an action ID that you configure in the manifest in a later step. If you define multiple function commands in the same file, your code must call associate for each one.
    • The function must take a parameter of type Office.AddinCommands.Event. The last line of the function must call event.completed.
    Office.onReady(function() {
    // Add any initialization code here.
    });
    
    function setNotification(event) {
    const message = {
        type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,
        message: "Performed action.",
        icon: "Icon.80x80",
        persistent: true,
    };
    
    // Show a notification message.
    Office.context.mailbox.item.notificationMessages.replaceAsync("ActionPerformanceNotification", message);
    
    // Be sure to indicate when the add-in command function is complete.
    event.completed();
    }
    
    // Map the function to the action ID in the manifest.
    Office.actions.associate("SetNotification", setNotification);
    
  2. Ensure that your source code includes an HTML file that is configured to load the function file you created. The following is an example. Note the following about this JSON:

    • For purposes of this article, the file is named commands.html.

    • The <body> element is empty because the file has no UI. Its only purpose is to load JavaScript files.

    • The Office JavaScript Library and the commands.js file that you created in the preceding step is explicitly loaded.

      Note

      It's common in Office Add-in development to use tools like webpack and its plugins to automatically inject <script> tags into HTML files at build time. If you use such a tool, you shouldn't include any <script> tags in your source file that are going to be inserted by the tool.

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    
            <!-- Office JavaScript Library -->
            <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
            <!-- Function command file -->
            <script src="commands.js" type="text/javascript"></script>
        </head>
        <body>
        </body>
    </html>
    

Configure the runtime for the function command

  1. Open the unified manifest and find the "extensions.runtimes" array.

  2. Ensure that there is a runtime object that has a "actions.type" property with the value "executeFunction".

  3. Ensure that the "requirements.capabilities" array contains objects that specify any Requirement Sets that are needed to support the APIs add-in commands. For Outlook, the minimum requirement set for add-in commands is Mailbox 1.3. But if your function command calls that API that is part of later Mailbox requirement set, such as Mailbox 1.5, then you need to specify the later version (e.g., "1.5") as the "minVersion" value.

    Note

    When support for the unified manifest is extended to other Office host applications, the minimum requirement set for add-in commands in those other hosts will be AddinCommands 1.1.

  4. Ensure that the "id" of the runtime object has a descriptive name such as "CommandsRuntime".

  5. Ensure that the "code.page" property of the runtime object is set to the URL of the UI-less HTML page that loads your function file, such as "https://localhost:3000/commands.html".

  6. Ensure that the "actions.id" of the runtime object has a descriptive name such as "SetNotification" that indicates what happens when the user selects the add-in command button or menu item.

    Important

    The value of "actions.id" must exactly match the first parameter of the call to Office.actions.associate in the function file.

  7. Set the other properties and subproperties of the runtime object as shown in the following completed example of a runtime object. The "type" and "lifetime" properties are required and they always have the values shown in Outlook add-ins, which is the only host that currently supports the unified manifest.

    "runtimes": [
        {
            "id": "CommandsRuntime",
            "type": "general",
            "code": {
                "page": "https://localhost:3000/commands.html"
            },
            "lifetime": "short",
            "actions": [
                {
                    "id": "SetNotification",
                    "type": "executeFunction",
                }
            ]
        }       
    ]
    

Configure the UI for the function command

  1. Ensure that the extension object for which you configured a runtime has a "ribbons" array property as a peer to the "runtimes" array. There is typically only one extension object in the "extensions" array.

  2. Ensure that the array has an object with array properties named "contexts" and "tabs", as shown in the following example.

    "ribbons": [
        {
            "contexts": [
                // child objects omitted
            ],
            "tabs": [
                // child objects omitted
            ]
        }
    ]
    
  3. Ensure that the "contexts" array has strings that specify the windows or panes in which the UI for the function command should appear. For example, "mailRead" means that it will appear in the reading pane or message window when an email message is open, but "mailCompose" means it will appear when a new message or a reply is being composed. The following are the allowable values:

    • mailRead
    • mailCompose
    • meetingDetailsOrganizer
    • meetingDetailsAttendee

    The following is an example.

    "contexts": [
        "mailRead"
    ],
    
  4. Ensure that the "tabs" array has an object with a "builtInTabId" string property that is set to the ID of ribbon tab in which you want your function command to appear and a "groups" array with at least one object in it. The following is an example.

    "tabs": [
        {
            "builtInTabID": "TabDefault",
            "groups": [
                {
                    // properties omitted
                }
            ]
        }
    ]
    

    Note

    The only allowed value for the "builtInTabID" property is "TabDefault", which in Outlook is either the Home, Message, or Meeting tab. When support for the unified manifest is added to other Office host applications, there will be other possible values.

  5. Ensure that the "groups" array has an object to define the custom control group that will hold your add-in command UI controls. The following is an example. Note the following about this JSON:

    • The "id" must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters.
    • The "label" appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the "label" to 16 characters.
    • One of the "icons" appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs.
    "groups": [
        {
            "id": "msgReadGroup",
            "label": "Contoso Add-in",
            "icons": [
                {
                    "size": 16,
                    "url": "https://localhost:3000/assets/icon-16.png"
                },
                {
                    "size": 32,
                    "url": "https://localhost:3000/assets/icon-32.png"
                },
                {
                    "size": 80,
                    "url": "https://localhost:3000/assets/icon-80.png"
                }
            ],
            "controls": [
                {
                    // properties omitted
                }
            ]
        }
    ]
    
  6. Ensure that there is a control object in the "controls" array for each button or custom menu you want. The following is an example. Note the following about this JSON:

    • The "id", "label", and "icons" properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to a specific button or menu within the group.
    • The "type" property is set to "button" which means that the control will be a ribbon button. You can also configure a function command to be run from a menu item. See Menu and menu items.
    • The "supertip.title" (maximum length: 64 characters) and "supertip.description" (maximum length: 128 characters) appear when the cursor is hovering over the button or menu.
    • The "actionId" must be an exact match for the "runtime.actions.id" that you set in Configure the runtime for the function command.
    {
        "id": "msgReadSetNotificationButton",
        "type": "button",
        "label": "Set Notification",
        "icons": [
            {
                "size": 16,
                "url": "https://localhost:3000/assets/icon-16.png"
            },
            {
                "size": 32,
                "url": "https://localhost:3000/assets/icon-32.png"
            },
            {
                "size": 80,
                "url": "https://localhost:3000/assets/icon-80.png"
            }
        ],
        "supertip": {
            "title": "Set Notification",
            "description": "Displays a notification message on the current message."
        },
        "actionId": "SetNotification"
    }
    

You've now completed adding a function command to your add-in. Sideload and test it.

In addition to custom buttons, you can also add custom drop down menus to the Office ribbon. This section explains how by using an example with two menu items. One invokes a task pane command. The other invokes a function command.

Configure the runtimes and code

Carry out the steps of the following sections:

Configure the UI for the menu

  1. Ensure that the extension object for which you configured a runtime has a "ribbons" array property as a peer to the "runtimes" array. There is typically only one extension object in the "extensions" array.

  2. Ensure that the array has an object with array properties named "contexts" and "tabs", as shown in the following example.

    "ribbons": [
        {
            "contexts": [
                // child objects omitted
            ],
            "tabs": [
                // child objects omitted
            ]
        }
    ]
    
  3. Ensure that the "contexts" array has strings that specify the windows or panes in which the menu should appear on the ribbon. For example, "mailRead" means that it will appear in the reading pane or message window when an email message is open, but "mailCompose" means it will appear when a new message or a reply is being composed. The following are the allowable values:

    • mailRead
    • mailCompose
    • meetingDetailsOrganizer
    • meetingDetailsAttendee

    The following is an example.

    "contexts": [
        "mailRead"
    ],
    
  4. Ensure that the "tabs" array has an object with a "builtInTabId" string property that is set to the ID of ribbon tab in which you want your task pane command to appear and a "groups" array with at least one object in it. The following is an example.

    "tabs": [
        {
            "builtInTabID": "TabDefault",
            "groups": [
                {
                    // properties omitted
                }
            ]
        }
    ]
    

    Note

    The only allowed value for the "builtInTabID" property is "TabDefault", which in Outlook is either the Home, Message, or Meeting tab. When support for the unified manifest is added to other Office host applications, there will be other possible values.

  5. Ensure that the "groups" array has an object to define the custom control group that will hold your drop down menu control. The following is an example. Note the following about this JSON:

    • The "id" must be unique across all groups in all ribbon objects in the manifest. Maximum length is 64 characters.
    • The "label" appears on the group on the ribbon. Although its maximum length is 64 characters, to ensure that the control group fits correctly in the ribbon, we recommend that you limit the "label" to 16 characters.
    • One of the "icons" appears on the group only if the Office application window, and hence the ribbon, has been sized by the user too small for any of the controls in the group to appear. Office decides when to use one of these icons and which one to use based on the size of the window and the resolution of the device. You cannot control this. You must provide image files for 16, 32, and 80 pixels, while five other sizes are also supported (20, 24, 40, 48, and 64 pixels). You must use Secure Sockets Layer (SSL) for all URLs.
    "groups": [
        {
            "id": "msgReadGroup",
            "label": "Contoso Add-in",
            "icons": [
                {
                    "size": 16,
                    "url": "https://localhost:3000/assets/icon-16.png"
                },
                {
                    "size": 32,
                    "url": "https://localhost:3000/assets/icon-32.png"
                },
                {
                    "size": 80,
                    "url": "https://localhost:3000/assets/icon-80.png"
                }
            ],
            "controls": [
                {
                    // properties omitted
                }
            ]
        }
    ]
    
  6. Ensure that there is a control object in the "controls" array. The following is an example. Note the following about this JSON:

    • The "id", "label", and "icons" properties have the same purpose and the same restrictions as the corresponding properties of a group object, except that they apply to the drop down menu within the group.
    • The "type" property is set to "menu" which means that the control will be a drop down menu.
    • The "supertip.title" (maximum length: 64 characters) and "supertip.description" (maximum length: 128 characters) appear when the cursor is hovering over the menu.
    • The "items" property contains the JSON for the two menu options. The values are added in later steps.
    {
        "id": "msgReadMenu",
        "type": "menu",
        "label": "Contoso Menu",
        "icons": [
            {
                "size": 16,
                "url": "https://localhost:3000/assets/icon-16.png"
            },
            {
                "size": 32,
                "url": "https://localhost:3000/assets/icon-32.png"
            },
            {
                "size": 80,
                "url": "https://localhost:3000/assets/icon-80.png"
            }
        ],
        "supertip": {
            "title": "Show Contoso Actions",
            "description": "Opens the Contoso menu."
        },
        "items": [
            {
                "id": "",
                "type": "",
                "label": "",
                "supertip": {},
                "actionId": ""
            },
            {
                "id": "",
                "type": "",
                "label": "",
                "supertip": {},
                "actionId": ""
            }
        ]
    }
    
  7. The first item shows a task pane. The following is an example. Note the following about this code:

    • The "id", "label", and "supertip" properties have the same purpose and the same restrictions as the corresponding properties of the parent menu object, except that they apply to just this menu option.
    • The "icons" property is optional for menu items and there isn't one in this example. If you include one, it has the same purposes and restrictions as the "icons" property of the parent menu, except that the icon appears on the menu item beside the label.
    • The "type" property is set to "menuItem".
    • The "actionId" must be an exact match for the "runtimes.actions.id" that you set in Configure the runtime for the task pane command.
    {
        "id": "msgReadOpenPaneMenuItem",
        "type": "menuItem",
        "label": "Show Task Pane",
        "supertip": {
            "title": "Show Contoso Task Pane",
            "description": "Opens the Contoso task pane."
        },
        "actionId": "ShowTaskPane"
    },
    
  8. The second item runs a function command. The following is an example. Note the following about this code:

    {
        "id": "msgReadSetNotificationMenuItem",
        "type": "menuItem",
        "label": "Set Notification",
        "supertip": {
            "title": "Set Notification",
            "description": "Displays a notification message on the current message."
        },
        "actionId": "SetNotification"
    }
    

You've now completed adding a menu to your add-in. Sideload and test it.

See also