The W3C App Manifest specification
Publikováno: 29.7.2014
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 […]
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 2014Web 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.
The W3C App Manifest specification originally appeared on HTML5 Doctor on July 29, 2014.