KaiOS Architecture

Gaia (Front-End)


Gaia is the user interface of the Jio platform. Anything drawn on the screen once Jio has launched is a product of the Gaia layer. Gaia implements the lock screen, home screen, and all the standard applications you expect on a smart feature phone. Gaia on Jio is implemented using HTML, CSS, and JavaScript. Its only interfaces to the underlying operating system are through open Web APIs, which are implemented by the Gecko layer. Third-party applications can be installed alongside the Gaia layer.Gaia is the core web app of the device and user interface layer, all written in HTML5, CSS and JavaScript, with a number of exposed APIs to allow the UI code to interact with the phone hardware and Gecko functionality.



Gecko forms the Jio application runtime; that is, the layer that provides all of the support for the trifecta of open standards: HTML, CSS, and JavaScript. It makes sure those APIs work well on every operating system Gecko supports. This means Gecko includes, among other things, a networking stack, graphics stack, layout engine, a JavaScript virtual machine, and porting layers.

Gecko is the web engine and presentation layer in Jio that connects hardware to HTML by serving as the interface between web content and the underlying device. Gecko provides an HTML5 parsing and rendering engine, programmatic access to hardware functionality via secure web APIs, a comprehensive security framework, update management, and other core services.



Gonk is the lower level operating system of the Jio platform, consisting of a Linux kernel (based on the Android Open Source Project (AOSP)) and a userspace Hardware Abstraction Layer (HAL). The kernel and several of the userspace libraries are common open-source projects: Linux, libusb, bluez, and so forth. Some of the other parts of the HAL are shared with the AOSP: GPS, camera, and others.You could say that Gonk is a very simple Linux distribution. Gonk is a porting target of Gecko; that is, there’s a port of Gecko to Gonk, just like there’s a port of Gecko to OS X, Windows, and Android. Since the Jio project has full control over Gonk, we can expose interfaces to Gecko that can’t be exposed on other operating systems. For example, Gecko has direct access to the full telephony stack and display frame buffer on Gonk, but doesn’t have this access on any other operating system.Gonk is the kernel-level component in the Jio stack that serves as the interface between Gecko and the underlying hardware. Gonk controls the underlying hardware and exposes hardware capabilities to Web APIs implemented in Gecko. Gonk can be seen as the “black box” that does all the complex, detailed work behind the scenes to control the mobile device by enacting requests at the hardware level.

Detailed flows







Jio apps are based on web technologies – HTML, CSS, and JavaScript and are run by Gecko runtime. If you have written a web page you already know the basics.Rendering is done by parsing HTML/CSS and painted using graphic APIs. JavaScripts are executed by the JS engine SpiderMonkey and connected to C++ components by XPConnect and WebIDL bindings. Applications and the core process communicate only through IPC protocols defined by IPDL.Additionally a set of core components including file and memory management, threads and data structures etc. are provided through the XPCOMcomponent object model.

Visual Style Guide



User interface design isn’t just about visuals. It’s about making sure users get the best possible experience when navigating an application. We accomplish this by letting the user be guided by motion and color, delighted by imagery, influenced by typefaces, and pushed forward through intelligent layout structures.This visual style guide serves as a resource for designers and developers, to help define the visual style for your Jio applications. The following components will help you incorporate the modern visual style of Jio into your applications.

Launcher Icon



The launcher icon is the first visual expression of your app, as it directly and, hopefully, effectively communicates its main purpose to the user. Unified graphic elements allow you to create simple, intuitive, consistent icons that reflect product characteristics and quality. It can also help your app stand out from other apps. The design principles in the following pages serve as a guide for icon design.


The app icon image is provided at 56 x 56 pixels in 24-bit png format. Icon shape is limited to 46 x 46 pixels round shape or 44 x 44 pixels square shape which casts a soft shadow around it.


Normal & focus states

Each icon has normal and focussed states, differentiated by color composition. Avoid using the same color for both states so they are easily distinguishable.

Appropriate icon size

It is important to keep the icon design area between 44×44 and 46×46 pixels; an oversized icon will obstruct the view while an app is being selected.

Concise icon style

All colors should be solid color elements with minimal flair; three- dimensional designs and textures will cause the icons to become overly complex and lead to inconsistencies on low resolution devices.

Transparency of icon

The launcher icon and focused color background should not be transparent, as it will expose the wallpaper and make it hard to recognize the icon.

Focus State

Color your own

Our unique transition design animates when an app is selected by users. It helps users stay focused while navigating to the app they are looking for.

The focus color in the All Apps view can be changed individually and customized to suit any brand need, as shown in the following illustration.


Baseline icon

Every app must supply a baseline icon at 56 x 56 pixels for use on the All Apps grid and list views, the KaiStore, Notices, and throughout the system once the app has been installed.

Large icon

Every app should also provide a larger icon at 112 x 112 pixels (you can choose to enlarge proportionally from the baseline icon) for display in the All Apps single view and the app launch screen.

