diff --git a/favicon.svg b/favicon.svg
new file mode 100644
index 0000000000..ba442c2d4d
--- /dev/null
+++ b/favicon.svg
@@ -0,0 +1,15 @@
+
+
+
diff --git a/index.html b/index.html
index 0da0ee0e1b..e884fa05d9 100644
--- a/index.html
+++ b/index.html
@@ -9,6 +9,7 @@
+
diff --git a/js/application.js b/js/application.js
index 2c1108e757..43bbd061f8 100644
--- a/js/application.js
+++ b/js/application.js
@@ -2,3 +2,6 @@
window.requestAnimationFrame(function () {
new GameManager(4, KeyboardInputManager, HTMLActuator, LocalStorageManager);
});
+if ("serviceWorker" in navigator) {
+ navigator.serviceWorker.register("../sw.js");
+}
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000000..5f04bcbbcf
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,23 @@
+{
+ "name": "2048",
+ "short_name": "2048",
+ "description": "2048 game",
+ "theme_color": "#FAF8EF",
+ "background_color": "#FAF8EF",
+ "display": "standalone",
+ "scope": "/",
+ "orientation": "portrait",
+ "start_url": "/",
+ "icons": [
+ {
+ "src": "/favicon.svg",
+ "type": "image/svg+xml",
+ "sizes": "32x32"
+ },
+ {
+ "src": "/meta/apple-touch-icon.png",
+ "type": "image/png",
+ "sizes": "152x152"
+ }
+ ]
+}
diff --git a/sw.js b/sw.js
new file mode 100644
index 0000000000..ed7b21f01e
--- /dev/null
+++ b/sw.js
@@ -0,0 +1,46 @@
+// This code executes in its own worker or thread
+const urlsToCache = [
+ "index.html",
+ "style/main.css",
+ "favicon.svg",
+ "favicon.ico",
+ "/js/animframe_polyfill.js",
+ "/js/application.js",
+ "/js/bind_polyfill.js",
+ "/js/classlist_polyfill.js",
+ "/js/dom.js",
+ "/js/game_manager.js",
+ "/js/grid.js",
+ "/js/html_actuator.js",
+ "/js/in-page.js",
+ "/js/js.js",
+ "/js/keyboard_input_manager.js",
+ "/js/local_storage_manager.js",
+ "/js/tile.js",
+ "/meta/apple-touch-icon.png",
+ "/meta/apple-touch-startup-image-640x920.png",
+ "/mata/apple-touch-startup-image-640x1096.png",
+ "/style/fonts/ClearSans-Bold-webfont.woff",
+ "/style/fonts/ClearSans-Regular-webfont.woff",
+ "/style/fonts/clear-sans.css",
+];
+
+self.addEventListener("install", (event) => {
+ event.waitUntil(async () => {
+ const cache = await caches.open("pwa-assets");
+ return cache.addAll(urlsToCache);
+ });
+});
+
+self.addEventListener("activate", (event) => {
+ console.log("Service worker activated");
+});
+
+self.addEventListener("fetch", (event) => {
+ event.respondWith(
+ caches.match(event.request).then((cachedResponse) => {
+ // It can update the cache to serve updated content on the next request
+ return cachedResponse || fetch(event.request);
+ })
+ );
+});