diff --git a/Dockerfile b/Dockerfile
index 1e8361fd2..9521c600e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,7 +23,6 @@ ARG OLLAMA_API_BASE_URL='/ollama/api'
 ENV ENV=prod
 ENV OLLAMA_API_BASE_URL $OLLAMA_API_BASE_URL
 ENV WEBUI_AUTH ""
-ENV WEBUI_DB_URL ""
 ENV WEBUI_JWT_SECRET_KEY "SECRET_KEY"
 
 WORKDIR /app
diff --git a/backend/apps/ollama/main.py b/backend/apps/ollama/main.py
index 98048ca53..a2a09fc79 100644
--- a/backend/apps/ollama/main.py
+++ b/backend/apps/ollama/main.py
@@ -59,9 +59,11 @@ def proxy(path):
     else:
         pass
 
+    r = None
+
     try:
         # Make a request to the target server
-        target_response = requests.request(
+        r = requests.request(
             method=request.method,
             url=target_url,
             data=data,
@@ -69,22 +71,37 @@ def proxy(path):
             stream=True,  # Enable streaming for server-sent events
         )
 
-        target_response.raise_for_status()
+        r.raise_for_status()
 
         # Proxy the target server's response to the client
         def generate():
-            for chunk in target_response.iter_content(chunk_size=8192):
+            for chunk in r.iter_content(chunk_size=8192):
                 yield chunk
 
-        response = Response(generate(), status=target_response.status_code)
+        response = Response(generate(), status=r.status_code)
 
         # Copy headers from the target server's response to the client's response
-        for key, value in target_response.headers.items():
+        for key, value in r.headers.items():
             response.headers[key] = value
 
         return response
     except Exception as e:
-        return jsonify({"detail": "Server Connection Error", "message": str(e)}), 400
+        error_detail = "Ollama WebUI: Server Connection Error"
+        if r != None:
+            res = r.json()
+            if "error" in res:
+                error_detail = f"Ollama: {res['error']}"
+            print(res)
+
+        return (
+            jsonify(
+                {
+                    "detail": error_detail,
+                    "message": str(e),
+                }
+            ),
+            400,
+        )
 
 
 if __name__ == "__main__":
diff --git a/backend/config.py b/backend/config.py
index 14ad30e4b..1dabe48ae 100644
--- a/backend/config.py
+++ b/backend/config.py
@@ -30,7 +30,7 @@ if ENV == "prod":
 # WEBUI_VERSION
 ####################################
 
-WEBUI_VERSION = os.environ.get("WEBUI_VERSION", "v1.0.0-alpha.21")
+WEBUI_VERSION = os.environ.get("WEBUI_VERSION", "v1.0.0-alpha.33")
 
 ####################################
 # WEBUI_AUTH
@@ -41,7 +41,7 @@ WEBUI_AUTH = True if os.environ.get("WEBUI_AUTH", "FALSE") == "TRUE" else False
 
 
 ####################################
-# WEBUI_DB
+# WEBUI_DB (Deprecated, Should be removed)
 ####################################
 
 
diff --git a/package-lock.json b/package-lock.json
index 7003749c0..bcfc72538 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
 				"katex": "^0.16.9",
 				"marked": "^9.1.0",
 				"svelte-french-toast": "^1.2.0",
+				"tippy.js": "^6.3.7",
 				"uuid": "^9.0.1"
 			},
 			"devDependencies": {
@@ -584,6 +585,15 @@
 			"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz",
 			"integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg=="
 		},
+		"node_modules/@popperjs/core": {
+			"version": "2.11.8",
+			"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+			"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/popperjs"
+			}
+		},
 		"node_modules/@rollup/plugin-commonjs": {
 			"version": "25.0.5",
 			"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.5.tgz",
@@ -3994,6 +4004,14 @@
 				"globrex": "^0.1.2"
 			}
 		},
+		"node_modules/tippy.js": {
+			"version": "6.3.7",
+			"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
+			"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
+			"dependencies": {
+				"@popperjs/core": "^2.9.0"
+			}
+		},
 		"node_modules/to-regex-range": {
 			"version": "5.0.1",
 			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -4160,9 +4178,9 @@
 			}
 		},
 		"node_modules/vite": {
-			"version": "4.4.11",
-			"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz",
-			"integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==",
+			"version": "4.5.1",
+			"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
+			"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
 			"dependencies": {
 				"esbuild": "^0.18.10",
 				"postcss": "^8.4.27",
@@ -4570,6 +4588,11 @@
 			"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz",
 			"integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg=="
 		},
+		"@popperjs/core": {
+			"version": "2.11.8",
+			"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+			"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
+		},
 		"@rollup/plugin-commonjs": {
 			"version": "25.0.5",
 			"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.5.tgz",
@@ -6885,6 +6908,14 @@
 				"globrex": "^0.1.2"
 			}
 		},
