├── .pr-preview.json ├── tidyconfig.txt ├── LICENSE.md ├── w3c.json ├── .github ├── CODE_OF_CONDUCT.md ├── workflows │ ├── tidy.yml │ └── auto-publish.yml ├── PULL_REQUEST_TEMPLATE.md └── CONTRIBUTING.md ├── ECHIDNA ├── README.md ├── images ├── monochrome-icon-tinted.svg ├── monochrome-icon-plain.svg ├── monochrome-icon-gradient.svg ├── icon-mask-windows.svg ├── icon-safe-zone.svg ├── icon-mask-android-circle.svg ├── icon-mask-android-roundsquare.svg ├── icon-mask-ios.svg ├── icon-mask-android-squircle.svg ├── icon-plain.svg ├── independent_policies.svg ├── manifest-src-directive.svg └── safe-zone.svg └── explainer.md /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.html", 3 | "type": "respec" 4 | } 5 | -------------------------------------------------------------------------------- /tidyconfig.txt: -------------------------------------------------------------------------------- 1 | char-encoding: utf8 2 | indent: yes 3 | indent-spaces: 2 4 | wrap: 80 5 | tidy-mark: no 6 | custom-tags: yes 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors 2 | under the 3 | [W3C Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [ 3 | "114929" 4 | ], 5 | "contacts": [ 6 | "siusin" 7 | ], 8 | "shortName": "manifest", 9 | "repo-type": "rec-track" 10 | } 11 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /ECHIDNA: -------------------------------------------------------------------------------- 1 | index.html?specStatus=WD&shortName=appmanifest respec 2 | images/manifest-src-directive.svg 3 | images/icon-mask-android-circle.svg 4 | images/icon-mask-android-roundsquare.svg 5 | images/icon-mask-android-squircle.svg 6 | images/icon-mask-ios.svg 7 | images/icon-mask-windows.svg 8 | images/icon-plain.svg 9 | images/icon-safe-zone.svg 10 | images/safe-zone.svg 11 | images/monochrome-icon-gradient.svg 12 | images/monochrome-icon-plain.svg 13 | images/monochrome-icon-tinted.svg 14 | -------------------------------------------------------------------------------- /.github/workflows/tidy.yml: -------------------------------------------------------------------------------- 1 | name: Tidy document 2 | on: 3 | workflow_dispatch: {} 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - index.html 9 | 10 | jobs: 11 | tidy: 12 | name: Tidy up 13 | runs-on: macos-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - run: brew install tidy-html5 17 | - run: tidy -config tidyconfig.txt -o index.html index.html 18 | - uses: peter-evans/create-pull-request@v6 19 | with: 20 | title: "Tidied up document using tidy-html5" 21 | commit-message: "chore: tidy up index.html" 22 | branch: html-tidy 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository is the home of the :star: **[Web Application Manifest](https://www.w3.org/TR/appmanifest/)** :star: specification being worked on by 2 | the [Web Applications Working Group](https://www.w3.org/2019/webapps/). 3 | 4 | ## Useful links 5 | * [Explainer](https://github.com/w3c/manifest/blob/gh-pages/explainer.md) 6 | * [The Web Application Manifest specification](https://www.w3.org/TR/appmanifest/) 7 | * [Manifest incubations](https://github.com/WICG/manifest-incubations) 8 | * [App Information supplement](https://github.com/w3c/manifest-app-info) 9 | * [Use cases and requirements](https://w3c-webmob.github.io/installable-webapps/) 10 | * [The Web Applications WG homepage](https://www.w3.org/2019/webapps/) 11 | -------------------------------------------------------------------------------- /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: {} 8 | 9 | jobs: 10 | validate-and-publish: 11 | name: Validate and Publish 12 | runs-on: ubuntu-latest # only linux supported at present 13 | steps: 14 | - uses: actions/checkout@v2 15 | - uses: w3c/spec-prod@v2 16 | with: 17 | TOOLCHAIN: respec 18 | VALIDATE_LINKS: false 19 | VALIDATE_PUBRULES: false 20 | GH_PAGES_BRANCH: gh-pages 21 | W3C_API_KEY: ${{ secrets.W3C_API_KEY }} 22 | W3C_ECHIDNA_TOKEN: ${{ secrets.ECHIDNA_TOKEN }} 23 | W3C_WG_DECISION_URL: "https://lists.w3.org/Archives/Public/public-webapps/2014JulSep/0627.html" 24 | W3C_NOTIFICATIONS_CC: "${{ secrets.CC }}" 25 | W3C_BUILD_OVERRIDE: | 26 | specStatus: WD 27 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Closes #??? 2 | 3 | This change (choose at least one, delete ones that don't apply): 4 | 5 | * Breaks existing normative behavior (please add label "breaking") 6 | * Adds new normative requirements 7 | * Adds new normative recommendations or optional items 8 | * Makes editorial changes (changes informative sections, or changes normative sections without changing behavior) 9 | * Is a "chore" (metadata, formatting, fixing warnings, etc). 10 | 11 | Implementation commitment (delete if not making normative changes): 12 | 13 | * [ ] WebKit (https://bugs.webkit.org) 14 | * [ ] Chromium (https://bugs.chromium.org/) 15 | * [ ] Gecko (http://bugzilla.mozilla.org) 16 | 17 | If change is normative, and it adds or changes a member: 18 | 19 | * [ ] [updated JSON schema](https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/web-manifest.json) 20 | 21 | Commit message: 22 | 23 | (Fill in. If making normative changes, describe exactly what the behavioral 24 | difference will be.) 25 | 26 | Person merging, please make sure that commits are squashed with one of the following as a commit message prefix: 27 | 28 | * chore: 29 | * editorial: 30 | * BREAKING CHANGE: 31 | * And use none if it's a normative change 32 | -------------------------------------------------------------------------------- /images/monochrome-icon-tinted.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/monochrome-icon-plain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /images/monochrome-icon-gradient.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Everyone is welcome to contribute to this specification. 4 | 5 | Any simple editorial contribution can simply be done with a GitHub Pull Request. 6 | You can even do an inline edit of the file on GitHub. 7 | 8 | For more substantial contributions, please first [file an issue](https://github.com/w3c/manifest/issues/new) here on Github. 9 | 10 | Note: Contributions to this repository are intended to become part of Recommendation-track documents governed by the 11 | [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy-20040205/) and 12 | [Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate 13 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 14 | 15 | If you are not the sole contributor to a contribution (pull request), please identify all 16 | contributors in the pull request comment. 17 | 18 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 19 | 20 | ``` 21 | +@github_username 22 | ``` 23 | 24 | If you added a contributor by mistake, you can remove them in a comment with: 25 | 26 | ``` 27 | -@github_username 28 | ``` 29 | 30 | If you are making a pull request on behalf of someone else but you had no part in designing the 31 | feature, you can remove yourself with the above syntax. 32 | 33 | 34 | # Style guide to contributors 35 | 36 | - the spec uses [ReSpec](https://www.w3.org/respec/) 37 | - the spec is tidied using [HTML5 Tidy](https://github.com/w3c/tidy-html5). For 38 | instructions on running HTML5 tidy, see below. 39 | - put comments in front of sections, for better readability with 40 | syntax coloring editors. 41 | 42 | 43 | # Running HTML5 Tidy 44 | 45 | Please make sure you have HTML5 tidy installed, instead of 46 | the the one that ships with *nix systems. You can confirm this by running: 47 | 48 | ```bash 49 | tidy --version #HTML Tidy for HTML5 (experimental) for ... 50 | ``` 51 | 52 | Once you have confirmed (make sure you have committed your changes before 53 | running tidy, as the changes are destructive ... in a good way:)): 54 | 55 | ```bash 56 | tidy -config tidyconfig.txt -o index.html index.html 57 | ``` 58 | -------------------------------------------------------------------------------- /images/icon-mask-windows.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /images/icon-safe-zone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /images/icon-mask-android-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /images/icon-mask-android-roundsquare.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /images/icon-mask-ios.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /images/icon-mask-android-squircle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /images/icon-plain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /images/independent_policies.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | indipendent_policies 4 | Created with Sketch (http://www.bohemiancoding.com/sketch) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Policy 15 | 16 | 17 | Policy 18 | 19 | 20 | HTML 21 | 22 | 23 | Manifest 24 | 25 | 26 | example.com 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /images/manifest-src-directive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Untitled 2 4 | example.com has a CSP policy associated with the HTML file which states that manifests come from 5 | bar.com, and icons from foo.com. 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Policy 19 | 20 | 21 | HTML 22 | 23 | 24 | Manifest 25 | 26 | 27 | example.com 28 | 29 | 30 | 31 | 32 | bar.com 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | icons.com 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | manifest-src bar.com 55 | img-src icons.com 56 | 57 | 58 | 59 | icons 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /images/safe-zone.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /explainer.md: -------------------------------------------------------------------------------- 1 | ## Manifest? Eh? What? Why? 2 | 3 | [Many of us](https://github.com/w3c/manifest/graphs/contributors) who work on the web are actively working to narrow "the gap" between native applications and web applications. 4 | 5 | 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. 6 | 7 | Nowadays, the primary gaps between native and web is not so much technological. It’s user experience. Users prefer to install apps, which live snugly on the homescreen (or possibly even the desktop, on desktop-class browsers). 8 | 9 | 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. 10 | 11 | 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. 12 | 13 | This is generally what we, in the web community, refer to as a "[progressive web app](https://en.wikipedia.org/wiki/Progressive_web_app)". 14 | 15 | ## What is "installation"? 16 | 17 | 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. 18 | 19 | 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: 20 | 21 | ```HTML 22 | 23 | ``` 24 | 25 | But what’s in this mysterious manifest file? Glad you asked! 26 | 27 | ## A very simple manifest 28 | 29 | A very simple manifest might just include a name and one or more icons. 30 | 31 | ```JSON 32 | { 33 | "name": "Super Racer 3000", 34 | "icons": [{ 35 | "src": "icon/lowres.png", 36 | "sizes": "64x64" 37 | }] 38 | } 39 | ``` 40 | 41 | ## A typical manifest 42 | 43 | A typical manifest might look something like the following. The names of the members should be fairly self evident, but we describe their usage in detail below. 44 | 45 | ```JSON 46 | { 47 | "lang": "en", 48 | "dir": "ltr", 49 | "name": "Super Racer 3000", 50 | "description": "The ultimate futuristic racing game from the future!", 51 | "short_name": "Racer3K", 52 | "icons": [{ 53 | "src": "icon/lowres.webp", 54 | "sizes": "64x64", 55 | "type": "image/webp" 56 | },{ 57 | "src": "icon/lowres.png", 58 | "sizes": "64x64" 59 | }, { 60 | "src": "icon/hd_hi", 61 | "sizes": "128x128" 62 | }], 63 | "scope": "/racer/", 64 | "start_url": "/racer/start.html", 65 | "display": "fullscreen", 66 | "orientation": "landscape", 67 | "theme_color": "aliceblue", 68 | "background_color": "red", 69 | "screenshots": [{ 70 | "src": "screenshots/in-game-1x.jpg", 71 | "sizes": "640x480", 72 | "type": "image/jpeg" 73 | },{ 74 | "src": "screenshots/in-game-2x.jpg", 75 | "sizes": "1280x920", 76 | "type": "image/jpeg" 77 | }] 78 | } 79 | ``` 80 | 81 | ## Application name 82 | 83 | 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` members. 84 | 85 | ```JSON 86 | { 87 | "name": "My totally awesome photo app", 88 | "short_name": "Photos" 89 | } 90 | ``` 91 | 92 | 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). 93 | The `name` can then be a bit longer, fully capturing the name of the application. 94 | This also provides an alternative way for users to search your app on their phone. 95 | So, typing ‘awesome’ or ‘photo’ would find the application on a user’s device. 96 | 97 | If you omit the name, the browser can fall back to using ``, and failing that, the `` element. 98 | 99 | Be careful though: some browsers can be quite strict about wanting you to include a `name` - and if omit them, it can invalidate your app from being a "progressive web app". 100 | 101 | ## Icons 102 | 103 | 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. 104 | 105 | ```JS 106 | { 107 | "icons": [{ 108 | "src": "icon/lowres", 109 | "sizes": "64x64", 110 | "type": "image/webp" 111 | }, { 112 | "src": "icon/hd_small", 113 | "sizes": "64x64" 114 | }, { 115 | "src": "icon/hd_hi", 116 | "sizes": "128x128", 117 | }] 118 | } 119 | ``` 120 | 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. 121 | 122 | ### Icon purpose 123 | 124 | TBW. 125 | 126 | More information about purpose can be found in the [Web Application Manifest spec](https://www.w3.org/TR/appmanifest/#purpose-member). 127 | 128 | ## Display modes and orientation 129 | Apps need to be able to control how they are to be displayed when they start-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. 130 | 131 | ```JSON 132 | { 133 | "display": "fullscreen", 134 | "orientation": "landscape" 135 | } 136 | ``` 137 | 138 | For the display modes, the options that you have are: 139 | 140 | * `fullscreen`: take over the whole screen. 141 | * `standalone`: opens the app with a status bar. 142 | * `minimal-ui`: like on iOS, the app is fullscreen, but certain actions can cause the navigation bar and back/forward buttons to reappear. 143 | * `browser`: opens your app with normal browser toolbars and buttons. 144 | 145 | 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 Orientation API](https://w3c.github.io/screen-orientation/). 146 | 147 | You can also style apps that are in a particular display mode by using the `display-mode` media feature: 148 | 149 | ```CSS 150 | @media all and (display-mode: standalone){ 151 | ... 152 | } 153 | ``` 154 | 155 | And use JavaScript `window.matchMedia()` to test that media query in JavaScript. 156 | 157 | ```JS 158 | if (window.matchMedia("(display-mode: standalone)").matches) { 159 | // do interesting UI adjustments 160 | } 161 | ``` 162 | 163 | ## Start URL 164 | 165 | 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. 166 | 167 | ```JSON 168 | { 169 | "start_url": "/start_screen.html" 170 | } 171 | ``` 172 | 173 | ## "Scope" of the app 174 | 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). 175 | 176 | 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!). 177 | 178 | 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"). 179 | 180 | 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. 181 | 182 | ```JSON 183 | { 184 | "scope": "/myapp" 185 | } 186 | ``` 187 | 188 | ## Internationalization: lang and dir 189 | TBW... 190 | 191 | ## Distributing your app 192 | TBW: using description and screenshots. 193 | 194 | ## Theme color and background color 195 | TBW... 196 | 197 | ## Adding shortcuts 198 | Numerous operating systems grant native applications the ability to add menu items to the app icon itself. These often provide quick access to key tasks for an app. Typically, these are exposed via a right click, long tap, or a similar context menu-triggering action. For web applications, you can define a set of shortcuts to be exposed when the app is installed. Each shortcut item must have a name and a target URL. You may also include additional information, such as a shorter name, a description for the action, and one or more icons. 199 | 200 | ```JSON 201 | "shortcuts": [ 202 | { 203 | "name": "Play Later", 204 | "description": "View the list of podcasts you saved for later", 205 | "url": "/play-later", 206 | "icons": [ 207 | { 208 | "src": "/icons/play-later.svg", 209 | "type": "image/svg+xml", 210 | "purpose": "any" 211 | } 212 | ] 213 | }, 214 | { 215 | "name": "Subscriptions", 216 | "description": "View the list of podcasts you listen to", 217 | "url": "/subscriptions", 218 | "icons": [ 219 | { 220 | "src": "/icons/subscriptions.svg", 221 | "type": "image/svg+xml", 222 | "purpose": "any" 223 | } 224 | ] 225 | }, 226 | { 227 | "name": "Search", 228 | "description": "Search for new podcasts to listen to", 229 | "url": "/search", 230 | "icons": [ 231 | { 232 | "src": "/icons/search.svg", 233 | "type": "image/svg+xml", 234 | "purpose": "any" 235 | } 236 | ] 237 | }, 238 | { 239 | "name": "Discover", 240 | "description": "Browse for new podcasts to listen to", 241 | "url": "/discover", 242 | "icons": [ 243 | { 244 | "src": "/icons/discover.svg", 245 | "type": "image/svg+xml", 246 | "purpose": "any" 247 | } 248 | ] 249 | } 250 | ] 251 | ``` 252 | 253 | ## How can I detect if the user "installed" my app? 254 | The spec provides a way for you to detect when the user installs your apps by registering for "appinstalled" events. 255 | 256 | ```JS 257 | function handleInstalled(ev) { 258 | const date = new Date(ev.timeStamp / 1000); 259 | console.log(`Yay! Our app got installed at ${date.toTimeString()}`); 260 | } 261 | 262 | // Using the event handler IDL attribute 263 | window.onappinstalled = handleInstalled; 264 | 265 | // Using .addEventListener() 266 | window.addEventListener("appinstalled", handleInstalled); 267 | ``` 268 | 269 | However, for privacy reasons, you can't directly detect if your application is installed - only if the manifest is being used with your web application. 270 | 271 | ## What’s wrong with `<meta>` tags? 272 | 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 Home screen uses `<meta>` tags, and this has been the natural home for proprietary flimflam since the web began. 273 | 274 | The reasons for including a separate file are 275 | 276 | * it saves loading every page of an installable app/site with tons of header info 277 | * once downloaded, the file sits in the browsers’s HTTP cache. 278 | 279 | More details about [why we chose JSON instead of the html tags](https://www.w3.org/TR/appmanifest/#relationship-to-html-s-link-and-meta-elements) can be found in the spec. 280 | 281 | ## Who is implementing this 282 | 283 | The manifest, and Progressive Web Apps are implemented in Chrome, Opera, and Samsung Internet for Android. There are positive signals from Firefox that they will support this standard too (it has been implemented in Gecko for over 2 years, but not shipping in any products yet). 284 | 285 | ## Interaction with Web Crawlers 286 | 287 | Like other web resources, a web application manifest should be accessible to any web browser or web crawler. 288 | 289 | If a web app developer wants to inform web crawlers of a desire for the file not to be crawled, the developer MAY do so by including the web application manifest in a robots.txt file. 290 | This is further described in the [robots.txt](http://www.robotstxt.org/) protocol. 291 | A web app developer could also use the `X-Robots-Tag` HTTP header. 292 | 293 | ## Attribution 294 | The bulk of this explainer originally appeared in [HTML5 Doctor](http://html5doctor.com/) as "[The W3C App Manifest specification](http://html5doctor.com/web-manifest-specification/)", and was written by [Marcos Cáceres](https://github.com/marcoscaceres) and [Bruce Lawson](https://www.brucelawson.co.uk/). This derivative work is allowed by the [Creative Commons Attribution-Non-Commercial 2.0](https://creativecommons.org/licenses/by-nc/2.0/uk/) license of the original document. Thus, feel free to change, reuse, modify, and extend this explainer. Some authors will retain their copyright on certain articles. 295 | --------------------------------------------------------------------------------