diff --git a/src/app.html b/src/app.html
index 239c952..526d1bb 100644
--- a/src/app.html
+++ b/src/app.html
@@ -1,9 +1,6 @@
-
-
-
%sveltekit.head%
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index a79b937..cd28044 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,4 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/service-worker.js b/src/service-worker.js
new file mode 100644
index 0000000..c5fb7e5
--- /dev/null
+++ b/src/service-worker.js
@@ -0,0 +1,49 @@
+///
+
+import { build, files, version } from '$service-worker';
+
+const cacheName = `ob-${version}`;
+
+const assets = [
+ ...build,
+ ...files
+];
+
+self.addEventListener('install', (event) => {
+ async function addToCache() {
+ const cache = await caches.open(cacheName);
+ await cache.addAll(assets);
+ }
+
+ event.waitUntil(addToCache());
+})
+
+self.addEventListener('activate', (event) => {
+ async function deleteOldCache() {
+ for (const key of await caches.keys()) {
+ if (key !== cacheName) {
+ await caches.delete(key);
+ }
+ }
+ }
+
+ event.waitUntil(deleteOldCache());
+})
+
+self.addEventListener('fetch', (event) => {
+ if (event.request.method !== 'GET') {return}
+ async function respond() {
+ const cacheRes = await caches.match(event.request, {ignoreSearch: true});
+ if (cacheRes) {
+ return cacheRes;
+ }
+
+ try {
+ return await fetch(event.request)
+ } catch (err) {
+ return {"error": "OFFLINE", "errorMsg": "You are not online"};
+ }
+ }
+
+ event.respondWith(respond());
+})
\ No newline at end of file
diff --git a/static/manifest.json b/static/manifest.json
new file mode 100644
index 0000000..098d295
--- /dev/null
+++ b/static/manifest.json
@@ -0,0 +1,33 @@
+{
+ "name": "OwlBoard",
+ "short_name": "OwlBoard",
+ "start_url": "/",
+ "scope": "/",
+ "display": "standalone",
+ "background_color": "#404c55",
+ "description": "Live station departures, PIS Code Lookup, Reference Data, Timetable search, with enhanced data for staff.",
+ "categories": "travel,utilities",
+ "lang": "en",
+ "orientation": "portrait",
+ "theme_color": "#00b7b7",
+ "icons": [
+ {
+ "src": "/images/app-icons/maskable/mask-icon.svg",
+ "sizes": "any",
+ "type": "image/svg+xml",
+ "purpose": "maskable"
+ },
+ {
+ "src": "/images/app-icons/any/plain-logo.svg",
+ "sizes": "any",
+ "type": "image/svg+xml",
+ "purpose": "any"
+ },
+ {
+ "src": "/images/app-icons/any/plain-logo-512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "any"
+ }
+ ]
+}
\ No newline at end of file