Image Size (px) File Name Use For
56 x 56 (Baseline) AppName_56.png All Apps (grid view)
All Apps (List view)
Jio Store
In-app Notices
112 x 112 AppName_112.png All Apps (Single view)
Launch Screen

Action icon



Action icons are used to represent common actions in your app. Jio provides many common action icons, such as add, cancel, search, next, and so on. We highly recommend using these icons in your apps. If none of the standard action icons meet your app’s needs, you can design your own action icons by following the design principles in the following sections.

Size & format

An action icon must be 32 x 32 pixels in SVG format. Always keep free space (5 pixels) around the icon. However, the icon can be extended into free space due to visual weight balance.

Normal & focus states

Each icon has normal and focussed states, differentiated by their color compositions. Avoid using the same color for both states so they are easily recognizable.


The icon should be two-dimensional and filled with a solid color. Avoid decorative details or using visual effects like drop shadow, gradient, and glow. Also, ensure that the size of your icon is readable and clear on a small-sized display.


An action icon should represent its desired function as simply and clearly as possible, while avoiding overly complex or compound ideas, such as intricate details or thin outline strokes.

UI Component

Jio apps are created from UI Components which define common interface elements. By following UI Components, apps achieve a consistent appearance across the system. The units of spacing defined in Jio are specified in rem. On a screen with a density of 140, 1 rem is equal to 10 pixels, which is a baseline QVGA resolution on a 2.8-inch display.


A header appears below the status bar. The text in the header is centered and displays the app name or page title.


A tab appears below the header, which separates grouped content and provides the ability to quickly switch between different sections of an app by tapping left or right on the navigation key.

Software Key

The software key appears at the bottom of the screen, which correspond to the center, right, and left hardware keys. Each key may or may not appear depending on the availability of features.


Lists are typically used to navigate to a new screen, or to display information or controls.


Separators are used to describe a subsection of content. The separator often appears between list or grid items, as it helps separate different groups of content.

Controls – Checkbox and Radio Button

Checkboxes allow users to select multiple options from a set. Radio buttons provide the ability to select one option from a set.


Progress represents how long the current operation will take, or appears as indeterminate when the completion status cannot be determined.


The slider is an extension of Progress that adds a draggable thumb. On a non-touch device, the user can press the Right and Left keys to set a new value for a given control, such as volume or brightness.


The button is used to perform an explicit action. It can include a title or combine with an icon.


Input is a data entry field and can be as simple as a text-only entry field in a list or a search input in the header.

Option Menu

Option Menu provides a list of choices on a pop-up component which may appear with controls such as a checkbox or radio button. It allows users to perform actions on objects without having to leave their current view.

Value Selector

The Value Selector provides an easy way to select a value from a pre-determined set of values.


A Dialog provides the user with some important information, asks the user to take or confirm an action, or allows the user to make a choice or enter information.


Toast appears at the top of the screen and provides important information, or alerts the user to a system event. It can’t be interacted with and will automatically time out depending on the length of the content.



The typography of Jio provides a great reading experience, conveys hierarchy, and facilitates understanding.

Open Sans is the standard typeface on Jio. It provides high legibility and is well suited for high or low density displays.

Noto Sans is the typeface to support other languages with harmonious look and feel.


Use font weight and size to emphasize important information in your app.

Open Sans font weights

Jio picks out 4 weights of Open Sans including Light, Regular, Semi-bold, and Bold.

The Open Sans is optimized for legibility across print, web, and mobile interfaces.

The Open Sans is optimized for legibility across print, web, and mobile interfaces.

The Open Sans is optimized for legibility across print, web, and mobile interfaces.

The Open Sans is optimized for legibility across print, web, and mobile interfaces.

Noto Sans

Jio picks out 2 weights of Noto Sans including Regular and Bold.

The Noto Sans is optimized for legibility across print, web, and mobile interfaces.

The Noto Sans is optimized for legibility across print, web, and mobile interfaces.

Font Sizes

Jio uses a specific set of font sizes to balance content priority and readability.

This is a list of the most common styles and the basics you may need. There are 11 default styles calculated for a 140 ppi screen, which is a QVGA resolution at 2.8 inch display. If you’re working with a different resolution you will need to convert the unit based on your device resolution.

Tag Description Typeface Pixel
H1 Text for Header Light/300 17
H2 Header of body texts Semi-Bold/600 17
H3 Text for Tabs Regular/400 14
H4 Text for Separators Regular/400 14
H5 Text for Software keys Semi-Bold/600 14
P.PRI Primary informaiton Regular/400 17
P.SEC Secondary information Regular/400 14
P.THI Tertiary information Regular/400 12
P/UL Body texts Regular/400 17
P.LINK Text for hyperlink Bold/700 17
P.BTN Text for Button Regular/400 17

Environment setup

In this section you will learn how to setup your environment and begin developing apps for Jio.

Setting WebIDE

Firefox’s WebIDE is a necessary development tool to inspect your app, as well as see the console, debugger, and others.

  • Follow the instructions in WebIDE to setup and learn more about WebIDE.

