The Web Manifest specification

by .

By Marcos Cáceres and Bruce Lawson.

Many of us who work on the web are actively working to narrow “the gap” between native applications and web applications. (Disclosure: your humble authors, Marcos Caceres and Bruce Lawson work for browser vendors – Mozilla and Opera respectively – and therefore have mortgage-related reasons to convince you this stuff is a good idea. Please also note that we are describing a technology that is a work in progress. It could all change tomorrow. )

But what is that gap? Just a few years ago, that gap was largely technological. If you wanted access to a device’s GPS, you had to write a native app. Nowadays, the situation is improving somewhat: we can now access devices sensors like GPS, camera, and orientation sensors – though we still have a long way to go. Thanks to recent advances in the web platform we now have a platform that can compete with native applications on a more equal footing.

Nowadays, the primary gaps between native and web is not so much technological. It’s user experience. User simply love installing apps, which live snugly on the homescreen (or the desktop) waiting to be tickled into life with the tap of a finger or the click of a mouse.

Furthermore, installed apps work offline by default, and integrate with the facilities provided by the underlying operating system: consider being able to see installed applications in the task switcher. Or being able to control an app’s privacy settings in the same place as apps installed from an app store. In browser land, we are still fumbling around trying to find opened tabs and having to type long and boring URLs to get anything done.

What we need is a method of “installing” web apps so they are indistinguishable from any other app installed on a user’s device. But at the same time, we don’t want to lose the powerful features that are central to the web platform: linkability, view source, and the ability to host our own stuff.

What is “installation”?

At its most basic, “installation” of a web app means “bookmarking” the web application to the homescreen or adding it to an application launcher. There are some pretty obvious things that you, as a developer, would need to provide to the browser so that it can treat your website as an app: the name, icons, etc. There are then more advanced features that you would need, like being able to indicate the prefered orientation and if you want your app to be fullscreen.

The Manifest specification aims to give you a standardised way to do this using JSON.

Application name

The application needs a real name or set of names (which is usually not the same as the title element of a document). For this you use the name and the short_name properties.

{
name: “My totally awesome photo app”
short_name: “Photos”
}

The short_name serves as the name for the application when displayed in contexts with constrained space (e.g., under an icon on the homescreen of a phone). The name can then be a bit longer, fully capturing the name of the application. This also provides an alternative way for users to search your app on their phone. So, typing ‘awesome’ or ‘photo’ would find the application on a user’s device.

If you omit the name, the browser just falls back to using <meta name=”application-name”>, and failing that, the <title> element.

Icons

There needs to be an icon associated with a web app, rather than the browser’s icon. To handle this, the manifest has an icons property. This takes a list of icons and their sizes, format, and target screen density. Having these optional properties makes icon selection really powerful, because it provides a responsive image solution for icons – which can help avoid unnecessary downloads and helps to make sure your icons always look great across a range of devices and screen densities.

{
   "icons": [{
        "src": "icon/lowres",
        "sizes": "64x64",
        "type": "image/webp"
      }, {
        "src": "icon/hd_small",
        "sizes": "64x64"
      }, {
        "src": "icon/hd_hi",
        "sizes": "128x128",
        "density": "2"
      }]
}

If you omit the icons, the browser just falls back to looking for <link rel=”icon”>, the favicon.ico or, failing that, may even use a screenshot of your website.

Display modes and orientation

Apps need to be able to control how they are to be displayed when they starts-up. If it’s a game, it might need to be in full-screen and possibly in landscape mode. In order to do this, the manifest format provides you with two properties.

{
 "display": "fullscreen",
 "orientation": "landscape"
}

For the display modes, the options that you have are:

  • fullscreen: take over the whole screen.
  • standalone: opens the app with a status bar.
  • minimal-ui: like on iOS, the app is fullscreen, but certain actions can cause the navigation bar and back/forward buttons to reappear.
  • browser: opens your app with normal browser toolbars and buttons.

The nice thing with orientation is that it serves as the “default orientation” for the scope of the application. So, as you navigate from one page to another, your app stays in the correct orientation. You can override the default orientation using the Screen Lock API.

Start URL

Sometimes you want to make sure that when the user starts up an app, they always go to a particular page first. The start_url property gives you a way of indicating this.

{
 start_url: “/start_screen.html”
}

“Scope” of the app

Native applications have clear “boundaries”: as a user, you know when you open a native application that it won’t suddenly open a different application without you noticing. When switching from one native application to another is often pretty clear that you’ve switched applications. These visual cues are often provided by the underlying operating system (think of bringing up the task manager and picking a different application – or pressing “command/alt-tab” on your desktop machine).

The web is very different: it’s a huge hypertextual system where web applications can span multiple domains: you can seamlessly jump from “gmail.com” to “docs.google.com” and as a user have no idea that you’ve jumped form one “origin” to another. In fact, the whole idea that there are boundaries to an application is totally foreign on the Web as, in reality, a web application is just a series of HTML documents (think, “a series of tubes”… no, don’t think that!).

On the web, the only reason we know that we’ve left the scope of one application and entered into another application is because the web designers have been kind enough to make their websites look uniquely different. In case where they haven’t, a lot of users have also been tricked by sites masquerading as another site (the ol’ “phishing attack”).

The manifest format assist with this problem by allowing you to specify a “URL scope” for your application. This scope sets a boundary for an app. It can either be a domain or a directory within that domain.

