Life on Planet Firefox
Writing apps for the new Firefox OS phones
ByCooking up an app for the Firefox OS is in no way difficult. All you need is a good measure of HTML and a dash of CSS. A few drops of JavaScript will bring it all to life.
Although the smartphone software market seems polarized between iOS and Android these days, other contenders out there are filling out or creating their own niches. Mozilla, for example is aiming at a modest part of the market share: the very low end phones. That doesn’t mean FirefoxOS phones are bad. Quite the contrary. The few models I have seen so far are perfectly adequate considering their price tag. Plus, they are real smartphones, with a great potential market in developing countries or just for those who feel that spending more than 100 bucks on a phone is a waste, which it is for most people.
Firefox OS can do most, if not all, of what you can do in Android and iOS, and it’s easy to make apps for it. If you can write HTML5, CSS3, and JavaScript to create a web app, you’ve already mastered 90% of what you need to know.
Even if you are bit rusty with your web technologies, I’ll try to show you in this article how to get from idea to marketplace quickly and easily.
The Hardware
It definitely helps to have a real device on which to test your software. The good news is that Firefox OS handsets are cheap, and you can pick up a ZTE Open for less than US$ 80 (or for as little as EUR 39 if you live in Spain). However, even if you don’t have a physical device, you can run, test, and debug your app in the Simulator.
The Simulator
The Simulator is a Firefox (as in the Firefox browser) plugin that allows you to run a Firefox OS emulator (Figure 1) and test your apps. Once installed, visit Tools | Web Developer | Firefox OS Simulator.
The simulator comprises two parts: the dashboard and the emulator proper. At the top of the dashboard, from left to right, you can run the emulator, see a list of apps you have installed in the emulator, add a directory, or add a URL that contains the manifest of the Firefox OS app (more about that later). On the far right, within the list of apps, you can Refresh individual apps on the emulator when you make changes, and Connect Firefox’s integrated web development tools to the emulator to debug your JavaScript code, HTML, or CSS.
If you have a Firefox OS handset, you can also Push your app to it. To do this, you have to configure your phone by going to Settings on your device; then, scroll down and choose Device Information | More Information | Developer and check the Remote Debugging option. Now connect your handset to your computer using the USB data cable, and ... Presto! Your device pops up on the dashboard.
The emulator itself, apart from simulating a handset, has two menus at the top. File allows you to Quit the emulator, and App allows you to Refresh an installed app.
Note that the Firefox OS emulator is still in a very early stage of development; hence, it’s slow and resource hungry. It might also behave weirdly, lock up, or show results inconsistent with what you would see on a real phone, which can be annoying and kind of defeats the purpose of an emulator in the first place. However, unless you have a real Firefox OS device, it’s the best you can do.
The Assets
Before you start writing your app, you will want to grab the assets Mozilla has to offer, which you can use freely in your project. Not only will this make your life easier, but it helps maintain a consistent look and feel across all apps on the system.
The bag of goodies you really want to get is the Building blocks package, which includes all the fonts, icons, images, and CSS files (which in turn include styles for buttons, the status bar, etc.) you need to design an app. Plus, you’ll find plenty of examples that can help you see how these resources are used, as well as sample JavaScript code to power the whole lot. The Mozilla Building Blocks page offers comprehensive advice and even more examples to help you use the assets.
The Package
Another thing you need to do (otherwise you won’t be able to run your app on the Simulator or handset) is write the manifest. The manifest is a JSON summary that contains all the details of your app so Firefox OS can run it correctly.
The manifest.webapp file must be at the root of the app. The example in Listing 1 gives you an idea of what the file should contain.
Listing 1: Manifest.webapp for Life
01 { 02 "version": "0.1", 03 "name": "Life", 04 "description": "Conway's Game of Life", 05 "launch_path": "/index.html", 06 "icons": { 07 "60": "/img/LifeIcon60x60.png", 08 "128": "/img/LifeIcon128x128.png" 09 }, 10 "developer": { 11 "name": "Paul Brown", 12 "url": "http://www.linux-magazine.com" 13 }, 14 "installs_allowed_from": ["*"], 15 "default_locale": "en", 16 "orientation": ["portrait"] 17 }
Most of the fields are pretty self-explanatory; however, note in the icons section that you will have an icon 60x60 pixels and another 128x128 pixels. The handset uses the 60-pixel icon in its list of apps (Figure 2); the 128-pixel icon comes into play if you want to distribute your app through the Firefox OS marketplace, which I talk about a bit later. A handy guide shows you how to create a thematically consistent icon.
The orientation field in line 16 allows you to decide how your app will be shown on the device: portrait, landscape, portrait-primary, landscape-primary, portrait-secondary, or landscape-secondary. For example, if you specify portrait-primary in your manifest file, your app appears in portrait mode with the top of your UI at the top of the device, and the bottom at the bottom of the device’s display. The portrait-secondary option flips the orientation 180 degrees. By using portrait, your app will flip in portrait mode depending on how the device is held, but it will not rotate 90 degrees when you turn the device on its side.
Combining these options, for example,
“orientation”: [“portrait”, “landscape-secondary”]
allows your app to flip either way in portrait mode (right way up or upside down) and will display correctly on one of its sides, but not the other. The Mozilla Developer Network has a good tutorial on how to write a good manifest.
The Software
In my example project, I’ll be implementing Conway’s Game of Life (GoL), probably one of the most popular and simplest life simulators. If you are unfamiliar with GoL, check out the “The Game of Life” box.
If you have had any experience with JavaScript in the last few years, you will have witnessed the rise of JavaScript libraries, none of which is more popular than jQuery. jQuery has simplified the creation of dynamic web programming to the point of forcing Flash nearly to extinction (which, by the way, is an excellent thing). jCanvas is an extension of JQuery that makes programming on a canvas object much easier.
In my implementation (Listing 2), I will use the HTML5 canvas object as a playing board (line 17).