Installing make

Make is a necessary tool to run Jio. Execute the following commands on the terminal to install it.

$ wget
$ sudo dpkg -i make_3.81-8.2_amd64.deb
$ sudo apt-mark hold make

Setting the required architectures

$ sudo dpkg --add-architecture i386
$ sudo dpkg --add-architecture amd64

Installing dependencies

There are some necessary dependencies to complete your environment for running Gaia. Execute the command below on your terminal and all these dependencies will be installed.

$ sudo apt install --no-install-recommends autoconf2.13 bison bzip2 ccache curl flex gawk gcc g++ g++-multilib git lib32ncurses5-dev lib32z1-dev libgconf2-dev zlib1g:amd64 zlib1g-dev:amd64 zlib1g:i386 zlib1g-dev:i386 libgl1-mesa-dev libx11-dev make zip lzop libxml2-utils openjdk-8-jdk nodejs unzip python

Setting ccache

$ ccache -M 10G

Installing ADB and fastboot

$ sudo apt install android-tools-adb android-tools-fastboot

Setting USB access

$ wget -S -O - | sudo tee >/dev/null /etc/udev/rules.d/51-android.rules; sudo udevadm control --reload-rules
  • Plug the device in your computer using a USB cable
  • Use the command
    $ lsusb

    on the terminal to get the Vendor ID. Example of a result: Bus 001 Device 014: ID 22b8:2e76 Motorola PCS ===> vendor ID is 22b8

  • Log in as root and edit this file: /etc/udev/rules.d/51-android.rules
  • In the file above put a new line using the vendor ID that you got before. Example: SUBSYSTEM==”usb”, ATTR{idVendor}==”22b8″, MODE=”0666″, GROUP=”plugdev”
  • Now execute:
    $ sudo chmod a+r /etc/udev/rules.d/51-android.rules
  • Create the following file in your HOME dir (not as root)
    $ nano ~/.android/adb_usb.ini
  • Put the value of vendor ID on this file using hex format. Example: 0x22b8, where 22b8 is the vendor ID that you got before.
  • Use the command ‘adb devices’ on the terminal to list all devices connected on your PC. Your device should be listed and is ready to receive Gaia apps or use it on WebIDE.

Connecting to Device

Open the Settings app and follow this flow:

Device > Developer > Debugger > ADB and DevTools

After that, you should see your device on the USB DEVICES list.

Using WebIDE with your device

  • Start WebIDE. If everything is fine, you can see your device in the ‘USB Devices’ section.
  • Click on a device name and all apps will be listed on the left side.
  • Choose one app to run, inspect, debug, test, etc.


The simulator lets you run Gaia and Web apps in a Gecko-based environment somewhat similar to an actual device. It doesn’t emulate device hardware, so it’s not adequate for testing device APIs and it isn’t a replacement for testing on actual hardware. It can, therefore, be useful during the development of your application, or while working on the application user interface itself. This article covers downloading of the simulator, as well as how to use it.


Quick start


After decompressing the files, run the following code in a terminal window:

$ ./b2g-bin -profile ./gaia/profile -start-debugger-server 6000


You should install dmg and execute from /Applications:

$ /Applications/ -profile ./gaia/profile -start-debugger-server 6000

Availble options

Options can be passed to b2g-bin:

Option Description
-profile $PROFILE_DIR Path to gaia profile.
-start-debugger-server $PORT Port number used for remote runtime.
-screen-type $SCREEN_TYPE Set screen type when startup. Can be portrait (default), landscape or stb.

After this the Jio Simulator window should pop up:

SDK Window

Connect from WebIDE

  1. Start WebIDE and click on Remote Runtime in the OTHER section on the right side
  2. Provide the correct port number set by -start-debugger-server
    Remote Runtime

Note: Please ignore “The connected runtime… Please update Firefox” warning.

Create a new app

  1. With WebIDE opened, click on New App… on the left side
  2. Choose a template and name your project
  3. After pressing the OK button, select where to save

New App

Install and run the app

  1. When the simulator is connected, click on the Install and run button (the play icon at the top of the WebIDE window)
    Install and Run
  2. The simulator window should now be updated
    Hello World

Debugging runtime apps

Click on the Debug App button (the wrench icon at the top of the WebIDE window) and the console panel will show up below it

Debug App

My First App

A native application on Jio is a Web application.Applications have different levels of access to resources depending on their granted permissions, which may be restricted by the types of applications.There are two types of web applications: packaged and hosted. A packaged app is essentially a zip file containing all application assets: HTML, CSS, JavaScript, images, manifest, etc. Hosted apps run from a server at a given domain, just like a standard website. Both app types require a valid manifest.As mentioned, a Jio app is a web app. So, if you already have some web apps ready or under development, you can easily port them to Jio.If you don’t have a web app yet, follow the steps below to create a simple web app for Jio.

  1. Supporting Multiple Resolutions
  2. Using Push Notifications
  3. Storage
  4. Caching
  5. Network State Changes
  6. Manifest
  7. Permissions
  8. Spatial Navigation
  9. Softkeys