+		"tippy.js": {
+			"version": "6.3.7",
+			"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
+			"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
+			"requires": {
+				"@popperjs/core": "^2.9.0"
+			}
+		},
 		"to-regex-range": {
 			"version": "5.0.1",
 			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -6991,9 +7022,9 @@
 			"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="
 		},
 		"vite": {
-			"version": "4.4.11",
-			"resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz",
-			"integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==",
+			"version": "4.5.1",
+			"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
+			"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
 			"requires": {
 				"esbuild": "^0.18.10",
 				"fsevents": "~2.3.2",
diff --git a/package.json b/package.json
index 5b1a89eca..f90b99ad7 100644
--- a/package.json
+++ b/package.json
@@ -48,6 +48,7 @@
 		"katex": "^0.16.9",
 		"marked": "^9.1.0",
 		"svelte-french-toast": "^1.2.0",
+		"tippy.js": "^6.3.7",
 		"uuid": "^9.0.1"
 	}
-}
\ No newline at end of file
+}
diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte
index bc3a6a9d2..172485ca2 100644
--- a/src/lib/components/chat/MessageInput.svelte
+++ b/src/lib/components/chat/MessageInput.svelte
@@ -161,7 +161,7 @@
 						<div class="ml-2 mt-2 mb-1 flex space-x-2">
 							{#each files as file, fileIdx}
 								<div class=" relative group">
-									<img src={file.url} alt="input" class=" h-16 w-16 rounded-xl bg-cover" />
+									<img src={file.url} alt="input" class=" h-16 w-16 rounded-xl object-cover" />
 
 									<div class=" absolute -top-1 -right-1">
 										<button
@@ -235,6 +235,30 @@
 								e.target.style.height = '';
 								e.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px';
 							}}
+							on:paste={(e) => {
+								const clipboardData = e.clipboardData || window.clipboardData;
+
+								if (clipboardData && clipboardData.items) {
+									for (const item of clipboardData.items) {
+										if (item.type.indexOf('image') !== -1) {
+											const blob = item.getAsFile();
+											const reader = new FileReader();
+
+											reader.onload = function (e) {
+												files = [
+													...files,
+													{
+														type: 'image',
+														url: `${e.target.result}`
+													}
+												];
+											};
+
+											reader.readAsDataURL(blob);
+										}
+									}
+								}
+							}}
 						/>
 
 						<div class="self-end mb-2 flex space-x-0.5 mr-2">
diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte
index b08f10931..c6d534249 100644
--- a/src/lib/components/chat/Messages.svelte
+++ b/src/lib/components/chat/Messages.svelte
@@ -2,6 +2,7 @@
 	import { marked } from 'marked';
 
 	import { v4 as uuidv4 } from 'uuid';
+	import tippy from 'tippy.js';
 	import hljs from 'highlight.js';
 	import 'highlight.js/styles/github-dark.min.css';
 	import auto_render from 'katex/dist/contrib/auto-render.mjs';
@@ -29,6 +30,35 @@
 			renderLatex();
 			hljs.highlightAll();
 			createCopyCodeBlockButton();
+
+			for (const message of messages) {
+				if (message.info) {
+					tippy(`#info-${message.id}`, {
+						content: `<span class="text-xs">token/s: ${
+							`${
+								Math.round(
+									((message.info.eval_count ?? 0) / (message.info.eval_duration / 1000000000)) * 100
+								) / 100
+							} tokens` ?? 'N/A'
+						}<br/>
+						total_duration: ${
+							Math.round(((message.info.total_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
+						}ms<br/>
+						load_duration: ${
+							Math.round(((message.info.load_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
+						}ms<br/>
+						prompt_eval_count: ${message.info.prompt_eval_count ?? 'N/A'}<br/>
+						prompt_eval_duration: ${
+							Math.round(((message.info.prompt_eval_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
+						}ms<br/>
+						eval_count: ${message.info.eval_count ?? 'N/A'}<br/>
+						eval_duration: ${
+							Math.round(((message.info.eval_duration ?? 0) / 1000000) * 100) / 100 ?? 'N/A'
+						}ms</span>`,
+						allowHTML: true
+					});
+				}
+			}
 		})();
 	}
 
@@ -861,6 +891,33 @@
 															</svg>
 														</button>
 