To help, I will use jQuery and jCanvas (lines 7 and 8). In lines 150-159, you can see how easy it is draw a cell on the canvas. Note that because I consider a single pixel too tiny, I decided to go with a 2x2 box for the cells. With a 300x300 canvas, the playing field can hold 150x150 cells.
Listing 2: Life for Firefox OS (index.html)
001 <!DOCTYPE html> 002 <html> 003 <head> 004 <title>Game of Life</title> 005 006 <!-- Include external JavaScript --> 007 <script src="js/jquery-2.0.3.js"></script> 008 <script src="js/jcanvas.min.js"></script> 009 010 <!-- Style Sheets --> 011 <link rel="stylesheet" href="style/buttons.css"> 012 <link rel="stylesheet" href="style/status.css"> 013 014 </head> 015 016 <body> 017 <canvas width="300" height="300" style="border:1px solid black"></canvas> 018 <button id="operate">Start</button> 019 <button id="reset">Clear</button> 020 021 <!-- Status Bar --> 022 <section role="status" id="cell-counter" hidden> 023 <p>Cells: <strong>0</strong></p> 024 </section> 025 026 <script> 027 028 var CULTURE=[]; 029 var BUTTON_TEXT="Start"; 030 var RUN; 031 032 /************* 033 * 034 * STATUS BAR 035 * 036 */ 037 038 $("canvas").dblclick(function(e) 039 { 040 $("#cell-counter" ).html( "<p>Cells: <strong>"+ CULTURE.length + "</strong></p>" ); 041 $("#cell-counter").fadeIn().delay(2000).fadeOut('slow'); 042 }); 043 044 /************* 045 * 046 * EDIT MODE 047 * 048 */ 049 050 // Check position of pointer on canvas 051 $("canvas").click(function(e) 052 { 053 var canvas_pos = $("canvas").position(); 054 var cellCoords= [Math.floor((e.pageX-canvas_pos.left)/2), Math.floor((e.pageY-canvas_pos.top)/2)] 055 editCell(cellCoords); 056 }); 057 058 059 function editCell(coords) 060 { 061 var stringCoords='"'+ coords[0] + ',' + coords[1] +'"' 062 if($.inArray(stringCoords, CULTURE) === -1) 063 { 064 CULTURE.push(stringCoords); 065 drawPixel(coords); 066 } 067 else 068 { 069 CULTURE.splice(CULTURE.indexOf(stringCoords),1); 070 erasePixel(coords); 071 } 072 073 } 074 075 /************* 076 * 077 * RUN MODE 078 * 079 */ 080 081 function mainLoop() 082 { 083 // This is the temporary array where we store 084 // the next culture 085 var nextCulture = []; 086 087 // Here we store the cells we have already examined 088 var cellExamined = []; 089 090 $.each(CULTURE, function(i, point) 091 { 092 var newX= convrt2Coords(point)[0]; 093 var newY= convrt2Coords(point)[1]; 094 095 // nbx and nby are the cells we have to examine since 096 // they are neighbouring active cells 097 098 for (nbx=newX-1;nbx<newX+2;nbx++) 099 { 100 for (nby=newY-1; nby<newY+2; nby++) 101 { 102 // But we'll only examine them if we haven't done so already 103 // (and they are not off the edge of the board). 104 if ($.inArray('"'+ nbx + ',' + nby +'"', cellExamined)===-1) 105 { 106 cellExamined.push('"'+ nbx + ',' + nby +'"'); 107 if(nbx>=0 && nbx<=300 && nby>=0 && nby<=300) 108 { 109 // Check neighbours 110 var neighbours=0; 111 for (ncx=nbx-1; ncx<nbx+2; ncx++) 112 { 113 for (ncy=nby-1; ncy<nby+2; ncy++) 114 { 115 if (!(ncx==nbx && ncy==nby)) 116 { 117 if($.inArray('"'+ ncx + ',' + ncy +'"', CULTURE)!==-1) neighbours++; 118 } 119 } 120 } 121 122 switch(neighbours) 123 { 124 case (3): 125 // If number of neighbours is 3, a cell is born 126 nextCulture.push('"' + nbx + ',' + nby + '"'); 127 case (2): 128 // If number of neighbours 2, leave alone 129 if ($.inArray('"' + nbx + ',' + nby + '"', CULTURE)!==-1) 130 { 131 nextCulture.push('"' + nbx + ',' + nby + '"'); 132 } 133 } 134 } 135 } 136 } 137 } 138 }); 139 140 CULTURE = nextCulture; 141 drawPlayingField(); 142 } 143 144 /************* 145 * 146 * MISC STUFF 147 * 148 */ 149 150 function drawPixel(coords) 151 { 152 $("canvas").drawRect 153 ({ 154 fillStyle:"rgba(0, 0, 0, 1)", 155 x: coords[0]*2, y: coords[1]*2, 156 width: 2, 157 height: 2 158 }); 159 } 160 161 function erasePixel(coords) 162 { 163 $("canvas").clearCanvas 164 ({ 165 x: coords[0]*2, y: coords[1]*2, 166 width: 2, 167 height: 2 168 }); 169 } 170 171 function drawPlayingField() 172 { 173 $("canvas").clearCanvas(); 174 //Loop thru coors and draw pixels 175 $.each(CULTURE, function(i, point) 176 { 177 drawPixel(convrt2Coords(point)); 178 }); 179 } 180 181 function convrt2Coords(coords) 182 { 183 var intCoords=[parseInt(coords.split(",")[0].slice(1)), parseInt(coords.split(",")[1])]; 184 return intCoords; 185 } 186 187 /************* 188 * 189 * BUTTONS 190 * 191 */ 192 193 $("#operate").click(function() 194 { 195 $(this).toggleClass("active"); 196 197 if (BUTTON_TEXT=="Start") 198 { 199 if (CULTURE[0]) 200 { 201 BUTTON_TEXT="Stop"; 202 $(this).text(BUTTON_TEXT); 203 RUN=setInterval(mainLoop,1); 204 } 205 } 206 else 207 { 208 BUTTON_TEXT="Start"; 209 clearInterval(RUN); 210 $(this).text(BUTTON_TEXT); 211 } 212 }); 213 214 $("#reset").click(function() 215 { 216 BUTTON_TEXT="Start"; 217 clearInterval(RUN); 218 $("canvas").clearCanvas(); 219 CULTURE=[]; 220 }); 221 222 </script> 223 </body> 224 </html>
The code in Listing 2 also uses jQuery extensively to refer to and manipulate some of the elements, such as the status bar, which will slowly appear and then fade out if you tap the playing field twice (the equivalent of a double-click) and show you how many live cells are in the current generation (lines 38-42). Speaking of the status bar, the HTML to include it in your app is very simple (lines 22-24), although you will have to modify the status.css file to use the clean, elegant font provided by Mozilla (see Listing 3).
Listing 3: Modified status.css File
01 /* ---------------------------------- 02 * Status 03 * ---------------------------------- */ 04 05 @font-face 06 { 07 font-family: FiraSans; 08 src: url('/fonts/FiraSans/FiraSans-Regular.ttf'); 09 } 10 11 @font-face 12 { 13 font-family: FiraSans; 14 src: url('/fonts/FiraSans/FiraSans-Bold.ttf'); 15 font-weight:bold; 16 } 17 18 section[role="status"] { 19 background: rgba(64,64,64,1) url(status/images/ui/pattern.png) repeat left top; 20 overflow: hidden; 21 position: absolute; 22 z-index: 100; 23 left: 0; 24 right: 0; 25 bottom: 0; 26 color: #fff; 27 text-align: left; 28 } 29 30 section[role="status"] p { 31 font-family: FiraSans; 32 font-size: 1.8rem; 33 font-weight: normal; 34 line-height: 2.2rem; 35 margin: 1rem 3rem; 36 padding: 0; 37 text-align: left; 38 } 39 40 section[role="status"] p strong { 41 font-family: FiraSans, bold; 42 color: rgb(9, 149, 176); 43 }
The Start/Stop and Clear buttons are included in the user interface in lines 18 and 19 (Listing 2), respectively. When you click Start or Stop, you either start the mainLoop function (which runs the simulation) or stop it (lines 193-212).
The Clear button uses a jCanvas function to erase all pixels from the canvas and empties the CULTURE array that holds the coordinates of the live cells in the current generation (lines 214-220).
The biggest chunk of code (lines 81-142) is the mainloop mentioned above. This section calculates the next generation based on the current generation stored in CULTURE. The most obvious way of doing this is to loop over every cell in the 150x150 array and examine each of the eight possible neighbors, changing their state as necessary. However, this process is a very slow, very inefficient way of doing things.
Instead, the CULTURE array contains the coordinates of only the live cells in the current generation. By only examining live cells and their immediate neighbors, you can skip enormous empty chunks of the playing board. All the white space above, between and below the live cells is ignored (lines 90-138). The jQuery $.each() loops over all the elements in CULTURE and avoids examining a cell twice by storing it in the cellExamined array (line 106) and skipping it if it’s encountered again (line 104). The new cell configuration is gradually stored in the nextCulture array.
Note that the cells are stored as strings, so cell (130, 45) is stored as [130, 45]. Arrays in JavaScript are flat, so a two-dimensional array like
a = [[130, 45], [20, 130], [45, 10]]
is actually stored like
a = [130, 45, 20, 130, 45, 10]
making searches for duplicate coordinates (i.e., lines 62-71) very difficult. The conversion from string to numbers and back again, which is going on within the loops, most certainly has an effect on performance, but the only other way would be to store the cells as an array of objects. Unfortunately, looping and searching for duplicates within an array of objects is also difficult, hence the string-based solution.
Finally, nextCulture is dumped into CULTURE, and the new generation is drawn to the playing board (lines 140-141).
The Distribution
Now that your app works, it’s time to package it and get it distributed. The packaging process is very straightforward. All you need to do is create a ZIP file that has the manifest.webapp file in its root. In Linux, you’d cd into the root of your app and type:
zip -r <appname>.zip *
Now, you have two choices: You can host it yourself on your own site, something Mozilla is perfectly okay with, or you can upload it to the Firefox OS Marketplace (Figure 6). To use the Marketplace, you need a Firefox OS developer account; the submission process is very straightforward (Figure 7).

Apart from getting more exposure with the marketplace, the wizard helps you weed out any errors you might have in your manifest and, in the future, you will be able to sell you apps using Mozilla’s framework.
Improving Life
If you run the game, your first complaint will pertain to the efficiency of the program. The program works well with small cultures but slows to a crawl as soon as the number of cells grows. There are probably ways to make GoL more efficient and the JavaScript more optimal that I have overlooked. Feel free to give the code a bash by downloading it and playing with it.
The second problem relates to usability. This app is screaming for a zoom function in edit mode. Even if the cells are 2x2 blocks on the canvas, they are tiny. No fat (or even thin) fingers will be able to place a cell accurately on the playing field without a stylus. Again, feel free to make your own changes and improvements.
Conclusion
The app itself is far from perfect, but it shows you how easy it is create an app for the Firefox OS mobile platform and some of the ways you can implement the assets Mozilla makes available.
If you already develop web apps using HTML5, you’re basically done. If not, HTML, CSS3, and jQuery are well-documented and relatively easy technologies to master, and you should be able to create your apps quickly and with little effort in no time.
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

News
-
LibreOffice 25.2 Has Arrived
If you've been hoping for a release that offers more UI customizations, you're in for a treat.
-
TuxCare Has a Big AlmaLinux 9 Announcement in Store
TuxCare announced it has successfully completed a Security Technical Implementation Guide for AlmaLinux OS 9.
-
First Release Candidate for Linux Kernel 6.14 Now Available
Linus Torvalds has officially released the first release candidate for kernel 6.14 and it includes over 500,000 lines of modified code, making for a small release.
-
System76 Refreshes Meerkat Mini PC
If you're looking for a small form factor PC powered by Linux, System76 has exactly what you need in the Meerkat mini PC.
-
Gnome 48 Alpha Ready for Testing
The latest Gnome desktop alpha is now available with plenty of new features and improvements.
-
Wine 10 Includes Plenty to Excite Users
With its latest release, Wine has the usual crop of bug fixes and improvements, along with some exciting new features.
-
Linux Kernel 6.13 Offers Improvements for AMD/Apple Users
The latest Linux kernel is now available, and it includes plenty of improvements, especially for those who use AMD or Apple-based systems.
-
Gnome 48 Debuts New Audio Player
To date, the audio player found within the Gnome desktop has been meh at best, but with the upcoming release that all changes.
-
Plasma 6.3 Ready for Public Beta Testing
Plasma 6.3 will ship with KDE Gear 24.12.1 and KDE Frameworks 6.10, along with some new and exciting features.
-
Budgie 10.10 Scheduled for Q1 2025 with a Surprising Desktop Update
If Budgie is your desktop environment of choice, 2025 is going to be a great year for you.