LogoLogo
  • About Thunderbird
  • Contributing to Thunderbird
    • Getting Started Contributing
    • Setting Up A Build Environment
    • Building Thunderbird
      • Windows Build Prerequisites
      • Linux Build Prerequisites
      • macOS Build Prerequisites
      • Artifact Builds
    • Codebase Overview
      • Account Configuration
      • Address Book
      • Chat Core
        • Notifications
        • Message Styles
        • Keyboard shortcuts
        • Chat Core Protocols
        • Contacts
      • Mail Front-End
    • Tutorials and Examples
      • Hello World Example
      • Thunderbird Live Development Videos
    • Fixing a Bug
      • Bug Triaging 101
        • Bug Status Classicification
        • Bug Types
        • Garbage Collection
        • Narrow the Scope
      • Using Mercurial Bookmarks
      • Using Mercurial Queues
      • Lint and Format Code
      • Using ESLint to Format Javascript Code
      • Try Server
      • Landing a Patch
      • Care and Feeding of the Tree
    • Testing
      • Running Tests
      • Adding Tests
      • Writing Mochitest Tests
  • Planning
    • Roadmap
    • Android Roadmap
    • Supported Standards
  • Add-on Development
    • Introduction
    • What's new?
      • Manifest Version 3
    • A "Hello World" Extension Tutorial
      • Using WebExtension APIs
      • Using a Background Page
      • Using Content Scripts
    • A Guide to Extensions
      • Supported Manifest Keys
      • Supported UI Elements
      • Supported WebExtension APIs
      • Thunderbird's WebExtension API Documentation
      • Thunderbird WebExtension Examples
      • Introducing Experiments
    • A Guide to Themes
    • Developer Community
    • Documentation & Resources
      • Tips and Tricks
    • Add-on Update Guides
      • Update for Thunderbird 128
      • Update for Thunderbird 115
        • Adapt to Changes in Thunderbird 103-115
      • Update for Thunderbird 102
        • Adapt to Changes in Thunderbird 92-102
      • Update for Thunderbird 91
        • Adapt to Changes in Thunderbird 79-91
      • Update for Thunderbird 78
        • Adapt to Changes in Thunderbird 69-78
      • Update for Thunderbird 68
        • Adapt to Changes in Thunderbird 61-68
      • How to convert legacy extensions?
        • Convert wrapped WebExtensions to modern WebExtensions
        • Convert legacy WebExtensions to modern WebExtensions
        • Convert legacy overlay extension to legacy WebExtension
        • Convert legacy bootstrapped extension to legacy WebExtension
  • Releases
    • Thunderbird Channels
    • Release Cadence
    • Uplifting Fixes
    • Feature Flags
    • Tracking Fixes for Releases
    • Contributing to Release Notes
Powered by GitBook
On this page
  • Creating a manifest.json
  • Using a browser_action
  • popup.html
  • popup.js
  • popup.css
  • Testing the Extension
  • Installing
  • Opening the Error Console
  • Trying it Out
  • Creating the add-on file

Was this helpful?

Edit on GitHub
Export as PDF
  1. Add-on Development

A "Hello World" Extension Tutorial

All the information you need to get your first Thunderbird extension up and running.

PreviousManifest Version 3NextUsing WebExtension APIs

Last updated 7 months ago

Was this helpful?

In the first part of this tutorial, we will create a very simple extension, which adds a "Hello World" button to Thunderbird's main toolbar and a click on it will show a Hello, World! popup.

Creating a manifest.json

First, we create an empty hello-world project folder for our extension and navigate to it.

Extensions require a manifest.json file that tells Thunderbird a few basic information about the add-on. Let's place the following manifest.json file directly in the hello-world project folder.