{
    “scope”: “/myapp”
}

Service Workers

You might have heard of service workers already. If you haven’t heard about them, a service worker is a script that allows an application to handle asynchronous events, like receiving a push notification (even after the application has been shut down). They can also be used to manage interactions between your application and a server – allowing for graceful error recovery, and hence for the ability to create applications that work offline without requiring the use of the much-disliked AppCache.

Using the “service_worker” property, the manifest spec allows you to specify a service worker for your application. The service_worker property lets you specify the url for the service worker and the URL scope to which the service worker applies.

{
service_worker: { src: “app.js”, scope: “/myapp” }
}

If you need to, you can add additional service workers through scripts in individual pages of your app.

How can I detect if the user “installed” my app?

As a developer, you really should not have to worry about this – the browser will take care of it for you. Firstly, bugging users to install your app is annoying. We’ve all seen this happen in iOS with sites asking users to “add my app to the homescreen”.

Instead, the approach that we take with the manifest is that “installing” is a progressive enhancement. Focus on creating the optimum experience based on what “display mode” the application is in. You will be able to detect and style this with CSS.

@media all and (display-mode: standalone){ ...}

You can use JavaScript matchMedia to test that media query in JavaScript.

What’s wrong with <meta> tags?

During the specification discussions, it was hotly debated whether to use <meta> tags in HTML rather than make a new format. After all, the Chrome implementation of Add to Homescreen uses <meta> tags, and this has been the natural home for proprietary flimflam since the web began.

The reasons for including a separate file are

  • it saves loading every page of an installable app/site with tons of header info
  • once downloaded, the file sits in the browsers’s HTTP cache.
  • Marcos loves JSON because he’s totally rad

Who is implementing this

Early implementations are underway in both Blink and Gecko – and there are positive signals from Microsoft too.

Statement of Intent

Don’t start coding for this stuff yet; it’s still in flux and subject to change. We draw it to your attention as it’s a statement of intent: Firefox, Opera and Google have been discussing this because we want the web to be able to compete with proprietary app platforms. The open web may not be too big to fail – but it’s too important to fail.

4 Responses on the article “The Web Manifest specification”

Jonathan Stark says

Great stuff!

I’m very excited for this – promoting web apps in the mobile OS (e.g., app launcher, app switcher, prefs pane in system settings) results in a significant improvement in the user experience.

I recently experimented with the new FxOS app installation option in Firefox for Android and it seriously kicks ass. Seamless installation experience, even when launching the app after uninstalling Firefox (e.g., “This app requires Firefox for Android. Please tap here to install it.”). Very nicely done!

A few thoughts from a lowly web dev:

1. External Manifest File

Perhaps this is only a transitional concern, but until there is wide consensus and broad implementation of the manifest format, I prefer the external file approach. We’ll likely have to support a few different formats for a while and I’d rather not have that mess inside my actual app but rather in a few external files (e.g., config.xml for PhoneGap, manifest.json for FxOS, the inevitable Chrome version of this, etc). Long term, I would prefer to see it in the meta tags but not until everyone is more or less in agreement.

2. Discoverablity

While I wholeheartedly agree that bugging people to “add to home screen” is annoying, I can attest from personal experience that it is effective. The feature is poorly advertised in browsers and few people are aware that they can do it, or what the benefits of doing it are. This is why cubiq’s Add to Homescreen js lib is so popular – if devs don’t advertise that their app can be saved to the home screen, no one will do it.

For web app installs to actually gain meaningful traction, the browser needs to advertise that a particular site is installable. I’m picturing a download icon in the URL bar, similar to the way some browsers display an RSS icon if a feed is present. Or, maybe similar to smart banners work in Safari on iOS, except instead of driving users to the native app store, the app would just install on the spot. Or like the “save password?” prompt in Chrome… whatever, you get the idea.

ASIDE: There needs to be a way to pass state into the installed app so the user can pick up where she left off in the browser, BUT this should be a one way, one time thing. e.g., clearing cookies in the parent browser later on shouldn’t log me out of my installed web app.

3. App Stores

Assuming that user behavior remains relatively consistent for the next couple years, we’re also going to need “web app stores” to accommodate user expectations. I’m picturing an “App Store” option in the browser menu that takes the user to a web site where they can browse and install a bunch of apps at once. Mozilla obviously realizes this because the Firefox Marketplace is brilliant.

Oof… sorry for the monologue! I’m just super excited about this trend and can’t wait for it to become commonplace.

Cheers!

JS

For more info:

https://hacks.mozilla.org/2014/06/firefox-os-apps-run-on-android/
http://docs.build.phonegap.com/en_US/configuring_basics.md.html
http://cubiq.org/add-to-home-screen
https://marketplace.firefox.com/

Jesse Tan says

Always nice to have a bit more human-friendly article besides the official spec.
I see no mention of “scope” in the latest published version or editor draft. Did that get removed already or hasn’t it been added yet?

Pipo says

Minor question: any reasons why its called “service_worker” and “start_url” instead of “serviceWorker” and “startUrl”? Camel case seems to be far more widespread for web developers. See “devDependencies” from Nodes package.json as an example.

Join the discussion.

Some HTML is ok

You can use these tags:
<a href="" title="">
<abbr title="">
<b>
<blockquote cite="">
<cite>
<del datetime="">
<em>
<i>
<q cite="">
<strong>

You can also use <code>, and remember to use &lt; and &gt; for brackets.