The W3C App Manifest specification

by .

By Marcos Cáceres and Bruce Lawson.

Update 26 September 2014 The initial work for Manifest in Chromium M39 is done, and Marcos (more or less) finished coding the processor a few months ago. “I’m hoping to see it in fxos 2.2“, he said from the pool of his gorgeous Malibu home.)

Update 11 November 2014 Web Application Manifest is in Chrome 38.

Update 9 April 2015 Updated implementation status to note App Install banners in Chrome, Opera Android implementation underway. Also show how to link to the manifest (thanks @mathias!) and remove some scary “this may all change” warnings.

Update 18 August 2015 François Beaufort pointed out that “According to the spec https://w3c.github.io/manifest/#h-density-member, the density should actually be a number (not a string)” – amended accordingly.

Update 7 December 2015 Link to my blogpost declaring Progressive Web Apps “ready for primetime”; remove stuff about service_worker manifest member, as it’s gone now because it was useless

Update 19 April 2016 Changed title to “W3C App Manifest” as that’s what most people know it as. Removed stuff about the density member, as it’s dropped.

Manifest? Eh? What? Why?

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.)

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. Users 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, native 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 preferred 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. In the HTML page to be “installed”, simply link to a manifest file, thus:

<link rel="manifest" href="/manifest.json">

But what’s in this mysterious manifest file? Glad you asked!

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, and format. 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",
      }]
}

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”
}

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.

Addendum June 2015: In Chromium, you can detect whether a user accepted or dismissed an install banner.

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

The manifest, and Progressive Web Apps are implemented in Chrome and Opera for Android. Implementation is underway in Firefox. You can kinda-sorta do this is a non-standard way in Safari/iOS, too.

Progressive Web Apps are ready for primetime, I believe.

6 Responses on the article “The W3C App Manifest specification”

  • 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/

  • robert says:

    .yaml is rad too although I think JSON is probably right in this case?

    http://stackoverflow.com/questions/1726802/what-is-the-difference-between-yaml-and-json-when-to-prefer-one-over-the-other

    would be interested on hearing your thoughts for not using yaml on this.

  • 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.

  • Klaus says:

    I am desperately trying to find a way to detect if a user ‘has installed’ my web app. The method advertized here, to add the media query:
    @media all and (display-mode: standalone){ …} to CSS and then to check with Javascript matchMedia .. well, that sounds so promising, but isn’t working at all. I tried with Google Chrome and a dynamic HTML-output to check if it does ‘snap’. Nope.

    This display-mode, I can’t even find it in the W3C Media Queries Level 4 working draft from June 2014. Is it a pure fantasy of the article’s writer?

  • Matteo says:

    @Klaus just add a parameter to start_url, for example

    "start_url" : "/index.html?from_homescreen=1"

  • Leave a Reply to Matteo

    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.