manifest.json
{
    "manifest_version": 2,
    "name": "Hello World Example",
    "description": "A basic Hello World example extension!",
    "version": "1.0",
    "author": "Thunderbird Team",
    "browser_specific_settings": {
        "gecko": {
            "id": "helloworld@yoursite.com",
            "strict_min_version": "128.0"
        }
    },
    "browser_action": {
        "default_popup": "mainPopup/popup.html",
        "default_title": "Hello World",
        "default_icon": "images/internet-32px.png"
    },
    "icons": {
        "64": "images/internet.png",
        "32": "images/internet-32px.png",
        "16": "images/internet-16px.png"
    }
}

Using a browser_action

The above manifest includes the definition for a browser_action. That is the button we want to add to Thunderbird's main toolbar. The reference to a browser in its name is inherited from the Firefox Browser.

popup.html

The location of the HTML file loaded by the popup of our browser_action is defined in the browser_action.default_popup key. Let's create a mainPopup directory in the hello-world project folder for everything related to that popup and start with the following popup.html .

popup.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Hello World</title>
    <link rel="stylesheet" type="text/css" media="screen" href="popup.css">
</head>

<body>
    <div class="popup-page">
        Hello, World!
    </div>
    <script type="module" src="popup.js"></script>
</body>

</html>

The script tag to include popup.js is setting type="module", which loads the script as a top level ES6 module. This enables the script to use the await keyword in file scope code and to load other ES6 modules.

We will not use these features in this step of the tutorial, but we still use the modern ES6 module approach here to introduce it as a standard programming practice.

popup.js

We're going to create the following file called popup.js and place it in the same folder as the popup.html file.

popup.js
// Below is what we'll log to the console.

console.log('Hello, World! - from popup.js');

What our little script does is sending a message to the console each time we click on our "Hello World" toolbar button. We'll take a look at that in a moment when we try out our add-on. The first line is just a comment, so we can remember what our code is doing.

popup.css

Now we want to create the CSS file referenced in our HTML file. We'll call it popup.css. This is just for decoration of the page, we'll put it in the same folder as the popup.html file.

popup.css
.popup-page {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    font-weight: bold;
    height: 60px;
    padding: 10px;
}

Testing the Extension

hello-world/
  ├── manifest.json
  ├── images/
      ├── internet.png
      ├── internet-16px.png
      └── internet-32px.png
  └── mainPopup/
      ├── popup.css
      ├── popup.html
      └── popup.js

Installing

To install the add-on we created, we are going to load it temporarily. Let's start by opening the Add-ons Manager:

This will open up the Add-ons Manager, make sure "Extensions" is selected on the left-hand side and click the gear to select "Debug Add-ons".

Click on the "Load Temporary Add-on..." button:

Select the manifest.json file from within our hello-world project folder:

This should install the add-on for this session only:

Opening the Error Console

Our extension will print messages to the error console using console.log(), so we need to open the error console first, in order to see those log entries. Hit the "Inspect" button under the add-on's listing (pictured above), this will open the Developer Tools window.

Make sure the "Console" tab is selected in the Developer Tools. Click the "Persist Logs" checkbox in the top right-hand corner of the Developer Tools window so that we can see the output from the add-on after we've interacted with it (otherwise, it only shows output as it is happening).

Trying it Out

Now we can give our new add-on a whirl. Head to the home tab and find the new "Hello World" button in the main toolbar in the top right-hand corner. Click on it to see a popup with the Hello, World! message.

Now, if you look at the Developer Tools window, you should see something like the following in the console:

Creating the add-on file

Once the add-on is ready for release or if you want to share it with others, you need to create a single add-on file. Simply zip the content of the add-on's project folder and use the xpi file extension. That file can be installed from the gear menu in the Thunderbird Add-ons Manager.

You can grab the icons we use for this example from the . Make sure to create an images directory in the hello-world project folder for them.

The allowed keys for the browser_action button are described in our . We define a popup HTML page, which should be loaded if the button is clicked, a title and an icon.

The default disallows JavaScript placed directly in <script> tags and inline event handlers like onclick. Place all JavaScript code into a separate file (like popup.js in this example) and use instead of inline event handlers.

First, let's double-check that we created and have them in the right places:

example repository
API documentation
content security policy
addEventListener()
the correct files