Supporting multiple resolutions

Applications on Jio should adapt to different resolutions. Current Jio devices support QVGA resolutions in portrait (240×320 pixels) or landscape (320×240 pixels).

Media query

The best and easiest way to develop a responsive UI on Jio is by making use of CSS media queries. The following are examples of media queries considering device orientation, with Jio supported resolutions in mind:

/* KaiOS portrait devices (240x320) */
@media only screen and (orientation : portrait) {
  /* styles */

/* KaiOS landscape devices (320x240) */
@media screen and (orientation: landscape) {
  /* styles */

If you need more help, make use of some the below tips to build your responsive Jio app:

Using Push notifications

Push API allow applications to receive asynchronous notifications and perform actions without staying in the foreground.


There is no limit to application size or storage size, except for physical storage constraints.App size range depends on the complexity of the app. Below some internal Jio apps’ sizes for your reference:

  • Calculator: 200KB
  • Settings: 10 MB

Web Storage

For small size records and application data, the Web Storage API provides access to session storage or local storage, allowing you to add, modify, or delete stored items.

Device Storage

For access to specific files in a specific storage area on the device, the DeviceStorage interface is used.

navigator.getDeviceStorage() will return a DeviceStorage object which you can then use to access content of the storage area.


Jio supports standard and non-standard web cache.


The Cache interface provides a storage mechanism for Request/Response objects.


HTML5 provides application caching that lets web applications run offline. The application cache mechanism allows offline browsing, increases loading speed, and reduces server load.

Network State Changes

In order to build a good offline-capable web application, you need to know when your application is actually offline. You also need to know when your application has returned to an ‘online’ status again. Effectively, the requirements break down as follows:

  1. You need to know when the user comes back online so that you can re-synchronize with the server.
  2. You need to know when the user is offline so that you can queue your server requests for a later time.

It is this process that online/offline events help to simplify.



navigator.onLine is a property that maintains a true/false value (true for online, false for offline). This property is updated whenever the user switches into “Offline Mode”.

Additionally, this property should update whenever a browser is no longer capable of connecting to the network. According to the specification:

The navigator.onLine attribute must return false if the user agent will not contact the network when the user follows links or when a script requests a remote page (or knows that such an attempt would fail)…

online and offline events

You can register listeners for these events in a few familiar ways:

  • Using addEventListener on the windowdocument, or document.body
  • By setting the .ononline or .onoffline properties on document or document.body to a JavaScript Function object. (Note: using window.ononline or window.onoffline will not work for compatibility reasons.)
  • By specifying ononline="..." or onoffline="..." attributes on the <body> tag in the HTML markup.


window.addEventListener('load', function() {
  let status = document.getElementById("status");
  let log = document.getElementById("log");

  function updateOnlineStatus(event) {
    let condition = navigator.onLine ? "online" : "offline";

    status.className = condition;
    status.innerHTML = condition.toUpperCase();

    log.insertAdjacentHTML("beforeend", "Event: " + event.type + "; Status: " + condition);

  window.addEventListener('online',  updateOnlineStatus);
  window.addEventListener('offline', updateOnlineStatus);

Network Information

The Network Information API provides information about the system’s connection in terms of general connection type (e.g., ‘wifi’, ‘cellular’, etc.). This can be used to select high definition content or low definition content based on the user’s connection. The entire API consists of the addition of the NetworkInformation interface and a single property to the Navigator interface: Navigator.connection.


Detect connection changes

This example watches for changes to the user’s connection.

var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
var type = connection.type;

function updateConnectionStatus() {
  console.log("Connection type changed from " + type + " to " + connection.type);

connection.addEventListener('change', updateConnectionStatus);

Preload large resources

The connection object is useful for deciding whether to preload resources that take large amounts of bandwidth or memory. This example would be called soon after page load to check for a connection type where preloading a video may not be desirable. If a cellular connection is found, then the preloadVideo flag is set to false. For simplicity and clarity, this example only tests for one connection type. A real-world use case would likely use a switch statement or some other method to check all of the possible values of NetworkInformation.type. Regardless of the type value you can get an estimate of connection speed through the NetworkInformation.effectiveType property.

let preloadVideo = true;
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
if (connection) {
  if (connection.type === 'cellular') {
    preloadVideo = false;


  • NetworkInformation
    Provides information about the connection a device is using to communicate with the network and provides a means for scripts to be notified if the connection type changes. The NetworkInformation interfaces cannot be instantiated. It is instead accessed through the Navigatorinterface.


The manifest.webapp file provides important information about the app, such as version, name, description, icon location, locale strings, domains the app can be installed from, and much more. Most importantly, it contains a list of APIs that your app needs. This allows users to make informed decisions about apps before installing them.Your app’s manifest.webapp file should be placed in the root of your app directory, and contain a simple JSON structure. A simple App Manifest JSON looks like this:

  "version": "1.0.0",
  "name": "KaiOS App",
  "description": "A file simple example manifest.webapp",
  "launch_path": "/your/repository/index.html",
  "icons": {
    "56": "/your/repository/icons/ic_Appname_56.png",
    "112": "/your/repository/icons/ic_Appname_112.png"
  "developer": {
    "name": "Your Name",
    "url": ""
  "locales": {
    "en": {
      "description": "Your new web app application",
      "developer": {
        "url": ""
  "default_locale": "en"

Required fields

The fields in your manifest can be in any order. Fields in the manifest other than the ones listed below will be ignored.


Note: Required for all app manifests.

A human-readable name for the app. Maximum length is 128 characters.

If you change the name of your app after distribution, the name will not be updated for any existing installations.

"name": "The Open Web!"


A specialized string that represents the version of the app. Must be integers separated by dots.

"version": "1.2.0"


Note: Required for all app manifests.

A human-readable description for the app. It should be a short and strong message. The maximum length is 40 characters long.

"description": "My elevator pitch goes here"


Note: One icon sized 56×56 is required for all app manifests. One icon sized 112×112 is recommended for all app manifests.

A map of icon sizes to URIs of the icons.

Remember that internal paths to icons must be absolute from the app’s origin, while paths to externally hosted icons must be fully qualified.

Icons must be square and in .png format. Icons should not have solid backgrounds that extend to all four corners of the icon.

For more details about app icon check Launcher Icon section in Visual Style Guide.

"icons": {
  "56": "/img/ic_Appname_56.png",
  "112": "/img/ic_Appname_112.jpg"


Note: Only the name is required for all app manifests.

  • name: The name of the developer. Required for all app manifests.
  • url: The URL of a website containing information about the app’s developer. Optional.
"developer": {
    "name": "The Open Web!",
    "url": ""


A map of one or more language-specific overrides of the field values in your app manifest.

Keys for locales use the same language tags as for default_locale (RFC 4646).

"locales": {
  "it": {
    "name": "L'Open Web",
    "description": "Eccitante azione di sviluppo web open!"
  "de": {
    "name": "Der Open Web",
    "description": "Spannende offene Web-Entwicklung-Action!"


A language tag (RFC 4646) that defines the language you used in the field values of your app manifest.

Please refer to the list below of language identification codes used in the Jio system. We strongly suggest to use the same language identification codes throughout to avoid misalignment issues or incorrect results when users change language settings in the system:

Afrikaans af-ZA Albanian sq-AL Arabic ar-SA Armenian hy-AM Assamese as-IN
Azerbaijani az-Latn-AZ Belarusian be-BY Bengali-BD bn-BD Bengali-IN bn-IN Bodo brx-IN
Bosnian bs-BA Bulgarian bg-BG Chinese-CN zh-CN Chinese-HK zh-HK Chinese-TW zh-TW
Croatian hr-HR Czech cs-CZ Danish da-DK Dogri doi-IN Dutch nl-NL
English-US en-US Estonian et-EE Finnish fi-FI French-CA fr-CA French-FR fr-FR
Georgian ka-GE German de-DE Greek el-GR Gujarati gu-IN Hebrew he-IL
Hindi hi-IN Hungarian hu-HU Icelandic is-IS Indonesian id-ID Italian it-IT
Kannada kn-IN Kashmiri ks-Deva-IN Kazakh kk-KZ Khmer km-KH Konkani kok-IN
Lao lo-LA Latvian lv-LV Lithuanian lt-LT Macedonian mk-MK Maithili mai-IN
Malay ms-MY Malayalam ml-IN Manipuri mni-IN Marathi mr-IN Moldavian ro-MD
Nepali ne-IN Norwegian nb-NO Oriya or-IN Pashto ps-AF Persian fa-IR
Polish pl-PL Portuguese-BR pt-BR Portuguese-PT pt-PT Punjabi pa-IN Romanian ro-RO
Russian ru-RU Sanskrit sa-IN Santhali sat-IN Serbian sr-Latn-CS Sindhi sd-Deva-IN
Sinhala si-LK Slovak sk-SK Slovenian sl-SI Spanish-ES es-ES Spanish-US es-US
Swahili sw-ZA Swedish sv-SE Tagalog fil-PH Tamil ta-IN Telugu te-IN
Thai th-TH Turkish tr-TR Ukrainian uk-UA Urdu ur-PK Uzbek (Cyrillic) uz-Cyrl-UZ
Vietnamese vi-VN Xhosa xh-ZA Zulu zu-ZA

For example, if your app uses English, it’s default_locale would be:

"default_locale": "en-US"


The app’s type, which defines its level of access to sensitive device APIs. If you do not define type, it will default to web as the type.

  • web: A regular hosted app. This type has the least access to APIs.
  • privileged: An authenticated app that has been approved by an app store such as the KaiStore. This type has greater access to APIs than a web app.

Optional fields

The following fields are optional.


A human-readable name for the app. Can differ from name field.


A map of background images sizes to URIs of the icons.

"bgs": {
  "56": "/img/ic_Appname_56.png",
  "112": "/img/ic_Appname_112.jpg"


The path within the app’s origin that is loaded when the app starts.

Specifies the starting point of the content local to the zip file containing the packaged app. For example, if the launch_path is /mywebapp/index.html, the app will open the file at /mywebapp/index.html when the app is launched.


  • If your app is stored in the root of a Web server, for example, then launch_path must be set to /.
  • If your app is stored in a subdirectory, for example, then launch_path must be set to /mywebapp/.
"launch_path": "/index.html"


Note: Applies only to privileged or internal (certified) packaged apps.

Packaged apps have a special internal protocol of app://UUID where UUID is a string unique to each device the app is installed on. UUID is not easily accessible at this time. The origin field allows you to replace this UUID value with a single domain name that will be used by each installed app.

Remember: domain name must start with app://, and you must be the owner of the domain name you specify.

"origin": "app://"


The user permissions for sensitive device APIs that your app needs, for example, access to the user’s Contacts. See a full list of API permissions/features.

Each permission requires:

  • name: the name of the permission
  • description: the reason why your app needs to use this permission
  • access: the level of access required, options being readonlyreadwritereadcreate, and createonly. Only a few APIs need this, for example Data Store.

For example, here’s a manifest entry for an app that needs permission to use the device’s contacts and alarms.

"permissions": {
  "contacts": {
    "description": "Required for autocompletion in the share screen",
    "access": "readcreate"
  "alarms": {
    "description": "Required to schedule notifications"

Note: If an app tries to use one of these APIs without a corresponding entry in the permissions field, it will fail to run.

There are many APIs, some of whom require the app type to be privileged or internal (certified). For example, systemXHR requires the type field to be set to privileged in order to work:

"type": "privileged",
  "permissions": {
    "systemXHR": {
      "description": "Required to download podcasts."


A control that tells the runtime whether or not to launch the app in full-screen mode.

"fullscreen": "true"


Note: Applies only to privileged/certified apps to be installed on Jio.

When making use of the Data Store API, the app that owns the data store MUST include the datastores-owned field in its manifest to claim ownership, for example:

"datastores-owned": {
  "myData": {
    "access": "readwrite",
    "description": "my data store"

You can include multiple properties to represent different data stores, and each one can use an access of readonly/readwrite to specify whether the data store can be read/modified by other applications. A description is also included to describe the purpose of the data store.


Note: Applies only to privileged/certified apps to be installed on Jio.

When making use of the Data Store API, any non-owner app that wants access to the the data store MUST include the datastores-access field in its manifest, for example:

"datastores-access": {
  "myData": {
    "access": "readwrite",
    "description": "Read and modify my data store"

Without this field being specified, the default behaviour is “no access”. Again, multiple properties can be included if you want to access multiple data stores, and an access of readonly or readwrite can be set to declare what access type is needed by the app.


Note: Applies only to apps to be installed on Jio.

The system messages you allow the app to capture, and the pages in your app that will display when those messages occur.

Below is an example from the Jio Dialer app. Every time an incoming call comes in (system message: telephony-new-call), the device shows the dialer’s keypad (URL: /dialer/index.html#keyboard-view).

"messages": [
  { "alarm": "/index.html" }
  { "notification": "/index.html" }
  { "telephony-new-call": "/dialer/index.html#keyboard-view" }


Note: Applies only to privileged/certified apps that are to be installed on Jio.

The internal URLs your app uses to handle external processes.

For example, your app might use Facebook OAuth authentication to get a user’s contacts. When the authentication is finished, the server usually redirects back to a URL that you control. Because packaged apps are not hosted on the web, a packaged app does not have a valid URL that can be redirected to. So you use the redirects field to redirect an external URL to an internal app URL.

In the scenario above, the redirects field will look like this:

"redirects": [
  {"from": "",
    "to": "/app/main_interface.html"}

The scope of the redirects declared by redirects is limited to the app that declares them. That makes it so that several apps can redirect the same public URL to their own local resources, and it also prevents global hijacking of public URLs by an application.


A set of Web Activities that your app supports (full list). It’s structured like so:

  • Each property in this field is an activity
  • Activity names are free-form text
  • Each activity is represented by an object

For example, here’s an entry with one activity named share.

"activities": {
  "share": {
    "filters": {
      "type": [ "image/png", "image/gif" ]
    "href": "foo.html",
    "disposition": "window",
    "returnValue": true

The object for the share activity in the example has filters, href, disposition and returnValue properties. These are described in Activity handler description.


The path to JavaScript files containing asm.js code that you want compiled at install time.

Compilation at install time makes the installation process longer, but reduces the time it takes to start up an app.

"precompile": [


The positioning at which the application will stay locked.

Illustration of possible values:

Value App will stay locked to
portrait-primary portrait-primary
portrait-secondary portrait-secondary
If you declare this, there’s no need to write -primary or -secondary
portrait-primary portrait-secondary
landscape-primary landscape-primary
landscape-secondary landscape-secondary
If you declare this, there’s no need to write -primary or -secondary
landscape-primary landscape-secondary
"orientation": [ "landscape-primary" ]


This field can be used to define a Content Security Policy (CSP) that is applied to all pages in the app. The policies you can add to a CSP are listed in CSP policy directives, and for an app you’ll need to include them in a line like so:

"csp" : "default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"

The default policies applied to Jio privileged and internal/certified apps are as follows:

Privileged CSP

default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'

Certified/Internal CSP

default-src *; script-src 'self'; object-src 'none'; style-src 'self'

These defaults can’t be overridden, only added to, i.e. the CSP policy in the manifest can only make the actual CSP applied more restrictive in the case of privileged/internal apps.

Serving manifest

Note: This is applied to ‘hosted app URL’

The app manifest must be served from the same origin that the app is served from.

The manifest should be stored with a file extension of .webapp. App manifests must be served with a Content-Type header of application/x-web-app-manifest+json. This is currently enforced by the KaiStore. The KaiStore only checks this if the origin of the page where the user triggers the install is different from the origin of the app itself. You don’t need other headers such as Content-Security-Policy and X-UA-Compatible.

Manifests can be served over SSL to mitigate certain classes of attacks. You can also serve the manifest with HTTP compression. The manifest should not be cached.

The manifest must be in UTF-8 encoding in order for the app to be submitted to the KaiStore. It is recommended that you omit the byte order mark (BOM). Other encodings can be specified with a charset parameter on the Content-Type header.

User Agents when possible should meaningfully message the site identity and TLS status when prompting a user to install an app.


The permissions field in the app manifest controls the app’s access to various sensitive APIs on the device (sometimes called WebAPIs). The permissions are described in the following tables. The three levels of permission, in brief, are:

  • Web apps: These only have a basic level of permissions, and don’t have access to privileged or internal APIs.
  • Privileged apps: These have all the permissions of web apps plus more. Hosted apps can’t be privileged — they must be packaged apps.

Hosted app and privileged app permissions

Manifest permission API name Minimum app type required access property Default granted
alarms Alarm hosted none Allow
audio-capture getUserMedia, Web Speech API hosted for getUserMedia, privileged for Web Speech API none Prompt for all installed App types for getUserMedia, Allow for Web Speech API.
audio-channel-alarm AudioChannels privileged none Allow
audio-channel-content AudioChannels hosted none Allow
audio-channel-normal AudioChannels hosted none Allow
audio-channel-notification AudioChannels privileged none Allow
browser Browser privileged none Allow
camera Camera privileged in Jio certified none Prompt for all installed App types.`
contacts Contacts privileged readonlyreadwritereadcreate, or createonly Prompt for all installed App types.
desktop-notification Notification hosted none Prompt for Web content. Allow for all installed App types.
device-storage:music Device Storage privileged readonlyreadwritereadcreate, or createonly Prompt
device-storage:pictures Device Storage privileged readonlyreadwritereadcreate, or createonly Prompt
device-storage:sdcard Device Storage privileged readonlyreadwritereadcreate, or createonly Prompt
device-storage:videos Device Storage privileged readonlyreadwritereadcreate, or createonly Prompt
fmradio FM Radio hosted none Allow
geolocation Geolocation hosted none Prompt (even for certified Apps)
input Keyboard privileged none Allow
mobileid Mobile identity privileged none Prompt
mobilenetwork Mobile Network privileged none Allow
moz-firefox-accounts Firefox Accounts privileged none Prompt for all installed App types.
nfc NFC API privileged none Allow
nfc-share NFC API privileged none Allow
nfc-readnfc-write NFC API Was certified/internal at this stage in development. none Allow
push Simple Push hosted none Allow
speech-recognition Web Speech API privileged none Allow
systemXHR SystemXHR privileged none Allow
tcp-socket TCP Socket privileged none Allow
video-capture GetUserMedia hosted none Prompt for all installed App types.

Spatial navigation

On non-touch devices, the preferred method of app navigation is to use the available hardware keys.Jio feature phones generally come up with 4 directional arrow keys and confirmation keys.The steps below are guidelines on how to have your webapp respond to directional keys instead of using a cursor or touch controls.

Step 1

Use same class to group elements and make them a navigation candidate pool.

<div class="items">1</div>

<div class="items">2</div>

<div class="items">3</div>

<div class="items">4</div>

<input type="text" class="items"/>

<a href="more.html" clas="items">more..</a>

Step 2

Make every element focusable

  • HTMLAnchorElement/HTMLAreaElement with an href
  • HTMLInputElement/HTMLSelectElement/HTMLTextAreaElement/HTMLButtonElement without disabled
  • HTMLIFrameElement

Any element with a tabindex eg:

<div class="items" tabIndex="1"></div>

Step 3

Let target element execute focus() to become active element. After calling focus you can confirm it via document.activeElement.

Step 4

Active element listen keydown or keyup event:

document.activeElement.addEventListener('keydown', handleKeydownEvent);

Step 5

Handle ArrowUpArrowRightArrowLeft and ArrowDown keys:

function handleKeydown(e) {
  switch(e.key) {
    case 'ArrowUp':
    case 'ArrowDown':
    case 'ArrowRight':
    case 'ArrowLeft': 

Step 6

Find next target element:

function nav (move) {
  var next = currentIndex + move;
  var items = document.querySelectorAll('.items');
  var targetElement = items[next];


The software key appears at the bottom of the screen, which corresponds to the center, right, and left hardware keys. Each key may or may not appear depending on the availability of features.


This is a simple structure of a softkey use, see the UI Components section for the style example of the component.

<body id="app">

<!-- Your app's code -->

    <footer class="softkey">
        <div id="softkey-left">Back</div>
        <div id="softkey-center">SELECT</div>
        <div id="softkey-right">Options</div>


User actions on the keyboard can lead to a new state of your application. For more understanding see the simple example below, where you can hear the device keyboard actions.

const softkeyCallback = {
    left: function() { console.log('You click on SoftLeft') },
    center: function() { console.log('You click on Enter') },
    right: function() { console.log('You click on SoftRight') }
function handleKeyDown(evt) {
    switch (evt.key) {
        case 'SoftLeft':
            // Action case press left key

        case 'SoftRight':
            // Action case press right key

        case 'Enter':
            // Action case press center key

document.addEventListener('keydown', handleKeyDown);

In case your application needs to update the softkey, according to a state, view or navigation, this can be done using a function like the following example:

function updateSoftKey(props) {
    const keys = Object.keys(props);

    keys.forEach(function(key) {
        const button = document.getElementById('softkey-' + key);
        button.textContent = props[key].label;
        softkeyCallback[key] = props[key].callback;

/* This function is call that way */
    left: {
        label: 'Left text',
        callback: function(){ /* Code */ }
    center: {
        label: 'Center text',
        callback: function(){ /* Code */ }
    right: {
        label: 'Right text',
        callback: function(){ /* Code */ }

Run and debug your first App

Running apps

When you’re ready to run the app, follow these steps for executing:

  1. Start WebIDE. If everything is fine until now, you can see your device on ‘USB Devices’ section.
  2. Click on the device name and all apps will be listed on the left side.
  3. Choose one app to run, inspect, debug, test, etc.


Debugging apps

To debug the app, click the wrench icon and the Developer Tools Toolbox appears, connected to your app:

WebIDE - Inspector

Exactly which tools you’ll have available depends on the runtime, but you will at least have the basics: the InspectorConsoleJavaScript DebuggerStyle EditorProfiler, and Scratchpad. Just as in a web page, any changes you make in the tools are visible immediately in the app, but are not persistent. Conversely, any changes you make in the editor pane can be saved straight back to disk, but are not visible without restarting the app.

If you’re interested in the performance of your apps, there are a few ways to measure their impact on the runtime in WebIDE:

  • The Monitor panel offers a good overview of a device’s performance. This can help you detect problems, e.g. a sudden, excessive increase in an app’s memory usage (leak).
  • The Profiler tool gives you a way to analyze a single app’s footprint in great detail. This is especially useful when investigating a known performance problem.

Unrestricted app debugging (including certified apps, main process, etc.)

You can run the debugger against the simulator, b2g desktop, or a real device.

With the Simulator, while the runtime is selected you can see and debug not only your app but all apps running in that runtime, including certified apps:

WebIDE - Debugging

Other Web APIs

Web Application Programming Interfaces (Web APIs) are used to perform a variety of tasks, such as manipulating the DOM, playing audio or video, or generating 3D graphics.When writing code for the Web with JavaScript, there are a great many APIs available. This page has a list of all the interfaces that you may be able to use while developing your Web app.

Ready to develop for Jio?

Thank you for your interest in contributing to the Jio platform.We look forward to receiving your application. As a first step, please carefully read the checklist below to ensure that your submission meets the Jio standards. Once you are familiar with the process and your access has been approved, you can follow these steps within the App Submission Portal.

  1. Make sure you have read all the documentation in this portal. This helps you understand what is considered a qualified app for Jio.
  2. Prepare an app manifest for the required fields. You cannot submit your app without a proper manifest so make sure you read this section carefully.
  3. Include known issues of your app with your app submission.
  4. Add your app’s test report in .txt format.
  5. If your app is a hosted app, include the hosted app URL.
  6. Agree to the “Jio Application Development Agreement” when you sign up in the App Submission Portal. Please contact us via our contact form under “Partnership opportunities” if you’d like to partner with us. We will review your proposal and send over our standard business terms.

Once you’ve submitted your app, the KaiStore team will review your submission and inform you of the result. In general, this process takes about two weeks.

The KaiStore team reserves the right to reject your app under the following circumstances:

  • The above steps have not been followed.
  • The required materials have not been submitted or are incomplete.
  • Your app does not meet our quality threshold in areas such as ‘Basic function’, ‘Interaction’, ‘Stability’, as well as ‘Compatibility’.