+														{#if message.info}
+															<button
+																class=" {messageIdx + 1 === messages.length
+																	? 'visible'
+																	: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition whitespace-pre-wrap"
+																on:click={() => {
+																	console.log(message);
+																}}
+																id="info-{message.id}"
+															>
+																<svg
+																	xmlns="http://www.w3.org/2000/svg"
+																	fill="none"
+																	viewBox="0 0 24 24"
+																	stroke-width="1.5"
+																	stroke="currentColor"
+																	class="w-4 h-4"
+																>
+																	<path
+																		stroke-linecap="round"
+																		stroke-linejoin="round"
+																		d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"
+																	/>
+																</svg>
+															</button>
+														{/if}
+
 														{#if messageIdx + 1 === messages.length}
 															<button
 																type="button"
diff --git a/src/lib/components/chat/SettingsModal.svelte b/src/lib/components/chat/SettingsModal.svelte
index fe17475e6..67617218b 100644
--- a/src/lib/components/chat/SettingsModal.svelte
+++ b/src/lib/components/chat/SettingsModal.svelte
@@ -4,7 +4,7 @@
 	import { WEB_UI_VERSION, OLLAMA_API_BASE_URL } from '$lib/constants';
 	import toast from 'svelte-french-toast';
 	import { onMount } from 'svelte';
-	import { config, models, settings, user } from '$lib/stores';
+	import { config, info, models, settings, user } from '$lib/stores';
 	import { splitStream, getGravatarURL } from '$lib/utils';
 	import Advanced from './Settings/Advanced.svelte';
 
@@ -22,6 +22,7 @@
 	// General
 	let API_BASE_URL = OLLAMA_API_BASE_URL;
 	let theme = 'dark';
+	let notificationEnabled = false;
 	let system = '';
 
 	// Advanced
@@ -51,6 +52,8 @@
 	// Addons
 	let titleAutoGenerate = true;
 	let speechAutoSend = false;
+	let responseAutoCopy = false;
+
 	let gravatarEmail = '';
 	let OPENAI_API_KEY = '';
 
@@ -108,6 +111,41 @@
 		saveSettings({ titleAutoGenerate: titleAutoGenerate });
 	};
 
+	const toggleNotification = async () => {
+		const permission = await Notification.requestPermission();
+
+		if (permission === 'granted') {
+			notificationEnabled = !notificationEnabled;
+			saveSettings({ notificationEnabled: notificationEnabled });
+		} else {
+			toast.error(
+				'Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.'
+			);
+		}
+	};
+
+	const toggleResponseAutoCopy = async () => {
+		const permission = await navigator.clipboard
+			.readText()
+			.then(() => {
+				return 'granted';
+			})
+			.catch(() => {
+				return '';
+			});
+
+		console.log(permission);
+
+		if (permission === 'granted') {
+			responseAutoCopy = !responseAutoCopy;
+			saveSettings({ responseAutoCopy: responseAutoCopy });
+		} else {
+			toast.error(
+				'Clipboard write permission denied. Please check your browser settings to grant the necessary access.'
+			);
+		}
+	};
+
 	const toggleAuthHeader = async () => {
 		authEnabled = !authEnabled;
 	};
@@ -153,6 +191,13 @@
 						if (data.status) {
 							if (!data.digest) {
 								toast.success(data.status);
+
+								if (data.status === 'success') {
+									const notification = new Notification(`Ollama`, {
+										body: `Model '${modelTag}' has been successfully downloaded.`,
+										icon: '/favicon.png'
+									});
+								}
 							} else {
 								digest = data.digest;
 								if (data.completed) {
@@ -297,6 +342,8 @@
 		console.log(settings);
 
 		theme = localStorage.theme ?? 'dark';
+		notificationEnabled = settings.notificationEnabled ?? false;
+
 		API_BASE_URL = settings.API_BASE_URL ?? OLLAMA_API_BASE_URL;
 		system = settings.system ?? '';
 
@@ -312,6 +359,8 @@
 
 		titleAutoGenerate = settings.titleAutoGenerate ?? true;
 		speechAutoSend = settings.speechAutoSend ?? false;
+		responseAutoCopy = settings.responseAutoCopy ?? false;
+
 		gravatarEmail = settings.gravatarEmail ?? '';
 		OPENAI_API_KEY = settings.OPENAI_API_KEY ?? '';
 
@@ -509,8 +558,10 @@
 				{#if selectedTab === 'general'}
 					<div class="flex flex-col space-y-3">
 						<div>
-							<div class=" py-1 flex w-full justify-between">
-								<div class=" self-center text-sm font-medium">Theme</div>
+							<div class=" mb-1 text-sm font-medium">WebUI Settings</div>
+
+							<div class=" py-0.5 flex w-full justify-between">
+								<div class=" self-center text-xs font-medium">Theme</div>
 
 								<button
 									class="p-1 px-3 text-xs flex rounded transition"
@@ -548,6 +599,26 @@
 									{/if}
 								</button>
 							</div>
+
+							<div>
+								<div class=" py-0.5 flex w-full justify-between">
+									<div class=" self-center text-xs font-medium">Notification</div>
+
+									<button
+										class="p-1 px-3 text-xs flex rounded transition"
+										on:click={() => {
+											toggleNotification();
+										}}
+										type="button"
+									>
+										{#if notificationEnabled === true}
+											<span class="ml-2 self-center">On</span>
+										{:else}
+											<span class="ml-2 self-center">Off</span>
+										{/if}
+									</button>
+								</div>
+							</div>
 						</div>
 
 						<hr class=" dark:border-gray-700" />
@@ -802,44 +873,68 @@
 					>
 						<div class=" space-y-3">
 							<div>
-								<div class=" py-1 flex w-full justify-between">
-									<div class=" self-center text-sm font-medium">Title Auto Generation</div>
+								<div class=" mb-1 text-sm font-medium">WebUI Add-ons</div>
 
-									<button
-										class="p-1 px-3 text-xs flex rounded transition"
-										on:click={() => {
-											toggleTitleAutoGenerate();
-										}}
-										type="button"
-									>
-										{#if titleAutoGenerate === true}
-											<span class="ml-2 self-center">On</span>
-										{:else}
-											<span class="ml-2 self-center">Off</span>
-										{/if}
-									</button>
+								<div>
+									<div class=" py-0.5 flex w-full justify-between">
+										<div class=" self-center text-xs font-medium">Title Auto Generation</div>
+
+										<button
+											class="p-1 px-3 text-xs flex rounded transition"
+											on:click={() => {
+												toggleTitleAutoGenerate();
+											}}
+											type="button"
+										>
+											{#if titleAutoGenerate === true}
+												<span class="ml-2 self-center">On</span>
+											{:else}
+												<span class="ml-2 self-center">Off</span>
+											{/if}
+										</button>
+									</div>
 								</div>
-							</div>
 
-							<hr class=" dark:border-gray-700" />
+								<div>
+									<div class=" py-0.5 flex w-full justify-between">
+										<div class=" self-center text-xs font-medium">Voice Input Auto-Send</div>
 
-							<div>
-								<div class=" py-1 flex w-full justify-between">
-									<div class=" self-center text-sm font-medium">Voice Input Auto-Send</div>
+										<button
+											class="p-1 px-3 text-xs flex rounded transition"
+											on:click={() => {
+												toggleSpeechAutoSend();
+											}}
+											type="button"
+										>
+											{#if speechAutoSend === true}
+												<span class="ml-2 self-center">On</span>
+											{:else}
+												<span class="ml-2 self-center">Off</span>
+											{/if}
+										</button>
+									</div>
+								</div>
 
-									<button
-										class="p-1 px-3 text-xs flex rounded transition"
-										on:click={() => {
-											toggleSpeechAutoSend();
-										}}
-										type="button"
-									>
-										{#if speechAutoSend === true}
-											<span class="ml-2 self-center">On</span>
-										{:else}
-											<span class="ml-2 self-center">Off</span>
-										{/if}
-									</button>
+								<div>
+									<div class=" py-0.5 flex w-full justify-between">
+										<div class=" self-center text-xs font-medium">
+											Response AutoCopy to Clipboard
+										</div>
+
+										<button
+											class="p-1 px-3 text-xs flex rounded transition"
+											on:click={() => {
+												toggleResponseAutoCopy();
+											}}
+											type="button"
+										>
+											{#if responseAutoCopy === true}
+												<span class="ml-2 self-center">On</span>
+											{:else}
+												<span class="ml-2 self-center">Off</span>
+											{/if}
+										</button>
+									</div>
 								</div>
 							</div>
 
@@ -1029,6 +1124,17 @@
 
 							<hr class=" dark:border-gray-700" />
 
+							<div>
+								<div class=" mb-2.5 text-sm font-medium">Ollama Version</div>
+								<div class="flex w-full">
+									<div class="flex-1 text-xs text-gray-700 dark:text-gray-200">
+										{$info?.ollama?.version ?? 'N/A'}
+									</div>
+								</div>
+							</div>
+
+							<hr class=" dark:border-gray-700" />
+
 							<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
 								Created by <a
 									class=" text-gray-500 dark:text-gray-300 font-medium"
diff --git a/src/lib/components/layout/Navbar.svelte b/src/lib/components/layout/Navbar.svelte
index 9bf15a07d..bcd66ee9e 100644
--- a/src/lib/components/layout/Navbar.svelte
+++ b/src/lib/components/layout/Navbar.svelte
@@ -2,51 +2,102 @@
 	import { v4 as uuidv4 } from 'uuid';
 
 	import { goto } from '$app/navigation';
-	import { chatId } from '$lib/stores';
+	import { chatId, db, modelfiles } from '$lib/stores';
+	import toast from 'svelte-french-toast';
 
 	export let title: string = 'Ollama Web UI';
+	export let shareEnabled: boolean = false;
+
+	const shareChat = async () => {
+		const chat = await $db.getChatById($chatId);
+		console.log('share', chat);
+		toast.success('Redirecting you to OllamaHub');
+
+		const url = 'https://ollamahub.com';
+		// const url = 'http://localhost:5173';
+
+		const tab = await window.open(`${url}/chats/upload`, '_blank');
+		window.addEventListener(
+			'message',
+			(event) => {
+				if (event.origin !== url) return;
+				if (event.data === 'loaded') {
+					tab.postMessage(
+						JSON.stringify({
+							chat: chat,
+							modelfiles: $modelfiles.filter((modelfile) => chat.models.includes(modelfile.tagName))
+						}),
+						'*'
+					);
+				}
+			},
+			false
+		);
+	};
 </script>
 
-<div
-	class=" fixed top-0 flex flex-row justify-center bg-white/95 dark:bg-gray-800/90 dark:text-gray-200 backdrop-blur-xl w-full z-30"
+<nav
+	id="nav"
+	class=" fixed py-2.5 top-0 flex flex-row justify-center bg-white/95 dark:bg-gray-800/90 dark:text-gray-200 backdrop-blur-xl w-screen z-30"
 >
-	<div class="basis-full">
-		<nav class="py-3" id="nav">
-			<div class=" flex max-w-3xl mx-auto px-3">
-				<div class="flex w-full max-w-full overflow-hidden text-ellipsis whitespace-nowrap">
-					<div class="pr-2">
-						<button
-							class=" cursor-pointer p-1 flex dark:hover:bg-gray-700 rounded-lg transition"
-							on:click={async () => {
-								console.log('newChat');
-								goto('/');
-								await chatId.set(uuidv4());
-							}}
+	<div class=" flex max-w-3xl w-full mx-auto px-3">
+		<div class="flex w-full max-w-full">
+			<div class="pr-2 self-center">
+				<button
+					class=" cursor-pointer p-1 flex dark:hover:bg-gray-700 rounded-lg transition"
+					on:click={async () => {
+						console.log('newChat');
+						goto('/');
+						await chatId.set(uuidv4());
+					}}
+				>
+					<div class=" m-auto self-center">
+						<svg
+							xmlns="http://www.w3.org/2000/svg"
+							viewBox="0 0 20 20"
+							fill="currentColor"
+							class="w-5 h-5"
 						>
-							<div class=" m-auto self-center">
-								<svg
-									xmlns="http://www.w3.org/2000/svg"
-									viewBox="0 0 20 20"
-									fill="currentColor"
-									class="w-5 h-5"
-								>
-									<path
-										d="M5.433 13.917l1.262-3.155A4 4 0 017.58 9.42l6.92-6.918a2.121 2.121 0 013 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 01-.65-.65z"
-									/>
-									<path
-										d="M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0010 3H4.75A2.75 2.75 0 002 5.75v9.5A2.75 2.75 0 004.75 18h9.5A2.75 2.75 0 0017 15.25V10a.75.75 0 00-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5z"
-									/>
-								</svg>
-							</div>
-						</button>
+							<path
+								d="M5.433 13.917l1.262-3.155A4 4 0 017.58 9.42l6.92-6.918a2.121 2.121 0 013 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 01-.65-.65z"
+							/>
+							<path
+								d="M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0010 3H4.75A2.75 2.75 0 002 5.75v9.5A2.75 2.75 0 004.75 18h9.5A2.75 2.75 0 0017 15.25V10a.75.75 0 00-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5z"
+							/>
+						</svg>
 					</div>
-					<div
-						class=" flex-1 self-center font-medium overflow-hidden text-ellipsis whitespace-nowrap w-[80vw] pr-4"
-					>
-						{title != '' ? title : 'Ollama Web UI'}
-					</div>
-				</div>
+				</button>
 			</div>
-		</nav>
+			<div class=" flex-1 self-center font-medium text-ellipsis whitespace-nowrap overflow-hidden">
+				{title != '' ? title : 'Ollama Web UI'}
+			</div>
+
+			{#if shareEnabled}
+				<div class="pl-2">
+					<button
+						class=" cursor-pointer p-2 flex dark:hover:bg-gray-700 rounded-lg transition border dark:border-gray-600"
+						on:click={async () => {
+							shareChat();
+						}}
+					>
+						<div class=" m-auto self-center">
+							<svg
+								xmlns="http://www.w3.org/2000/svg"
+								viewBox="0 0 20 20"
+								fill="currentColor"
+								class="w-4 h-4"
+							>
+								<path
+									d="M9.25 13.25a.75.75 0 001.5 0V4.636l2.955 3.129a.75.75 0 001.09-1.03l-4.25-4.5a.75.75 0 00-1.09 0l-4.25 4.5a.75.75 0 101.09 1.03L9.25 4.636v8.614z"
+								/>
+								<path
+									d="M3.5 12.75a.75.75 0 00-1.5 0v2.5A2.75 2.75 0 004.75 18h10.5A2.75 2.75 0 0018 15.25v-2.5a.75.75 0 00-1.5 0v2.5c0 .69-.56 1.25-1.25 1.25H4.75c-.69 0-1.25-.56-1.25-1.25v-2.5z"
+								/>
+							</svg>
+						</div>
+					</button>
+				</div>
+			{/if}
+		</div>
 	</div>
-</div>
+</nav>
diff --git a/src/lib/stores/index.ts b/src/lib/stores/index.ts
index 342e64943..9962b4ac7 100644
--- a/src/lib/stores/index.ts
+++ b/src/lib/stores/index.ts
@@ -1,6 +1,7 @@
 import { writable } from 'svelte/store';
 
 // Backend
+export const info = writable({});
 export const config = writable(undefined);
 export const user = writable(undefined);
 
diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts
index 220969949..2d9f1b31e 100644
--- a/src/lib/utils/index.ts
+++ b/src/lib/utils/index.ts
@@ -65,3 +65,38 @@ export const getGravatarURL = (email) => {
 	// Grab the actual image URL
 	return `https://www.gravatar.com/avatar/${hash}`;
 };
+
+const copyToClipboard = (text) => {
+	if (!navigator.clipboard) {
+		var textArea = document.createElement('textarea');
+		textArea.value = text;
+
+		// Avoid scrolling to bottom
+		textArea.style.top = '0';
+		textArea.style.left = '0';
+		textArea.style.position = 'fixed';
+
+		document.body.appendChild(textArea);
+		textArea.focus();
+		textArea.select();
+
+		try {
+			var successful = document.execCommand('copy');
+			var msg = successful ? 'successful' : 'unsuccessful';
+			console.log('Fallback: Copying text command was ' + msg);
+		} catch (err) {
+			console.error('Fallback: Oops, unable to copy', err);
+		}
+
+		document.body.removeChild(textArea);
+		return;
+	}
+	navigator.clipboard.writeText(text).then(
+		function () {
+			console.log('Async: Copying to clipboard was successful!');
+		},
+		function (err) {
+			console.error('Async: Could not copy text: ', err);
+		}
+	);
+};
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte
index e837741e5..4f4774232 100644
--- a/src/routes/(app)/+layout.svelte
+++ b/src/routes/(app)/+layout.svelte
@@ -6,6 +6,7 @@
 
 	import {
 		config,
+		info,
 		user,
 		showSettings,
 		settings,
@@ -21,6 +22,7 @@
 	import toast from 'svelte-french-toast';
 	import { OLLAMA_API_BASE_URL, WEBUI_API_BASE_URL } from '$lib/constants';
 
+	let requiredOllamaVersion = '0.1.16';
 	let loaded = false;
 
 	const getModels = async () => {
@@ -160,33 +162,116 @@
 		};
 	};
 
+	const getOllamaVersion = async () => {
+		const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/version`, {
+			method: 'GET',
+			headers: {
+				Accept: 'application/json',
+				'Content-Type': 'application/json',
+				...($settings.authHeader && { Authorization: $settings.authHeader }),
+				...($user && { Authorization: `Bearer ${localStorage.token}` })
+			}
+		})
+			.then(async (res) => {
+				if (!res.ok) throw await res.json();
+				return res.json();
+			})
+			.catch((error) => {
+				console.log(error);
+				if ('detail' in error) {
+					toast.error(error.detail);
+				} else {
+					toast.error('Server connection failed');
+				}
+				return null;
+			});
+
+		console.log(res);
+
+		return res?.version ?? '0';
+	};
+
+	const setOllamaVersion = async (ollamaVersion) => {
+		await info.set({ ...$info, ollama: { version: ollamaVersion } });
+
+		if (
+			ollamaVersion.localeCompare(requiredOllamaVersion, undefined, {
+				numeric: true,
+				sensitivity: 'case',
+				caseFirst: 'upper'
+			}) < 0
+		) {
+			toast.error(`Ollama Version: ${ollamaVersion}`);
+		}
+	};
+
 	onMount(async () => {
 		if ($config && $config.auth && $user === undefined) {
 			await goto('/auth');
 		}
 
-		await settings.set(JSON.parse(localStorage.getItem('settings') ?? JSON.stringify($settings)));
+		await settings.set(JSON.parse(localStorage.getItem('settings') ?? '{}'));
 
-		let _models = await getModels();
-		await models.set(_models);
-		let _db = await getDB();
-		await db.set(_db);
-
-		await modelfiles.set(
-			JSON.parse(localStorage.getItem('modelfiles') ?? JSON.stringify($modelfiles))
-		);
+		await models.set(await getModels());
+		await modelfiles.set(JSON.parse(localStorage.getItem('modelfiles') ?? '[]'));
 
 		modelfiles.subscribe(async () => {
 			await models.set(await getModels());
 		});
 
+		let _db = await getDB();
+		await db.set(_db);
+
+		await setOllamaVersion(await getOllamaVersion());
+
 		await tick();
 		loaded = true;
 	});
 </script>
 
 {#if loaded}
-	<div class="app">
+	<div class="app relative">
+		{#if ($info?.ollama?.version ?? '0').localeCompare( requiredOllamaVersion, undefined, { numeric: true, sensitivity: 'case', caseFirst: 'upper' } ) < 0}
+			<div class="absolute w-full h-full flex z-50">
+				<div
+					class="absolute rounded-xl w-full h-full backdrop-blur bg-gray-900/60 flex justify-center"
+				>
+					<div class="m-auto pb-44">
+						<div class="text-center dark:text-white text-2xl font-medium z-50">
+							Ollama Update Required
+						</div>
+
+						<div class=" mt-4 text-center max-w-md text-sm dark:text-gray-200">
+							Oops! It seems like your Ollama needs a little attention. <br
+								class=" hidden sm:flex"
+							/>
+							We encountered a connection issue or noticed that you're running an outdated version. Please
+							update to
+							<span class=" dark:text-white font-medium">{requiredOllamaVersion} or above</span>.
+						</div>
+
+						<div class=" mt-6 mx-auto relative group w-fit">
+							<button
+								class="relative z-20 flex px-5 py-2 rounded-full bg-gray-100 hover:bg-gray-200 transition font-medium text-sm"
+								on:click={async () => {
+									await setOllamaVersion(await getOllamaVersion());
+								}}
+							>
+								Check Again
+							</button>
+
+							<button
+								class="text-xs text-center w-full mt-2 text-gray-400 underline"
+								on:click={async () => {
+									await setOllamaVersion(requiredOllamaVersion);
+								}}>Close</button
+							>
+						</div>
+					</div>
+				</div>
+			</div>
+		{/if}
+
 		<div
 			class=" text-gray-700 dark:text-gray-100 bg-white dark:bg-gray-800 min-h-screen overflow-auto flex flex-row"
 		>
diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte
index 7c0c87b4d..d0b83b80d 100644
--- a/src/routes/(app)/+page.svelte
+++ b/src/routes/(app)/+page.svelte
@@ -84,11 +84,45 @@
 		let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
 		console.log(_settings);
 		settings.set({
-			...$settings,
 			..._settings
 		});
 	};
 
+	const copyToClipboard = (text) => {
+		if (!navigator.clipboard) {
+			var textArea = document.createElement('textarea');
+			textArea.value = text;
+
+			// Avoid scrolling to bottom
+			textArea.style.top = '0';
+			textArea.style.left = '0';
+			textArea.style.position = 'fixed';
+
+			document.body.appendChild(textArea);
+			textArea.focus();
+			textArea.select();
+
+			try {
+				var successful = document.execCommand('copy');
+				var msg = successful ? 'successful' : 'unsuccessful';
+				console.log('Fallback: Copying text command was ' + msg);
+			} catch (err) {
+				console.error('Fallback: Oops, unable to copy', err);
+			}
+
+			document.body.removeChild(textArea);
+			return;
+		}
+		navigator.clipboard.writeText(text).then(
+			function () {
+				console.log('Async: Copying to clipboard was successful!');
+			},
+			function (err) {
+				console.error('Async: Could not copy text: ', err);
+			}
+		);
+	};
+
 	//////////////////////////
 	// Ollama functions
 	//////////////////////////
@@ -213,12 +247,34 @@
 								responseMessage.context = data.context ?? null;
 								responseMessage.info = {
 									total_duration: data.total_duration,
+									load_duration: data.load_duration,
+									sample_count: data.sample_count,
+									sample_duration: data.sample_duration,
 									prompt_eval_count: data.prompt_eval_count,
 									prompt_eval_duration: data.prompt_eval_duration,
 									eval_count: data.eval_count,
 									eval_duration: data.eval_duration
 								};
 								messages = messages;
+
+								if ($settings.notificationEnabled && !document.hasFocus()) {
+									const notification = new Notification(
+										selectedModelfile
+											? `${
+													selectedModelfile.title.charAt(0).toUpperCase() +
+													selectedModelfile.title.slice(1)
+											  }`
+											: `Ollama - ${model}`,
+										{
+											body: responseMessage.content,
+											icon: selectedModelfile?.imageUrl ?? '/favicon.png'
+										}
+									);
+								}
+
+								if ($settings.responseAutoCopy) {
+									copyToClipboard(responseMessage.content);
+								}
 							}
 						}
 					}
@@ -423,6 +479,18 @@
 				stopResponseFlag = false;
 
 				await tick();
+
+				if ($settings.notificationEnabled && !document.hasFocus()) {
+					const notification = new Notification(`OpenAI ${model}`, {
+						body: responseMessage.content,
+						icon: '/favicon.png'
+					});
+				}
+
+				if ($settings.responseAutoCopy) {
+					copyToClipboard(responseMessage.content);
+				}
+
 				if (autoScroll) {
 					window.scrollTo({ top: document.body.scrollHeight });
 				}
@@ -566,7 +634,7 @@
 	}}
 />
 
-<Navbar {title} />
+<Navbar {title} shareEnabled={messages.length > 0} />
 <div class="min-h-screen w-full flex justify-center">
 	<div class=" py-2.5 flex flex-col justify-between w-full">
 		<div class="max-w-2xl mx-auto w-full px-3 md:px-0 mt-10">
diff --git a/src/routes/(app)/c/[id]/+page.svelte b/src/routes/(app)/c/[id]/+page.svelte
index f108ba222..bf7207fb3 100644
--- a/src/routes/(app)/c/[id]/+page.svelte
+++ b/src/routes/(app)/c/[id]/+page.svelte
@@ -82,10 +82,11 @@
 					: convertMessagesToHistory(chat.messages);
 			title = chat.title;
 
+			let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
 			await settings.set({
-				...$settings,
-				system: chat.system ?? $settings.system,
-				options: chat.options ?? $settings.options
+				..._settings,
+				system: chat.system ?? _settings.system,
+				options: chat.options ?? _settings.options
 			});
 			autoScroll = true;
 
@@ -101,6 +102,41 @@
 		}
 	};
 
+	const copyToClipboard = (text) => {
+		if (!navigator.clipboard) {
+			var textArea = document.createElement('textarea');
+			textArea.value = text;
+
+			// Avoid scrolling to bottom
+			textArea.style.top = '0';
+			textArea.style.left = '0';
+			textArea.style.position = 'fixed';
+
+			document.body.appendChild(textArea);
+			textArea.focus();
+			textArea.select();
+
+			try {
+				var successful = document.execCommand('copy');
+				var msg = successful ? 'successful' : 'unsuccessful';
+				console.log('Fallback: Copying text command was ' + msg);
+			} catch (err) {
+				console.error('Fallback: Oops, unable to copy', err);
+			}
+
+			document.body.removeChild(textArea);
+			return;
+		}
+		navigator.clipboard.writeText(text).then(
+			function () {
+				console.log('Async: Copying to clipboard was successful!');
+			},
+			function (err) {
+				console.error('Async: Could not copy text: ', err);
+			}
+		);
+	};
+
 	//////////////////////////
 	// Ollama functions
 	//////////////////////////
@@ -225,12 +261,34 @@
 								responseMessage.context = data.context ?? null;
 								responseMessage.info = {
 									total_duration: data.total_duration,
+									load_duration: data.load_duration,
+									sample_count: data.sample_count,
+									sample_duration: data.sample_duration,
 									prompt_eval_count: data.prompt_eval_count,
 									prompt_eval_duration: data.prompt_eval_duration,
 									eval_count: data.eval_count,
 									eval_duration: data.eval_duration
 								};
 								messages = messages;
+
+								if ($settings.notificationEnabled && !document.hasFocus()) {
+									const notification = new Notification(
+										selectedModelfile
+											? `${
+													selectedModelfile.title.charAt(0).toUpperCase() +
+													selectedModelfile.title.slice(1)
+											  }`
+											: `Ollama - ${model}`,
+										{
+											body: responseMessage.content,
+											icon: selectedModelfile?.imageUrl ?? '/favicon.png'
+										}
+									);
+								}
+
+								if ($settings.responseAutoCopy) {
+									copyToClipboard(responseMessage.content);
+								}
 							}
 						}
 					}
@@ -435,6 +493,18 @@
 				stopResponseFlag = false;
 
 				await tick();
+
+				if ($settings.notificationEnabled && !document.hasFocus()) {
+					const notification = new Notification(`OpenAI ${model}`, {
+						body: responseMessage.content,
+						icon: '/favicon.png'
+					});
+				}
+
+				if ($settings.responseAutoCopy) {
+					copyToClipboard(responseMessage.content);
+				}
+
 				if (autoScroll) {
 					window.scrollTo({ top: document.body.scrollHeight });
 				}
@@ -579,7 +649,7 @@
 />
 
 {#if loaded}
-	<Navbar {title} />
+	<Navbar {title} shareEnabled={messages.length > 0} />
 	<div class="min-h-screen w-full flex justify-center">
 		<div class=" py-2.5 flex flex-col justify-between w-full">
 			<div class="max-w-2xl mx-auto w-full px-3 md:px-0 mt-10">
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 199265536..7479f5598 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -7,7 +7,7 @@
 
 	import '../app.css';
 	import '../tailwind.css';
-
+	import 'tippy.js/dist/tippy.css';
 	let loaded = false;
 
 	onMount(async () => {