Skip to content

Firefox extension (jpm) tutorial

Earlier this week, I wrote my first Firefox extension, a port of the “Millennials to Snake People” Chrome extension, which you might’ve read about in the Huffington Post, or The Verge, or quite a few other outlets. It simply takes the word “millennials” and re-writes it to “snake people.” It also rewrites quite a few other things, such as replacing “digital native” to “parseltongue” – you can read all the replacements in the source.

My writing of the port came out of a Facebook conversation where a friend was disappointed that she couldn’t use the extension because it didn’t exist for Firefox, and I had a port up and running in about an hour.

Now, when people say “I did this in 30 seconds!” I’m pretty skeptical, but it was quite easy to port to Firefox using the jpm tool, but there are a few gotchas I found and thus hello, here’s a blog post.

Build you a Firefox extension

This tutorial is to use jpm, which stands for “jetpack manager”. This only works for versions of Firefox 38+, and at this writing we’re on Firefox … 39 🙂 However, since Firefox (hopefully) updates automatically, people should get on the newer versions and be able to use your plugin, because jpm was wonderfully simple to use once I got it.

1. Install jpm GLOBALLY

I have a bias against the -g flag on npm install.

I prefer to install packages in my project and then use npm to run those binaries by adding a command to the scripts object of package.json.

You CANNOT do this with jpm. It will mess up the packaging of your project. You have to install it globally 🙁 So run npm install -g jpm.

2. Set up your package.json file

This is fairly similar to working with say, NW.js. Your package.json file needs a main attribute and engines. jpm comes with an init command that will make your package.json for you, but you can edit your existing package.json if you made one to include the necessary attributes.

Here’s what a package.json from jpm init looks like:

  "title": "My Jetpack Addon",
  "name": "addon-example",
  "version": "0.0.1",
  "description": "A basic add-on",
  "main": "index.js",
  "author": "",
  "engines": {
    "firefox": ">=38.0a1",
    "fennec": ">=38.0a1"
  "license": "MIT"

3. Tell your main script what to do

The main script for Millennials to Snake people is very simple – it injects JavaScript onto any web page. As far as I could tell, this is what the Chrome extension does.


The longer I program, the more I get paranoid about just how much shit there is out there and how easily we install it without knowing what we have, without reading the source, and even if we have the source, how do we KNOW that the source is the input that generates the output that we install unless we compile it ourselves? And there’s even problems from there!

Anyhow, back to code.

var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");

  include: "*",
  contentScriptFile: data.url("content-script.js")

We load the data and pageMod modules and use those to say “we’re going to modify the page” and use data to get the location of the script I want loaded on any webpage (that matches *, aka, every webpage).

Now that I’ve told the main file to load this JavaScript file, the extension is done.

4. Package it!

This is why you need jpm installed globally. jpm appears to run a command that wraps up your whole folder into a package (.xpi) that Firefox can understand, but it wraps your _whole_ project, including your node_modules folder.

Run jpm xpi and it will generate a .xpi file for you.

5. Submit it!

The submission process is really quite simple. There’s a form, you upload your package, and it runs some automated verifications on it.

The add-on submission process

It’s pretty cool! After that, it’s what you’d expect along the lines of linking to your source (if you’re going to), writing a description, etc.

Once you’ve submitted, while it’s pending review, it will still have its own web page (not sure if that goes away eventually or if the package is rejected?) and people can install the plugin right away.

jpm was quite easy to get going once I figured some of it out (there are about 3+ places to find jpm docs, but this one was my favorite), and maybe this little tutorial will help people port plugins they like (or made!) for Chrome!

9 Replies to “Firefox extension (jpm) tutorial”

  1. Hi Pam

    One question, when setting the path to the icon in package.json file where is the path relative from?

    I have an extension that was sourcing the icon fine until recently. Wondering if it was something I changed or the base of the path has changed in the SDK?


    1. Hey, I didn’t set an icon in the package.json, I set that via the form on the Add-ons store. Don’t know if that helps at all ¯\_(ツ)_/¯

  2. Hi,
    can you tell me how do i add external packages like this “” .. I copied the q.js to the development directory (where i’m developing the add-one) but there should a way to add it using node “npm” can you tell me .. i’m just started last night ,please ..

  3. Hi,

    i am trying out firefox add-on sdk, i am confused about one thing. I am adding some npm packages and they work without giving any errors. But some packages fails giving error message:

    Message: Module `xxx` is not found at resource://gre/modules/commonjs/xxx.js

    Some examples would be ‘net’ and ‘util’ modules.

    Is there a way to make firefox add-ons use at least core nodejs modules (like ‘net’) ?

  4. while running command npm install -g jpm it is not getting installed in my laptop.
    it always shows ‘normalizetree->install \ |——————————-‘. like this

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.