diff --git a/preview/index.html b/preview/index.html
new file mode 100644
index 0000000..da28569
--- /dev/null
+++ b/preview/index.html
@@ -0,0 +1 @@
+Loading...
diff --git a/preview/service-worker.js b/preview/service-worker.js
new file mode 100644
index 0000000..1213f69
--- /dev/null
+++ b/preview/service-worker.js
@@ -0,0 +1,59 @@
+const CACHE_NAME = 'webmaker-vfiles';
+self.addEventListener('fetch', function(event) {
+	// console.log('fetch event', event.request.url, event.request);
+	event.respondWith(
+		caches.open(CACHE_NAME).then(function(cache) {
+			return cache
+				.match(event.request)
+				.then(response => {
+					// console.log('responding with ', response);
+					if (response !== undefined) {
+						return response;
+					}
+					return fetch(event.request);
+				})
+				.catch(function(e) {
+					// Fall back to just fetch()ing the request if some unexpected error
+					// prevented the cached response from being valid.
+					console.warn(
+						'Couldn\'t serve response for "%s" from cache: %O',
+						event.request.url,
+						e
+					);
+					return fetch(event.request);
+				});
+		})
+	);
+	// }
+});
+
+function getContentType(url) {
+	if (url.match(/\.html$/)) {
+		return 'text/html; charset=UTF-8';
+	} else if (url.match(/\.css$/)) {
+		return 'text/css; charset=UTF-8';
+	}
+	if (url.match(/\.js$/)) {
+		return 'application/javascript; charset=UTF-8';
+	}
+	return 'text/html; charset=UTF-8';
+}
+
+self.addEventListener('message', function(e) {
+	// console.log('message aya sw main', e.data);
+	caches.open(CACHE_NAME).then(function(cache) {
+		for (const url in e.data) {
+			if (Object.prototype.hasOwnProperty.call(e.data, url)) {
+				// console.log('Received data', url, e.data[url])
+				cache.put(
+					url,
+					new Response(e.data[url], {
+						headers: {
+							'Content-Type': getContentType(url)
+						}
+					})
+				);
+			}
+		}
+	});
+});
diff --git a/preview/talk.html b/preview/talk.html
new file mode 100644
index 0000000..7d439ec
--- /dev/null
+++ b/preview/talk.html
@@ -0,0 +1,72 @@
+Hello
+
+<script>
+	if (
+		'serviceWorker' in navigator
+	) {
+		// Delay registration until after the page has loaded, to ensure that our
+		// precaching requests don't degrade the first visit experience.
+		// See https://developers.google.com/web/fundamentals/instant-and-offline/service-worker/registration
+		window.addEventListener('load', function () {
+			// Your service-worker.js *must* be located at the top-level directory relative to your site.
+			// It won't be able to control pages unless it's located at the same level or higher than them.
+			// *Don't* register service worker file in, e.g., a scripts/ sub-directory!
+			// See https://github.com/slightlyoff/ServiceWorker/issues/468
+			navigator.serviceWorker
+				.register('service-worker.js')
+				.then(function (reg) {
+					// updatefound is fired if service-worker.js changes.
+					reg.onupdatefound = function () {
+						// The updatefound event implies that reg.installing is set; see
+						// https://w3c.github.io/ServiceWorker/#service-worker-registration-updatefound-event
+						var installingWorker = reg.installing;
+
+						installingWorker.onstatechange = function () {
+							/* eslint-disable default-case */
+							switch (installingWorker.state) {
+								case 'installed':
+									if (navigator.serviceWorker.controller) {
+										// At this point, the old content will have been purged and the fresh content will
+										// have been added to the cache.
+										// It's the perfect time to display a "New content is available; please refresh."
+										// message in the page's interface.
+										console.log('New or updated content is available.');
+
+									} else {
+										// At this point, everything has been precached.
+										// It's the perfect time to display a "Content is cached for offline use." message.
+										console.log('Content is now available offline!');
+										if (window.alertsService) {
+											window.alertsService.add(
+												'Web Maker is now ready to be used offline.'
+											);
+										}
+									}
+									break;
+
+								case 'redundant':
+									console.error(
+										'The installing service worker became redundant.'
+									);
+									break;
+							}
+						};
+					};
+				})
+				.catch(function (e) {
+					console.error('Error during service worker registration:', e);
+				});
+		});
+	}
+
+</script>
+
+
+<script>
+	console.log('controller', navigator.serviceWorker.controller)
+	window.addEventListener('message', (e) => {
+		console.log(88, e.data);
+		navigator.serviceWorker.controller.postMessage(e.data);
+	});
+
+</script>
diff --git a/src/components/CodeEditor.jsx b/src/components/CodeEditor.jsx
index 06eae83..ceb59e6 100644
--- a/src/components/CodeEditor.jsx
+++ b/src/components/CodeEditor.jsx
@@ -244,8 +244,6 @@ export default class CodeEditor extends Component {
 	}
 
 	async initEditor() {
-		console.log('init editor');
-
 		this.editorReadyDeferred = deferred();
 		await this.loadDeps();
 
diff --git a/src/components/ContentWrapFiles.jsx b/src/components/ContentWrapFiles.jsx
index b222174..a139896 100644
--- a/src/components/ContentWrapFiles.jsx
+++ b/src/components/ContentWrapFiles.jsx
@@ -226,7 +226,7 @@ export default class ContentWrapFiles extends Component {
 		);
 		// Namespace all file paths to '/user' because thats what the service worker
 		// recognizes.
-		const files = linearizeFiles(assignFilePaths(duplicateFiles, '/user'));
+		const files = linearizeFiles(assignFilePaths(duplicateFiles, ''));
 
 		files.forEach(file => {
 			obj[file.path] = file.content || '';
@@ -245,13 +245,16 @@ export default class ContentWrapFiles extends Component {
 			}
 		});
 
-		navigator.serviceWorker.controller.postMessage(obj);
+		// navigator.serviceWorker.controller.postMessage(obj);
+		window.talkFrame.contentWindow.postMessage(obj, '*');
 
 		if (this.detachedWindow) {
 			log('✉️ Sending message to detached window');
 			this.detachedWindow.postMessage({ contents: '/user/index.html' }, '*');
 		} else {
-			this.frame.src = '/user/index.html';
+			setTimeout(() => {
+				this.frame.src = 'https://preview.webmaker.com:8083/index.html';
+			}, 10);
 		}
 	}
 	cleanupErrors() {
@@ -650,11 +653,15 @@ export default class ContentWrapFiles extends Component {
 				<div class="demo-side" id="js-demo-side" style="">
 					<iframe
 						ref={el => (this.frame = el)}
-						src="/user/index.html"
+						src="https://preview.webmaker.com:8083/index.html"
 						frameborder="0"
 						id="demo-frame"
 						allowfullscreen
 					/>
+					<iframe
+						src="https://preview.webmaker.com:8083/talk.html"
+						id="talkFrame"
+					/>
 					<PreviewDimension ref={comp => (this.previewDimension = comp)} />
 					<Console
 						logs={this.state.logs}