diff --git a/index.html b/index.html
index 10f01cf..56f0f0c 100644
--- a/index.html
+++ b/index.html
@@ -5,6 +5,11 @@
Reaktor — MontLab Modular Synth
+
+
+
+
+
diff --git a/public/icon-192.png b/public/icon-192.png
new file mode 100644
index 0000000..723ed12
Binary files /dev/null and b/public/icon-192.png differ
diff --git a/public/icon-512.png b/public/icon-512.png
new file mode 100644
index 0000000..2de1180
Binary files /dev/null and b/public/icon-512.png differ
diff --git a/public/manifest.json b/public/manifest.json
new file mode 100644
index 0000000..4468fba
--- /dev/null
+++ b/public/manifest.json
@@ -0,0 +1,15 @@
+{
+ "name": "Reaktor — MontLab Modular Synth",
+ "short_name": "Reaktor",
+ "description": "Modular synthesizer & SynthQuest puzzle game",
+ "start_url": "/",
+ "display": "standalone",
+ "orientation": "any",
+ "background_color": "#08080f",
+ "theme_color": "#00e5ff",
+ "icons": [
+ { "src": "/favicon.svg", "sizes": "any", "type": "image/svg+xml", "purpose": "any" },
+ { "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
+ { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
+ ]
+}
diff --git a/public/sw.js b/public/sw.js
new file mode 100644
index 0000000..22d088e
--- /dev/null
+++ b/public/sw.js
@@ -0,0 +1,33 @@
+const CACHE_NAME = 'reaktor-v1';
+
+self.addEventListener('install', (e) => {
+ self.skipWaiting();
+});
+
+self.addEventListener('activate', (e) => {
+ e.waitUntil(
+ caches.keys().then(keys =>
+ Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k)))
+ )
+ );
+ self.clients.claim();
+});
+
+self.addEventListener('fetch', (e) => {
+ // Only cache GET requests, skip API calls
+ if (e.request.method !== 'GET') return;
+
+ e.respondWith(
+ caches.match(e.request).then(cached => {
+ const fetching = fetch(e.request).then(response => {
+ if (response.ok) {
+ const clone = response.clone();
+ caches.open(CACHE_NAME).then(cache => cache.put(e.request, clone));
+ }
+ return response;
+ }).catch(() => cached);
+
+ return cached || fetching;
+ })
+ );
+});
diff --git a/src/main.jsx b/src/main.jsx
index fadf959..c7427ce 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -15,3 +15,10 @@ function Root() {
}
createRoot(document.getElementById('root')).render();
+
+// Register service worker for PWA
+if ('serviceWorker' in navigator) {
+ window.addEventListener('load', () => {
+ navigator.serviceWorker.register('/sw.js').catch(() => {});
+ });
+}