about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--package.json32
-rw-r--r--rollup.config.js15
-rw-r--r--src/assets/images/libredirect.svg2
-rw-r--r--src/assets/javascripts/localise.js34
-rw-r--r--src/assets/javascripts/utils.js8
-rw-r--r--src/config.json5
-rw-r--r--src/manifest.json4
-rw-r--r--src/pages/components/Button.svelte (renamed from src/pages/src/components/Button.svelte)2
-rw-r--r--src/pages/components/Checkbox.svelte (renamed from src/pages/src/components/Checkbox.svelte)19
-rw-r--r--src/pages/components/Input.svelte (renamed from src/pages/src/components/Input.svelte)7
-rw-r--r--src/pages/components/Label.svelte (renamed from src/pages/src/components/Label.svelte)0
-rw-r--r--src/pages/components/Row.svelte (renamed from src/pages/src/components/Row.svelte)2
-rw-r--r--src/pages/components/Select.svelte (renamed from src/pages/src/components/Select.svelte)2
-rw-r--r--src/pages/fonts/Inter-VariableFont_slnt,wght.ttf (renamed from src/pages/stylesheets/Inter-VariableFont_slnt,wght.ttf)bin803384 -> 803384 bytes
-rw-r--r--src/pages/fonts/Vazirmatn-VariableFont_wght.ttf (renamed from src/pages/stylesheets/Vazirmatn-VariableFont_wght.ttf)bin285620 -> 285620 bytes
-rw-r--r--src/pages/fonts/styles.css13
-rw-r--r--src/pages/icons/AboutIcon.svelte (renamed from src/pages/src/icons/AboutIcon.svelte)0
-rw-r--r--src/pages/icons/AddIcon.svelte (renamed from src/pages/src/icons/AddIcon.svelte)0
-rw-r--r--src/pages/icons/CloseIcon.svelte (renamed from src/pages/src/icons/CloseIcon.svelte)0
-rw-r--r--src/pages/icons/CopyIcon.svelte12
-rw-r--r--src/pages/icons/ExportIcon.svelte (renamed from src/pages/src/icons/ExportIcon.svelte)9
-rw-r--r--src/pages/icons/GeneralIcon.svelte (renamed from src/pages/src/icons/GeneralIcon.svelte)0
-rw-r--r--src/pages/icons/ImportIcon.svelte12
-rw-r--r--src/pages/icons/PingIcon.svelte (renamed from src/pages/src/icons/PingIcon.svelte)9
-rw-r--r--src/pages/icons/RedirectIcon.svelte10
-rw-r--r--src/pages/icons/RedirectToOriginalIcon.svelte13
-rw-r--r--src/pages/icons/ResetIcon.svelte (renamed from src/pages/src/icons/ResetIcon.svelte)1
-rw-r--r--src/pages/icons/ServicesIcon.svelte (renamed from src/pages/src/icons/ServicesIcon.svelte)0
-rw-r--r--src/pages/icons/SettingsIcon.svelte12
-rw-r--r--src/pages/icons/SwitchInstanceIcon.svelte15
-rw-r--r--src/pages/options/index.html17
-rw-r--r--src/pages/options/init.js51
-rw-r--r--src/pages/options_src/App.svelte139
-rw-r--r--src/pages/options_src/General/Exceptions.svelte (renamed from src/pages/src/General/Exceptions.svelte)22
-rw-r--r--src/pages/options_src/General/General.svelte79
-rw-r--r--src/pages/options_src/General/SettingsButtons.svelte (renamed from src/pages/src/General/SettingsButtons.svelte)65
-rw-r--r--src/pages/options_src/Services/FrontendIcon.svelte43
-rw-r--r--src/pages/options_src/Services/Instances.svelte (renamed from src/pages/src/Services/Instances.svelte)100
-rw-r--r--src/pages/options_src/Services/RedirectType.svelte102
-rw-r--r--src/pages/options_src/Services/ServiceIcon.svelte40
-rw-r--r--src/pages/options_src/Services/Services.svelte202
-rw-r--r--src/pages/options_src/Sidebar.svelte68
-rw-r--r--src/pages/options_src/main.js (renamed from src/pages/src/main.js)0
-rw-r--r--src/pages/options_src/stores.js (renamed from src/pages/src/stores.js)0
-rw-r--r--src/pages/popup/index.html17
-rw-r--r--src/pages/popup/popup.js119
-rw-r--r--src/pages/popup/popup.pug53
-rw-r--r--src/pages/popup/style.css65
-rw-r--r--src/pages/popup/switches.pug14
-rw-r--r--src/pages/popup_src/App.svelte (renamed from src/pages/src/App.svelte)36
-rw-r--r--src/pages/popup_src/Buttons.svelte118
-rw-r--r--src/pages/popup_src/components/Row.svelte13
-rw-r--r--src/pages/popup_src/components/ServiceIcon.svelte40
-rw-r--r--src/pages/popup_src/components/Switch.svelte67
-rw-r--r--src/pages/popup_src/main.js7
-rw-r--r--src/pages/popup_src/stores.js5
-rw-r--r--src/pages/src/General/General.svelte70
-rw-r--r--src/pages/src/Services/RedirectType.svelte84
-rw-r--r--src/pages/src/Services/Services.svelte119
-rw-r--r--src/pages/src/Sidebar.svelte43
-rw-r--r--src/pages/src/components/RowCheckbox.svelte14
-rw-r--r--src/pages/src/components/RowSelect.svelte19
-rw-r--r--src/pages/src/icons/ImportIcon.svelte5
-rw-r--r--src/pages/stylesheets/styles.css449
65 files changed, 1231 insertions, 1297 deletions
diff --git a/.gitignore b/.gitignore
index 7ca34ebb..f9768f05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,6 @@ nod
 node_modules
 package-lock.json
 .vscode
-src/pages/options/index.html
-src/pages/popup/popup.html
 pnpm-lock.yaml
-src/pages/options/build
\ No newline at end of file
+src/pages/options/build
+src/pages/popup/build
\ No newline at end of file
diff --git a/package.json b/package.json
index 234dd5e1..2a79b660 100644
--- a/package.json
+++ b/package.json
@@ -3,16 +3,17 @@
   "type": "module",
   "description": "Redirects YouTube, Twitter, TikTok and more to privacy friendly frontends.",
   "engines": {
-    "node": ">=16.13.1",
-    "npm": ">=8.1.2"
+    "node": ">=18.20.4",
+    "npm": ">=10.7.0"
   },
   "scripts": {
     "start": "web-ext run",
     "nightly": "web-ext run --firefox=/home/esmail/software/firefox_nightly/firefox",
-    "android": "web-ext run -t firefox-android --adb-device emulator-5554 --firefox-apk org.mozilla.fenix",
+    "start_ar": "web-ext run --firefox=/home/esmail/software/firefox_ar/firefox",
+    "android": "web-ext run -t firefox-android --adb-device emulator-5554 --firefox-apk org.mozilla.fenix ",
     "build": "web-ext build",
     "test": "web-ext lint",
-    "html": "rollup -c"
+    "html": "rollup -c --config-popup && rollup -c --config-options"
   },
   "repository": {
     "type": "git",
@@ -25,16 +26,7 @@
   },
   "homepage": "https://libredirect.github.io",
   "devDependencies": {
-    "prettier": "3.3.3",
-    "pug-cli": "^1.0.0-alpha6",
-    "web-ext": "^7.2.0",
-    "@rollup/plugin-commonjs": "^24.0.0",
-    "@rollup/plugin-node-resolve": "^15.0.0",
-    "@rollup/plugin-terser": "^0.4.0",
-    "rollup": "^3.15.0",
-    "rollup-plugin-css-only": "^4.3.0",
-    "rollup-plugin-svelte": "^7.1.2",
-    "svelte": "^3.55.0"
+    "prettier": "3.3.3"
   },
   "webExt": {
     "sourceDir": "./src/",
@@ -44,5 +36,17 @@
     "build": {
       "overwriteDest": true
     }
+  },
+  "dependencies": {
+    "svelte-select": "^5.8.3",
+    "pug-cli": "^1.0.0-alpha6",
+    "rollup": "^3.15.0",
+    "rollup-plugin-css-only": "^4.3.0",
+    "rollup-plugin-svelte": "^7.1.2",
+    "svelte": "^3.55.0",
+    "web-ext": "^7.2.0",
+    "@rollup/plugin-commonjs": "^24.0.0",
+    "@rollup/plugin-node-resolve": "^15.0.0",
+    "@rollup/plugin-terser": "^0.4.0"
   }
 }
diff --git a/rollup.config.js b/rollup.config.js
index 71222de8..5a2ce362 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -5,14 +5,23 @@ import resolve from "@rollup/plugin-node-resolve"
 import css from "rollup-plugin-css-only"
 
 const production = !process.env.ROLLUP_WATCH
+let input
+let output
+if (process.argv.includes("--config-options")) {
+  input = "src/pages/options_src/main.js"
+  output = "src/pages/options/build/bundle.js"
+} else if (process.argv.includes("--config-popup")) {
+  input = "src/pages/popup_src/main.js"
+  output = "src/pages/popup/build/bundle.js"
+}
 
 export default {
-  input: "src/pages/src/main.js",
+  input,
   output: {
     sourcemap: true,
     format: "iife",
     name: "app",
-    file: "src/pages/options/build/bundle.js",
+    file: output,
   },
   plugins: [
     svelte({
@@ -27,7 +36,7 @@ export default {
       exportConditions: ["svelte"],
     }),
     commonjs(),
-    // production && terser(),
+    production && terser(),
   ],
   watch: {
     clearScreen: false,
diff --git a/src/assets/images/libredirect.svg b/src/assets/images/libredirect.svg
index ad616dd3..a9d63d95 100644
--- a/src/assets/images/libredirect.svg
+++ b/src/assets/images/libredirect.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 333.369 333.369"><g><path d="M166.684 0c-3.524 0-7.047 1.35-9.748 4.051L4.051 156.935a13.76 13.76 0 0 0 0 19.5l152.885 152.883a13.757 13.757 0 0 0 19.498 0l152.884-152.884a13.76 13.76 0 0 0 0-19.499L176.434 4.051A13.75 13.75 0 0 0 166.684 0" style="fill:#000;fill-opacity:1;stroke-width:10.6446;stroke-linejoin:bevel;paint-order:stroke markers fill;stop-color:#000"/><path d="M166.684 0c-3.524 0-7.047 1.35-9.748 4.051L4.051 156.935a13.76 13.76 0 0 0 0 19.5l152.885 152.883a13.757 13.757 0 0 0 19.498 0l152.884-152.884a13.76 13.76 0 0 0 0-19.499L176.434 4.051A13.75 13.75 0 0 0 166.684 0m0 10.72a12.86 12.86 0 0 1 9.123 3.79L318.86 157.562a12.873 12.873 0 0 1 0 18.245L175.807 318.86a12.873 12.873 0 0 1-18.245 0L14.51 175.807a12.873 12.873 0 0 1 0-18.245L157.562 14.51a12.86 12.86 0 0 1 9.122-3.79" style="fill:#fbc118;fill-opacity:1;stroke-width:10.6446;stroke-linejoin:bevel;paint-order:stroke markers fill;stop-color:#000"/><rect width="211.979" height="211.979" x="-105.99" y="129.738" ry="11.989" style="fill:#fbc117;fill-opacity:1;stroke-width:9.25578;stroke-linejoin:bevel;paint-order:stroke markers fill;stop-color:#000" transform="rotate(-45)"/><path d="M184.948 150.313c-47.943 20.638-46.951 86.743-46.951 86.743h-33.492s-.437-96.715 73.158-116.434c-6.913-13.854-10.362-19.427-5.933-21.62 5.935-2.94 68.022 11.716 70.346 20.393 2.286 8.528-46.827 53.143-53.656 53.143-5.852 0-4.229-7.023-3.472-22.225z" style="fill:#000;fill-opacity:1;stroke-width:11.7733;stroke-linejoin:bevel;paint-order:stroke markers fill;stop-color:#000"/></g></svg>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 333.369 333.369"><path d="M166.684 0a13.74 13.74 0 0 0-9.748 4.051L4.051 156.935a13.76 13.76 0 0 0 0 19.5l152.885 152.883a13.757 13.757 0 0 0 19.498 0l152.884-152.884a13.76 13.76 0 0 0 0-19.499L176.434 4.051A13.75 13.75 0 0 0 166.684 0"/><path fill="#fbc118" d="M166.684 0a13.74 13.74 0 0 0-9.748 4.051L4.051 156.935a13.76 13.76 0 0 0 0 19.5l152.885 152.883a13.757 13.757 0 0 0 19.498 0l152.884-152.884a13.76 13.76 0 0 0 0-19.499L176.434 4.051A13.75 13.75 0 0 0 166.684 0m0 10.72a12.86 12.86 0 0 1 9.123 3.79L318.86 157.562a12.873 12.873 0 0 1 0 18.245L175.807 318.86a12.873 12.873 0 0 1-18.245 0L14.51 175.807a12.873 12.873 0 0 1 0-18.245L157.562 14.51a12.86 12.86 0 0 1 9.122-3.79"/><rect width="211.979" height="211.979" x="-105.99" y="129.738" fill="#fbc117" ry="11.989" transform="rotate(-45)"/><path d="M184.948 150.313c-47.943 20.638-46.951 86.743-46.951 86.743h-33.492s-.437-96.715 73.158-116.434c-6.913-13.854-10.362-19.427-5.933-21.62 5.935-2.94 68.022 11.716 70.346 20.393 2.286 8.528-46.827 53.143-53.656 53.143-5.852 0-4.229-7.023-3.472-22.225"/></svg>
\ No newline at end of file
diff --git a/src/assets/javascripts/localise.js b/src/assets/javascripts/localise.js
deleted file mode 100644
index d26d07d4..00000000
--- a/src/assets/javascripts/localise.js
+++ /dev/null
@@ -1,34 +0,0 @@
-window.browser = window.browser || window.chrome
-
-function localisePage() {
-  /**
-   * @param {string} tag
-   */
-  function getMessage(tag) {
-    return tag.replace(/__MSG_(\w+)__/g, (_match, v1) => {
-      return v1 ? browser.i18n.getMessage(v1) : null
-    })
-  }
-
-  const elements = document.querySelectorAll("[data-localise]")
-  for (let i in elements)
-    if (elements.hasOwnProperty(i)) {
-      const obj = elements[i]
-      const tag = obj.getAttribute("data-localise").toString()
-      const msg = getMessage(tag)
-      if (msg && msg !== tag) obj.textContent = msg
-    }
-
-  const placeholders = document.querySelectorAll("[data-localise-placeholder]")
-  for (let i in placeholders)
-    if (placeholders.hasOwnProperty(i)) {
-      const obj = placeholders[i]
-      const tag = obj.getAttribute("data-localise-placeholder").toString()
-      const msg = getMessage(tag)
-      if (msg && msg !== tag) obj.placeholder = msg
-    }
-}
-
-export default {
-  localisePage,
-}
diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js
index 439826dd..18168e90 100644
--- a/src/assets/javascripts/utils.js
+++ b/src/assets/javascripts/utils.js
@@ -21,13 +21,6 @@ function getNextInstance(currentInstanceUrl, instances) {
 }
 
 /**
- * @param {string} str
- */
-function camelCase(str) {
-  return str.charAt(0).toUpperCase() + str.slice(1)
-}
-
-/**
  * @param {URL} url
  */
 function protocolHost(url) {
@@ -178,7 +171,6 @@ export default {
   protocolHost,
   getList,
   getBlacklist,
-  camelCase,
   getConfig,
   getOptions,
   getPingCache,
diff --git a/src/config.json b/src/config.json
index 3f58ea95..9728cdc3 100644
--- a/src/config.json
+++ b/src/config.json
@@ -917,14 +917,15 @@
         "simplyTranslate": {
           "name": "SimplyTranslate",
           "instanceList": true,
-          "url": "https://git.sr.ht/~metalune/simplytranslate_web",
+          "url": "https://codeberg.org/ManeraKai/simplytranslate",
           "localhost": true
         },
         "mozhi": {
           "name": "Mozhi",
           "instanceList": true,
           "url": "https://codeberg.org/aryak/mozhi",
-          "localhost": false
+          "localhost": false,
+          "imageType": "svg"
         },
         "libreTranslate": {
           "name": "LibreTranslate",
diff --git a/src/manifest.json b/src/manifest.json
index 1f36e7c7..880268bb 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -29,7 +29,7 @@
   "browser_action": {
     "default_title": "__MSG_extensionName__",
     "browser_style": false,
-    "default_popup": "pages/popup/popup.html",
+    "default_popup": "pages/popup/index.html",
     "default_icon": {
       "16": "assets/images/libredirect-16.png",
       "32": "assets/images/libredirect-32.png",
@@ -48,7 +48,7 @@
     "search_provider": {
       "name": "__MSG_extensionName__",
       "keyword": "@libredirect",
-      "favicon_url": "https://raw.githubusercontent.com/libredirect/libredirect/master/src/assets/images/libredirect-16.png",
+      "favicon_url": "https://raw.githubusercontent.com/libredirect/browser_extension/master/src/assets/images/libredirect.svg",
       "search_url": "https://search.libredirect.invalid/?q={searchTerms}",
       "encoding": "UTF-8",
       "is_default": false
diff --git a/src/pages/src/components/Button.svelte b/src/pages/components/Button.svelte
index 3405c2ea..8836b47e 100644
--- a/src/pages/src/components/Button.svelte
+++ b/src/pages/components/Button.svelte
@@ -1,4 +1,4 @@
-<button on:click {...$$props}>
+<button {...$$restProps} on:click {...$$props}>
   <slot></slot>
 </button>
 
diff --git a/src/pages/src/components/Checkbox.svelte b/src/pages/components/Checkbox.svelte
index f5245045..9ba9c56c 100644
--- a/src/pages/src/components/Checkbox.svelte
+++ b/src/pages/components/Checkbox.svelte
@@ -1,9 +1,10 @@
 <script>
   export let checked
   export let onChange
+  console.log(document.body.dir)
 </script>
 
-<input bind:checked on:change={onChange} type="checkbox" />
+<input class={document.body.dir} {...$$restProps} bind:checked on:change={onChange} type="checkbox" />
 
 <style>
   input[type="checkbox"] {
@@ -40,13 +41,13 @@
     left: 24px;
   }
 
-  /* body.rtl div.block input[type="checkbox"]::before {
-      left: auto;
-      right: 4px;
-    } */
+  input[type="checkbox"].rtl::before {
+    left: auto;
+    right: 3.5px;
+  }
 
-  /* body.rtl div.block input[type="checkbox"]:checked::before {
-      left: auto;
-      right: 24px;
-    } */
+  input[type="checkbox"].rtl:checked::before {
+    left: auto;
+    right: 24px;
+  }
 </style>
diff --git a/src/pages/src/components/Input.svelte b/src/pages/components/Input.svelte
index d963233c..59e584db 100644
--- a/src/pages/src/components/Input.svelte
+++ b/src/pages/components/Input.svelte
@@ -3,7 +3,7 @@
 </script>
 
 <input
-  {...$$props}
+  {...$$restProps}
   bind:value
   on:blur
   on:change
@@ -38,4 +38,9 @@
   input:focus {
     outline-color: var(--active);
   }
+  @media (max-width: 715px) {
+    input {
+      width: 200px;
+    }
+  }
 </style>
diff --git a/src/pages/src/components/Label.svelte b/src/pages/components/Label.svelte
index 39930cd1..39930cd1 100644
--- a/src/pages/src/components/Label.svelte
+++ b/src/pages/components/Label.svelte
diff --git a/src/pages/src/components/Row.svelte b/src/pages/components/Row.svelte
index 4f23cffa..09246d98 100644
--- a/src/pages/src/components/Row.svelte
+++ b/src/pages/components/Row.svelte
@@ -1,4 +1,4 @@
-<div {...$$props}>
+<div {...$$restProps} on:click>
   <slot></slot>
 </div>
 
diff --git a/src/pages/src/components/Select.svelte b/src/pages/components/Select.svelte
index a0939d1f..7829c53e 100644
--- a/src/pages/src/components/Select.svelte
+++ b/src/pages/components/Select.svelte
@@ -5,7 +5,7 @@
   export let ariaLabel
 </script>
 
-<select  bind:value={value} on:change={onChange} aria-label={ariaLabel} on:change on:contextmenu on:input>
+<select bind:value on:change={onChange} aria-label={ariaLabel} on:change on:contextmenu on:input>
   {#each values as option}
     <option value={option.value}>{option.name}</option>
   {/each}
diff --git a/src/pages/stylesheets/Inter-VariableFont_slnt,wght.ttf b/src/pages/fonts/Inter-VariableFont_slnt,wght.ttf
index 969a990f..969a990f 100644
--- a/src/pages/stylesheets/Inter-VariableFont_slnt,wght.ttf
+++ b/src/pages/fonts/Inter-VariableFont_slnt,wght.ttf
Binary files differdiff --git a/src/pages/stylesheets/Vazirmatn-VariableFont_wght.ttf b/src/pages/fonts/Vazirmatn-VariableFont_wght.ttf
index f4b97c01..f4b97c01 100644
--- a/src/pages/stylesheets/Vazirmatn-VariableFont_wght.ttf
+++ b/src/pages/fonts/Vazirmatn-VariableFont_wght.ttf
Binary files differdiff --git a/src/pages/fonts/styles.css b/src/pages/fonts/styles.css
new file mode 100644
index 00000000..754543b1
--- /dev/null
+++ b/src/pages/fonts/styles.css
@@ -0,0 +1,13 @@
+@font-face {
+  font-family: "Inter";
+  src: url("Inter-VariableFont_slnt,wght.ttf");
+  font-weight: normal;
+  font-style: normal;
+}
+
+@font-face {
+  font-family: "Vazirmatn";
+  src: url("Vazirmatn-VariableFont_wght.ttf");
+  font-weight: normal;
+  font-style: normal;
+}
\ No newline at end of file
diff --git a/src/pages/src/icons/AboutIcon.svelte b/src/pages/icons/AboutIcon.svelte
index e113dd68..e113dd68 100644
--- a/src/pages/src/icons/AboutIcon.svelte
+++ b/src/pages/icons/AboutIcon.svelte
diff --git a/src/pages/src/icons/AddIcon.svelte b/src/pages/icons/AddIcon.svelte
index ab26f078..ab26f078 100644
--- a/src/pages/src/icons/AddIcon.svelte
+++ b/src/pages/icons/AddIcon.svelte
diff --git a/src/pages/src/icons/CloseIcon.svelte b/src/pages/icons/CloseIcon.svelte
index ddfb29cb..ddfb29cb 100644
--- a/src/pages/src/icons/CloseIcon.svelte
+++ b/src/pages/icons/CloseIcon.svelte
diff --git a/src/pages/icons/CopyIcon.svelte b/src/pages/icons/CopyIcon.svelte
new file mode 100644
index 00000000..37c13f98
--- /dev/null
+++ b/src/pages/icons/CopyIcon.svelte
@@ -0,0 +1,12 @@
+<svg
+  xmlns="http://www.w3.org/2000/svg"
+  height="24px"
+  width="24px"
+  viewBox="0 0 24 24"
+  preserveAspectRatio="xMinYMin meet"
+  fill="currentColor"
+>
+  <path
+    d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"
+  />
+</svg>
diff --git a/src/pages/src/icons/ExportIcon.svelte b/src/pages/icons/ExportIcon.svelte
index 196726a8..d155e5c5 100644
--- a/src/pages/src/icons/ExportIcon.svelte
+++ b/src/pages/icons/ExportIcon.svelte
@@ -1,4 +1,11 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
+<svg
+  {...$$restProps}
+  xmlns="http://www.w3.org/2000/svg"
+  height="24px"
+  viewBox="0 0 24 24"
+  width="24px"
+  fill="currentColor"
+>
   <path
     d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"
   />
diff --git a/src/pages/src/icons/GeneralIcon.svelte b/src/pages/icons/GeneralIcon.svelte
index b9429021..b9429021 100644
--- a/src/pages/src/icons/GeneralIcon.svelte
+++ b/src/pages/icons/GeneralIcon.svelte
diff --git a/src/pages/icons/ImportIcon.svelte b/src/pages/icons/ImportIcon.svelte
new file mode 100644
index 00000000..f64d0ff6
--- /dev/null
+++ b/src/pages/icons/ImportIcon.svelte
@@ -0,0 +1,12 @@
+<svg
+  {...$$restProps}
+  xmlns="http://www.w3.org/2000/svg"
+  height="24px"
+  viewBox="0 0 24 24"
+  width="24px"
+  fill="currentColor"
+>
+  <path
+    d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
+  />
+</svg>
diff --git a/src/pages/src/icons/PingIcon.svelte b/src/pages/icons/PingIcon.svelte
index 8fcfe27b..34c4a37d 100644
--- a/src/pages/src/icons/PingIcon.svelte
+++ b/src/pages/icons/PingIcon.svelte
@@ -1,4 +1,11 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 0 24 24" width="20px" fill="currentColor">
+<svg
+  {...$$restProps}
+  xmlns="http://www.w3.org/2000/svg"
+  height="20px"
+  viewBox="0 0 24 24"
+  width="20px"
+  fill="currentColor"
+>
   <path
     d="M10.45 15.5q.6.6 1.55.587.95-.012 1.4-.687L19 7l-8.4 5.6q-.675.45-.712 1.375-.038.925.562 1.525ZM12 4q1.475 0 2.838.412Q16.2 4.825 17.4 5.65l-1.9 1.2q-.825-.425-1.712-.637Q12.9 6 12 6 8.675 6 6.338 8.337 4 10.675 4 14q0 1.05.287 2.075Q4.575 17.1 5.1 18h13.8q.575-.95.838-1.975Q20 15 20 13.9q0-.9-.212-1.75-.213-.85-.638-1.65l1.2-1.9q.75 1.175 1.188 2.5.437 1.325.462 2.75.025 1.425-.325 2.725-.35 1.3-1.025 2.475-.275.45-.75.7-.475.25-1 .25H5.1q-.525 0-1-.25t-.75-.7q-.65-1.125-1-2.387Q2 15.4 2 14q0-2.075.788-3.888.787-1.812 2.15-3.175Q6.3 5.575 8.125 4.787 9.95 4 12 4Zm.175 7.825Z"
   /></svg
diff --git a/src/pages/icons/RedirectIcon.svelte b/src/pages/icons/RedirectIcon.svelte
new file mode 100644
index 00000000..9392762a
--- /dev/null
+++ b/src/pages/icons/RedirectIcon.svelte
@@ -0,0 +1,10 @@
+<svg
+  xmlns="http://www.w3.org/2000/svg"
+  height="24px"
+  width="24px"
+  viewBox="0 0 24 24"
+  preserveAspectRatio="xMinYMin meet"
+  fill="currentColor"
+>
+  <path d="M7 20v-9q0-.825.588-1.413Q8.175 9 9 9h8.2l-1.6-1.6L17 6l4 4-4 4-1.4-1.4 1.6-1.6H9v9Z" />
+</svg>
diff --git a/src/pages/icons/RedirectToOriginalIcon.svelte b/src/pages/icons/RedirectToOriginalIcon.svelte
new file mode 100644
index 00000000..aad5c48e
--- /dev/null
+++ b/src/pages/icons/RedirectToOriginalIcon.svelte
@@ -0,0 +1,13 @@
+<svg
+  xmlns="http://www.w3.org/2000/svg"
+  height="24px"
+  width="24px"
+  viewBox="0 0 24 24"
+  preserveAspectRatio="xMinYMin meet"
+  fill="currentColor"
+>
+  <path
+    d="M 17,20 V 11 Q 17,10.175 16.412,9.587 15.825,9 15,9 H 6.8 L 8.4,7.4 7,6 3,10 7,14 8.4,12.6 6.8,11 H 15 v 9 z"
+    id="path2"
+  />
+</svg>
diff --git a/src/pages/src/icons/ResetIcon.svelte b/src/pages/icons/ResetIcon.svelte
index 0900aef8..6daf57e6 100644
--- a/src/pages/src/icons/ResetIcon.svelte
+++ b/src/pages/icons/ResetIcon.svelte
@@ -5,6 +5,7 @@
   viewBox="0 0 24 24"
   width="24px"
   fill="currentColor"
+  {...$$restProps}
 >
   <path
     d="M12,5V2L8,6l4,4V7c3.31,0,6,2.69,6,6c0,2.97-2.17,5.43-5,5.91v2.02c3.95-0.49,7-3.85,7-7.93C20,8.58,16.42,5,12,5z"
diff --git a/src/pages/src/icons/ServicesIcon.svelte b/src/pages/icons/ServicesIcon.svelte
index ec24259b..ec24259b 100644
--- a/src/pages/src/icons/ServicesIcon.svelte
+++ b/src/pages/icons/ServicesIcon.svelte
diff --git a/src/pages/icons/SettingsIcon.svelte b/src/pages/icons/SettingsIcon.svelte
new file mode 100644
index 00000000..f47d078a
--- /dev/null
+++ b/src/pages/icons/SettingsIcon.svelte
@@ -0,0 +1,12 @@
+<svg
+  xmlns="http://www.w3.org/2000/svg"
+  height="24px"
+  width="24px"
+  viewBox="0 0 24 24"
+  preserveAspectRatio="xMinYMin meet"
+  fill="currentColor"
+>
+  <path
+    d="m9.25 22-.4-3.2q-.325-.125-.612-.3-.288-.175-.563-.375L4.7 19.375l-2.75-4.75 2.575-1.95Q4.5 12.5 4.5 12.337v-.675q0-.162.025-.337L1.95 9.375l2.75-4.75 2.975 1.25q.275-.2.575-.375.3-.175.6-.3l.4-3.2h5.5l.4 3.2q.325.125.613.3.287.175.562.375l2.975-1.25 2.75 4.75-2.575 1.95q.025.175.025.337v.675q0 .163-.05.338l2.575 1.95-2.75 4.75-2.95-1.25q-.275.2-.575.375-.3.175-.6.3l-.4 3.2Zm2.8-6.5q1.45 0 2.475-1.025Q15.55 13.45 15.55 12q0-1.45-1.025-2.475Q13.5 8.5 12.05 8.5q-1.475 0-2.488 1.025Q8.55 10.55 8.55 12q0 1.45 1.012 2.475Q10.575 15.5 12.05 15.5Z"
+  />
+</svg>
diff --git a/src/pages/icons/SwitchInstanceIcon.svelte b/src/pages/icons/SwitchInstanceIcon.svelte
new file mode 100644
index 00000000..6a1f96ac
--- /dev/null
+++ b/src/pages/icons/SwitchInstanceIcon.svelte
@@ -0,0 +1,15 @@
+<svg
+  {...$$restProps}
+  xmlns="http://www.w3.org/2000/svg"
+  height="24px"
+  width="24px"
+  viewBox="0 0 24 24"
+  preserveAspectRatio="xMinYMin meet"
+  fill="currentColor"
+  on:click
+  on:keydown={null}
+>
+  <path
+    d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"
+  />
+</svg>
diff --git a/src/pages/options/index.html b/src/pages/options/index.html
new file mode 100644
index 00000000..b197d4a7
--- /dev/null
+++ b/src/pages/options/index.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset='utf-8'>
+	<meta name='viewport' content='width=device-width,initial-scale=1'>
+	<link rel="icon" type="image/x-icon" href="../../../assets/images/libredirect.svg">
+	<title>Settings</title>
+	<link rel='stylesheet' href='build/bundle.css'>
+	<link rel='stylesheet' href='../fonts/styles.css'>
+	<script defer src='build/bundle.js'></script>
+</head>
+
+<body>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/src/pages/options/init.js b/src/pages/options/init.js
deleted file mode 100644
index 07da1859..00000000
--- a/src/pages/options/init.js
+++ /dev/null
@@ -1,51 +0,0 @@
-window.browser = window.browser || window.chrome
-
-import localise from "../../assets/javascripts/localise.js"
-import utils from "../../assets/javascripts/utils.js"
-import servicesHelper from "../../assets/javascripts/services.js"
-
-if (!(await utils.getOptions())) {
-  await servicesHelper.initDefaults()
-}
-
-async function changeTheme() {
-  switch ((await utils.getOptions()).theme) {
-    case "dark":
-      document.body.classList.add("dark-theme")
-      document.body.classList.remove("light-theme")
-      for (const element of document.body.getElementsByClassName("dark")) {
-        element.style.display = "none"
-      }
-      break
-    case "light":
-      document.body.classList.add("light-theme")
-      document.body.classList.remove("dark-theme")
-      for (const element of document.body.getElementsByClassName("light")) {
-        element.style.display = "none"
-      }
-      break
-    default:
-      if (matchMedia("(prefers-color-scheme: light)").matches) {
-        document.body.classList.add("light-theme")
-        document.body.classList.remove("dark-theme")
-        for (const element of document.body.getElementsByClassName("light")) {
-          element.style.display = "none"
-        }
-      } else {
-        document.body.classList.add("dark-theme")
-        document.body.classList.remove("light-theme")
-        for (const element of document.body.getElementsByClassName("dark")) {
-          element.style.display = "none"
-        }
-      }
-  }
-}
-
-changeTheme()
-if (["ar", "iw", "ku", "fa", "ur"].includes(browser.i18n.getUILanguage())) {
-  document.getElementsByTagName("body")[0].classList.add("rtl")
-  document.getElementsByTagName("body")[0].dir = "rtl"
-}
-localise.localisePage()
-
-window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", changeTheme)
diff --git a/src/pages/options_src/App.svelte b/src/pages/options_src/App.svelte
new file mode 100644
index 00000000..dfafe1f0
--- /dev/null
+++ b/src/pages/options_src/App.svelte
@@ -0,0 +1,139 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import General from "./General/General.svelte"
+  import utils from "../../assets/javascripts/utils.js"
+  import { onDestroy } from "svelte"
+  import servicesHelper from "../../assets/javascripts/services.js"
+  import { onMount } from "svelte"
+  import Sidebar from "./Sidebar.svelte"
+  import { options, config, page } from "./stores"
+  import Services from "./Services/Services.svelte"
+
+  let _options
+  const unsubscribeOptions = options.subscribe(val => {
+    if (val) {
+      _options = val
+      browser.storage.local.set({ options: val })
+    }
+  })
+
+  let _config
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  onMount(async () => {
+    let opts = await utils.getOptions()
+    if (!opts) {
+      await servicesHelper.initDefaults()
+      opts = await utils.getOptions()
+    }
+    options.set(opts)
+    config.set(await utils.getConfig())
+  })
+
+  let _page
+  page.subscribe(val => (_page = val))
+
+  const dark = {
+    text: "#fff",
+    bgMain: "#121212",
+    bgSecondary: "#202020",
+    active: "#fbc117",
+    danger: "#f04141",
+    lightGrey: "#c3c3c3",
+  }
+  const light = {
+    text: "black",
+    bgMain: "white",
+    bgSecondary: "#e4e4e4",
+    active: "#fb9817",
+    danger: "#f04141",
+    lightGrey: "#c3c3c3",
+  }
+  let cssVariables
+  $: if (_options) {
+    if (_options.theme == "dark") {
+      cssVariables = dark
+    } else if (_options.theme == "light") {
+      cssVariables = light
+    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
+      cssVariables = dark
+    } else {
+      cssVariables = light
+    }
+  }
+
+  const dir = ["ar", "iw", "ku", "fa", "ur"].includes(browser.i18n.getUILanguage()) ? "rtl" : "ltr"
+  document.body.dir = dir
+</script>
+
+{#if _options && _config}
+  <div
+    class={dir}
+    {dir}
+    style="
+    --text: {cssVariables.text};
+    --bg-main: {cssVariables.bgMain};
+    --bg-secondary: {cssVariables.bgSecondary};
+    --active: {cssVariables.active};
+    --danger: {cssVariables.danger};
+    --light-grey: {cssVariables.lightGrey};"
+  >
+    <Sidebar />
+    {#if _page == "general"}
+      <General />
+    {:else if _page == "services"}
+      <Services />
+    {/if}
+  </div>
+{:else}
+  <p>Loading...</p>
+{/if}
+
+<style>
+  :global(body) {
+    width: 100vw;
+    height: 100vh;
+    margin: 0;
+    padding: 0;
+  }
+
+  div {
+    height: 100%;
+    display: grid;
+    grid-template-columns: min-content 800px;
+    margin: 0;
+    padding-top: 50px;
+    justify-content: center;
+    font-family: "Inter";
+    box-sizing: border-box;
+    font-size: 16px;
+    background-color: var(--bg-main);
+    color: var(--text);
+    overflow: scroll;
+  }
+
+  @media (max-width: 1250px) {
+    div {
+      grid-template-columns: auto;
+      grid-template-rows: min-content auto;
+      padding-left: 5vw;
+      padding-right: 5vw;
+    }
+  }
+
+  @media (max-width: 715px) {
+    div {
+      font-size: 14px;
+      grid-template-columns: auto;
+      grid-template-rows: min-content auto;
+      padding-left: 5vw;
+      padding-right: 5vw;
+    }
+  }
+</style>
diff --git a/src/pages/src/General/Exceptions.svelte b/src/pages/options_src/General/Exceptions.svelte
index e43afaf6..7315877d 100644
--- a/src/pages/src/General/Exceptions.svelte
+++ b/src/pages/options_src/General/Exceptions.svelte
@@ -1,10 +1,12 @@
 <script>
-  import Row from "../components/Row.svelte"
-  import Select from "../components/Select.svelte"
-  import AddIcon from "../icons/AddIcon.svelte"
-  import CloseIcon from "../icons/CloseIcon.svelte"
-  import Input from "../components/Input.svelte"
-  import Label from "../components/Label.svelte"
+  const browser = window.browser || window.chrome
+
+  import Row from "../../components/Row.svelte"
+  import Select from "../../components/Select.svelte"
+  import AddIcon from "../../icons/AddIcon.svelte"
+  import CloseIcon from "../../icons/CloseIcon.svelte"
+  import Input from "../../components/Input.svelte"
+  import Label from "../../components/Label.svelte"
   import { options, config } from "../stores"
   import { onDestroy } from "svelte"
 
@@ -54,10 +56,10 @@
   }
 </script>
 
-<div class="block block-option">
-  <Row>
-    <Label>Excluded from redirecting</Label>
-  </Row>
+<Row>
+  <Label>{browser.i18n.getMessage("excludeFromRedirecting") || "Excluded from redirecting"}</Label>
+</Row>
+<div dir="ltr">
   <Row>
     <div>
       <Input
diff --git a/src/pages/options_src/General/General.svelte b/src/pages/options_src/General/General.svelte
new file mode 100644
index 00000000..37c38a0a
--- /dev/null
+++ b/src/pages/options_src/General/General.svelte
@@ -0,0 +1,79 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import Exceptions from "./Exceptions.svelte"
+  import SettingsButtons from "./SettingsButtons.svelte"
+  import { options } from "../stores"
+  import { onDestroy } from "svelte"
+  import Row from "../../components/Row.svelte"
+  import Label from "../../components/Label.svelte"
+  import Select from "../../components/Select.svelte"
+  import Checkbox from "../../components/Checkbox.svelte"
+
+  let _options
+  const unsubscribe = options.subscribe(val => (_options = val))
+  onDestroy(unsubscribe)
+
+  let bookmarksPermission
+  browser.permissions.contains({ permissions: ["bookmarks"] }, r => (bookmarksPermission = r))
+  $: if (bookmarksPermission) {
+    browser.permissions.request({ permissions: ["bookmarks"] }, r => (bookmarksPermission = r))
+  } else {
+    browser.permissions.remove({ permissions: ["bookmarks"] })
+    bookmarksPermission = false
+  }
+</script>
+
+<div>
+  <Row>
+    <Label>{browser.i18n.getMessage("theme") || "Theme"}</Label>
+    <Select
+      values={[
+        { value: "detect", name: browser.i18n.getMessage("auto") || "Auto" },
+        { value: "light", name: browser.i18n.getMessage("light") || "Light" },
+        { value: "dark", name: browser.i18n.getMessage("dark") || "Dark" },
+      ]}
+      value={_options.theme}
+      onChange={e => {
+        _options.theme = e.target.options[e.target.options.selectedIndex].value
+        options.set(_options)
+      }}
+    />
+  </Row>
+
+  <Row>
+    <Label>{browser.i18n.getMessage("fetchPublicInstances") || "Fetch public instances"}</Label>
+    <Select
+      value={_options.fetchInstances}
+      values={[
+        { value: "github", name: "GitHub" },
+        { value: "codeberg", name: "Codeberg" },
+        { value: "disable", name: browser.i18n.getMessage("disable") || "Disable" },
+      ]}
+      onChange={e => {
+        _options.fetchInstances = e.target.options[e.target.options.selectedIndex].value
+        options.set(_options)
+      }}
+    />
+  </Row>
+
+  <Row>
+    <Label>{browser.i18n.getMessage("redirectOnlyInIncognito") || "Redirect Only in Incognito"}</Label>
+    <Checkbox
+      checked={_options.redirectOnlyInIncognito}
+      onChange={e => {
+        _options.redirectOnlyInIncognito = e.target.checked
+        options.set(_options)
+      }}
+    />
+  </Row>
+
+  <Row>
+    <Label>{browser.i18n.getMessage("bookmarksMenu") || "Bookmarks menu"}</Label>
+    <Checkbox bind:checked={bookmarksPermission} />
+  </Row>
+
+  <Exceptions />
+
+  <SettingsButtons />
+</div>
diff --git a/src/pages/src/General/SettingsButtons.svelte b/src/pages/options_src/General/SettingsButtons.svelte
index 89d5e95d..2f574199 100644
--- a/src/pages/src/General/SettingsButtons.svelte
+++ b/src/pages/options_src/General/SettingsButtons.svelte
@@ -1,11 +1,11 @@
 <script>
-  let browser = window.browser || window.chrome
+  const browser = window.browser || window.chrome
 
   import { onDestroy } from "svelte"
-  import Button from "../components/Button.svelte"
-  import ExportIcon from "../icons/ExportIcon.svelte"
-  import ImportIcon from "../icons/ImportIcon.svelte"
-  import ResetIcon from "../icons/ResetIcon.svelte"
+  import Button from "../../components/Button.svelte"
+  import ExportIcon from "../../icons/ExportIcon.svelte"
+  import ImportIcon from "../../icons/ImportIcon.svelte"
+  import ResetIcon from "../../icons/ResetIcon.svelte"
   import { options } from "../stores"
   import servicesHelper from "../../../assets/javascripts/services.js"
   import utils from "../../../assets/javascripts/utils.js"
@@ -14,24 +14,18 @@
   const unsubscribe = options.subscribe(val => (_options = val))
   onDestroy(unsubscribe)
 
-  let disableButtons = false
-
   let importSettingsInput
   let importSettingsFiles
   $: if (importSettingsFiles) {
-    disableButtons = true
     const reader = new FileReader()
     reader.readAsText(importSettingsFiles[0])
     reader.onload = async () => {
       const data = JSON.parse(reader.result)
       if ("theme" in data && data.version == browser.runtime.getManifest().version) {
         browser.storage.local.clear(async () => {
-          console.log("clearing")
           options.set(data)
-          disableButtons = false
         })
       } else {
-        console.log("incompatible settings")
         alert("Incompatible settings")
       }
     }
@@ -42,26 +36,21 @@
   }
 
   async function exportSettings() {
-    disableButtons = true
     _options.version = browser.runtime.getManifest().version
     const resultString = JSON.stringify(_options, null, "  ")
     const anchor = document.createElement("a")
     anchor.href = "data:application/json;base64," + btoa(resultString)
     anchor.download = `libredirect-settings-v${_options.version}.json`
     anchor.click()
-    disableButtons = false
   }
 
   async function exportSettingsSync() {
-    disableButtons = true
     _options.version = browser.runtime.getManifest().version
     await servicesHelper.initDefaults()
     browser.storage.sync.set({ options: _options })
-    disableButtons = false
   }
 
   async function importSettingsSync() {
-    disableButtons = true
     browser.storage.sync.get({ options }, r => {
       const optionsSync = r.options
       if (optionsSync.version == browser.runtime.getManifest().version) {
@@ -69,24 +58,21 @@
       } else {
         alert("Error")
       }
-      disableButtons = false
     })
   }
 
   async function resetSettings() {
-    disableButtons = true
     browser.storage.local.clear(async () => {
       await servicesHelper.initDefaults()
       options.set(await utils.getOptions())
-      disableButtons = false
     })
   }
 </script>
 
 <div class="buttons">
-  <Button on:click={() => importSettingsInput.click()} disabled={disableButtons}>
-    <ImportIcon />
-    <x data-localise="__MSG_importSettings__">Import Settings</x>
+  <Button on:click={() => importSettingsInput.click()}>
+    <ImportIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("importSettings") || "Import Settings"}
   </Button>
   <input
     type="file"
@@ -96,23 +82,34 @@
     bind:files={importSettingsFiles}
   />
 
-  <Button on:click={exportSettings} disabled={disableButtons}>
-    <ExportIcon />
-    <x data-localise="__MSG_exportSettings__">Export Settings</x>
+  <Button on:click={exportSettings}>
+    <ExportIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("exportSettings") || "Export Settings"}
   </Button>
 
-  <Button on:click={exportSettingsSync} disabled={disableButtons}>
-    <ExportIcon />
-    <x>Export Settings to Sync</x>
+  <Button on:click={exportSettingsSync}>
+    <ExportIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("exportSettingsToSync") || "Export Settings to Sync"}
   </Button>
 
-  <Button on:click={importSettingsSync} disabled={disableButtons}>
-    <ImportIcon />
-    <x>Import Settings from Sync</x>
+  <Button on:click={importSettingsSync}>
+    <ImportIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("importSettingsFromSync") || "Import Settings from Sync"}
   </Button>
 
-  <Button on:click={resetSettings} disabled={disableButtons}>
-    <ResetIcon />
-    <x>Reset Settings</x>
+  <Button on:click={resetSettings}>
+    <ResetIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("resetSettings") || "Reset Settings"}
   </Button>
 </div>
+
+<style>
+  :global(.margin) {
+    margin-right: 10px;
+    margin-left: 0;
+  }
+  :global(.margin_rtl) {
+    margin-right: 0;
+    margin-left: 10px;
+  }
+</style>
diff --git a/src/pages/options_src/Services/FrontendIcon.svelte b/src/pages/options_src/Services/FrontendIcon.svelte
new file mode 100644
index 00000000..24942fd6
--- /dev/null
+++ b/src/pages/options_src/Services/FrontendIcon.svelte
@@ -0,0 +1,43 @@
+<script>
+  import { onDestroy } from "svelte"
+  export let details
+  import { config, options } from "../stores"
+  let _options
+  let _config
+
+  const unsubscribeOptions = options.subscribe(val => (_options = val))
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  let theme
+  $: if (_options) {
+    if (_options.theme == "dark") {
+      theme = "dark"
+    } else if (_options.theme == "light") {
+      theme = "light"
+    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
+      theme = "dark"
+    } else {
+      theme = "light"
+    }
+  }
+
+  export let selectedService
+
+  $: imageType = _config.services[selectedService].frontends[details.value].imageType
+</script>
+
+{#if imageType}
+  {#if imageType == "svgMono"}
+    {#if theme == "dark"}
+      <img src={`/assets/images/${details.value}-icon-light.svg`} alt={details.label} />
+    {:else}
+      <img src={`/assets/images/${details.value}-icon.svg`} alt={details.label} />
+    {/if}
+  {:else}
+    <img src={`/assets/images/${details.value}-icon.${imageType}`} alt={details.label} />
+  {/if}
+{/if}
diff --git a/src/pages/src/Services/Instances.svelte b/src/pages/options_src/Services/Instances.svelte
index 3c9b1ccf..862bbf7e 100644
--- a/src/pages/src/Services/Instances.svelte
+++ b/src/pages/options_src/Services/Instances.svelte
@@ -1,18 +1,19 @@
 <script>
-  let browser = window.browser || window.chrome
+  const browser = window.browser || window.chrome
 
-  import Button from "../components/Button.svelte"
-  import AddIcon from "../icons/AddIcon.svelte"
+  import Button from "../../components/Button.svelte"
+  import AddIcon from "../../icons/AddIcon.svelte"
   import { options, config } from "../stores"
-  import PingIcon from "../icons/PingIcon.svelte"
-  import Row from "../components/Row.svelte"
-  import Input from "../components/Input.svelte"
-  import Label from "../components/Label.svelte"
-  import CloseIcon from "../icons/CloseIcon.svelte"
+  import PingIcon from "../../icons/PingIcon.svelte"
+  import Row from "../../components/Row.svelte"
+  import Input from "../../components/Input.svelte"
+  import Label from "../../components/Label.svelte"
+  import CloseIcon from "../../icons/CloseIcon.svelte"
   import { onDestroy, onMount } from "svelte"
   import utils from "../../../assets/javascripts/utils"
 
   export let selectedService
+  export let selectedFrontend
 
   let _options
   let _config
@@ -27,17 +28,16 @@
   let blacklist
   let redirects
 
-  $: serviceOptions = _options[selectedService]
   $: serviceConf = _config.services[selectedService]
 
   let allInstances = []
 
   $: {
     allInstances = []
-    if (_options[serviceOptions.frontend]) allInstances.push(..._options[serviceOptions.frontend])
-    if (redirects && redirects[serviceOptions.frontend]) {
-      for (const network in redirects[serviceOptions.frontend]) {
-        allInstances.push(...redirects[serviceOptions.frontend][network])
+    if (_options[selectedFrontend]) allInstances.push(..._options[selectedFrontend])
+    if (redirects && redirects[selectedFrontend]) {
+      for (const network in redirects[selectedFrontend]) {
+        allInstances.push(...redirects[selectedFrontend][network])
       }
     }
   }
@@ -48,12 +48,12 @@
   }
 
   function isCustomInstance(instance) {
-    if (redirects[serviceOptions.frontend]) {
-      for (const network in redirects[serviceOptions.frontend]) {
-        if (redirects[serviceOptions.frontend][network].includes(instance)) return true
+    if (redirects[selectedFrontend]) {
+      for (const network in redirects[selectedFrontend]) {
+        if (redirects[selectedFrontend][network].includes(instance)) return false
       }
     }
-    return false
+    return true
   }
 
   async function pingInstances() {
@@ -62,10 +62,10 @@
       console.log("pinging...", instance)
       pingCache[instance] = { color: "lightblue", value: "pinging..." }
       const time = await utils.ping(instance)
-      pingCache[instance] = processTime(time)
+      pingCache[instance] = colorTime(time)
     }
   }
-  function processTime(time) {
+  function colorTime(time) {
     let value
     let color
     if (time < 5000) {
@@ -92,44 +92,42 @@
   let addInstanceValue
   function addInstance() {
     const instance = utils.protocolHost(new URL(addInstanceValue))
-    if (!_options[serviceOptions.frontend].includes(instance)) {
-      _options[serviceOptions.frontend].push(instance)
+    if (!_options[selectedFrontend].includes(instance)) {
+      _options[selectedFrontend].push(instance)
       addInstanceValue = ""
       options.set(_options)
     }
   }
 </script>
 
-{#if serviceConf.frontends[serviceOptions.frontend].instanceList && redirects && blacklist}
+{#if serviceConf.frontends[selectedFrontend].instanceList && redirects && blacklist}
   <hr />
-  <div dir="ltr">
-    <div class="ping">
-      <Button on:click={pingInstances}>
-        <PingIcon />
-        Ping Instances
-      </Button>
-    </div>
 
-    <Row>
-      <Label>Add your favorite instances</Label>
-    </Row>
+  <div class="ping">
+    <Button on:click={pingInstances}>
+      <PingIcon class="margin margin_{document.body.dir}" />
+      {browser.i18n.getMessage("pingInstances") || "Ping Instances"}
+    </Button>
+  </div>
 
+  <Row>
+    <Label>{browser.i18n.getMessage("addYourFavoriteInstances") || "Add your favorite instances"}</Label>
+  </Row>
+  <div dir="ltr">
     <Row>
       <Input
         bind:value={addInstanceValue}
         type="url"
         placeholder="https://instance.com"
         aria-label="Add instance input"
-        on:keydown={e => {
-          if (e.key === "Enter") addInstance()
-        }}
+        on:keydown={e => e.key === "Enter" && addInstance()}
       />
       <button on:click={addInstance} class="add" aria-label="Add the instance">
         <AddIcon />
       </button>
     </Row>
 
-    {#each _options[serviceOptions.frontend] as instance}
+    {#each _options[selectedFrontend] as instance}
       <Row>
         <span>
           <a href={instance} target="_blank" rel="noopener noreferrer">{instance}</a>
@@ -144,9 +142,9 @@
           class="add"
           aria-label="Remove Instance"
           on:click={() => {
-            const index = _options[serviceOptions.frontend].indexOf(instance)
+            const index = _options[selectedFrontend].indexOf(instance)
             if (index > -1) {
-              _options[serviceOptions.frontend].splice(index, 1)
+              _options[selectedFrontend].splice(index, 1)
               options.set(_options)
             }
           }}
@@ -156,15 +154,15 @@
       </Row>
       <hr />
     {/each}
-    <Row></Row>
 
     {#if redirects !== "disabled" && blacklist !== "disabled"}
-      {#if redirects[serviceOptions.frontend] && redirects[serviceOptions.frontend]["clearnet"]}
+      {#if redirects[selectedFrontend] && redirects[selectedFrontend]["clearnet"]}
         {#each Object.entries(_config.networks) as [networkName, network]}
-          {#if redirects[serviceOptions.frontend] && redirects[serviceOptions.frontend][networkName]}
+          {#if redirects[selectedFrontend] && redirects[selectedFrontend][networkName] && redirects[selectedFrontend][networkName].length > 0}
+            <Row></Row>
             <Row><Label>{network.name}</Label></Row>
             <hr />
-            {#each redirects[serviceOptions.frontend][networkName] as instance}
+            {#each redirects[selectedFrontend][networkName] as instance}
               <Row>
                 <span>
                   <a href={instance} target="_blank" rel="noopener noreferrer">{instance}</a>
@@ -178,7 +176,7 @@
                       cloudflare
                     </a>
                   {/if}
-                  {#if _options[serviceOptions.frontend].includes(instance)}
+                  {#if _options[selectedFrontend].includes(instance)}
                     <span style="color:grey">chosen</span>
                   {/if}
                   {#if pingCache && pingCache[instance]}
@@ -189,9 +187,9 @@
                   class="add"
                   aria-label="Add instance"
                   on:click={() => {
-                    if (_options[serviceOptions.frontend]) {
-                      if (!_options[serviceOptions.frontend].includes(instance)) {
-                        _options[serviceOptions.frontend].push(instance)
+                    if (_options[selectedFrontend]) {
+                      if (!_options[selectedFrontend].includes(instance)) {
+                        _options[selectedFrontend].push(instance)
                         options.set(_options)
                       }
                     }
@@ -226,9 +224,19 @@
   a {
     color: var(--text);
     text-decoration: none;
+    word-wrap: anywhere;
   }
 
   a:hover {
     text-decoration: underline;
   }
+
+  :global(.margin) {
+    margin-right: 10px;
+    margin-left: 0;
+  }
+  :global(.margin_rtl) {
+    margin-right: 0;
+    margin-left: 10px;
+  }
 </style>
diff --git a/src/pages/options_src/Services/RedirectType.svelte b/src/pages/options_src/Services/RedirectType.svelte
new file mode 100644
index 00000000..29c169bc
--- /dev/null
+++ b/src/pages/options_src/Services/RedirectType.svelte
@@ -0,0 +1,102 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import { onDestroy } from "svelte"
+  import SvelteSelect from "svelte-select"
+  import { options, config } from "../stores"
+  import Row from "../../components/Row.svelte"
+  import Label from "../../components/Label.svelte"
+  import FrontendIcon from "./FrontendIcon.svelte"
+  import Select from "../../components/Select.svelte"
+
+  let _options
+  let _config
+
+  const unsubscribeOptions = options.subscribe(val => (_options = val))
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  export let selectedService
+
+  $: serviceConf = _config.services[selectedService]
+  $: serviceOptions = _options[selectedService]
+  $: frontendName = _options[selectedService].frontend
+
+  let values
+  $: if (serviceConf.frontends[frontendName].embeddable) {
+    values = [
+      { value: "both", name: browser.i18n.getMessage("both") || "Both" },
+      { value: "sub_frame", name: browser.i18n.getMessage("onlyEmbedded") || "Only Embedded" },
+      { value: "main_frame", name: browser.i18n.getMessage("onlyNotEmbedded") || "Only Not Embedded" },
+    ]
+  } else if (
+    serviceConf.frontends[frontendName].desktopApp &&
+    Object.values(serviceConf.frontends).some(frontend => frontend.embeddable)
+  ) {
+    values = [
+      { value: "both", name: "both" },
+      { value: "main_frame", name: "Only Not Embedded" },
+    ]
+    if (serviceOptions.redirectType == "sub_frame") {
+      serviceOptions.redirectType = "main_frame"
+      options.set(_options)
+    }
+  } else {
+    values = [{ value: "main_frame", name: "Only Not Embedded" }]
+    serviceOptions.redirectType = "main_frame"
+    options.set(_options)
+  }
+
+  let embeddableFrontends = []
+  $: if (serviceConf) {
+    embeddableFrontends = []
+    for (const [frontendId, frontendConf] of Object.entries(serviceConf.frontends)) {
+      if (frontendConf.embeddable && frontendConf.instanceList) {
+        embeddableFrontends.push({
+          value: frontendId,
+          label: frontendConf.name,
+        })
+      }
+    }
+  }
+</script>
+
+<Row>
+  <Label>{browser.i18n.getMessage("redirectType") || "Redirect Type"}</Label>
+  <Select
+    value={serviceOptions.redirectType}
+    onChange={e => {
+      serviceOptions.redirectType = e.target.options[e.target.options.selectedIndex].value
+      options.set(_options)
+    }}
+    {values}
+  />
+</Row>
+
+{#if serviceConf.frontends[frontendName].desktopApp && serviceOptions.redirectType != "main_frame"}
+  <Row>
+    <Label>{browser.i18n.getMessage("embedFrontend") || "Embed Frontend"}</Label>
+    <SvelteSelect
+      clearable={false}
+      class="svelte_select"
+      value={serviceOptions.embedFrontend}
+      on:change={e => {
+        serviceOptions.embedFrontend = e.detail.value
+        options.set(_options)
+      }}
+      items={embeddableFrontends}
+    >
+      <div class="slot" slot="item" let:item>
+        <FrontendIcon details={item} {selectedService} />
+        {item.label}
+      </div>
+      <div class="slot" slot="selection" let:selection>
+        <FrontendIcon details={selection} {selectedService} />
+        {selection.label}
+      </div>
+    </SvelteSelect>
+  </Row>
+{/if}
diff --git a/src/pages/options_src/Services/ServiceIcon.svelte b/src/pages/options_src/Services/ServiceIcon.svelte
new file mode 100644
index 00000000..89393cf6
--- /dev/null
+++ b/src/pages/options_src/Services/ServiceIcon.svelte
@@ -0,0 +1,40 @@
+<script>
+  import { onDestroy } from "svelte"
+  export let details
+  import { config, options } from "../stores"
+  let _options
+  let _config
+
+  const unsubscribeOptions = options.subscribe(val => (_options = val))
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  let theme
+  $: if (_options) {
+    if (_options.theme == "dark") {
+      theme = "dark"
+    } else if (_options.theme == "light") {
+      theme = "light"
+    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
+      theme = "dark"
+    } else {
+      theme = "light"
+    }
+  }
+  $: imageType = _config.services[details.value].imageType
+</script>
+
+{#if imageType}
+  {#if imageType == "svgMono"}
+    {#if theme == "dark"}
+      <img src={`/assets/images/${details.value}-icon-light.svg`} alt={details.label} />
+    {:else}
+      <img src={`/assets/images/${details.value}-icon.svg`} alt={details.label} />
+    {/if}
+  {:else}
+    <img src={`/assets/images/${details.value}-icon.${imageType}`} alt={details.label} />
+  {/if}
+{/if}
diff --git a/src/pages/options_src/Services/Services.svelte b/src/pages/options_src/Services/Services.svelte
new file mode 100644
index 00000000..4e719447
--- /dev/null
+++ b/src/pages/options_src/Services/Services.svelte
@@ -0,0 +1,202 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import Row from "../../components/Row.svelte"
+  import Label from "../../components/Label.svelte"
+  import Select from "../../components/Select.svelte"
+  import { options, config } from "../stores"
+  import RedirectType from "./RedirectType.svelte"
+  import { onDestroy } from "svelte"
+  import Instances from "./Instances.svelte"
+  import SvelteSelect from "svelte-select"
+  import ServiceIcon from "./ServiceIcon.svelte"
+  import FrontendIcon from "./FrontendIcon.svelte"
+  import Checkbox from "../../components/Checkbox.svelte"
+
+  let _options
+  let _config
+
+  const unsubscribeOptions = options.subscribe(val => (_options = val))
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  let selectedService = "youtube"
+  $: serviceConf = _config.services[selectedService]
+  $: serviceOptions = _options[selectedService]
+  $: frontendWebsite = serviceConf.frontends[serviceOptions.frontend].url
+</script>
+
+<div>
+  <Row>
+    <Label>
+      Service:
+      <a href={serviceConf.url} target="_blank" rel="noopener noreferrer">{serviceConf.url}</a>
+    </Label>
+    <div dir="ltr">
+      <SvelteSelect
+        clearable={false}
+        class="svelte_select"
+        value={selectedService}
+        on:change={e => (selectedService = e.detail.value)}
+        items={[
+          ...Object.entries(_config.services).map(([serviceKey, service]) => {
+            return { value: serviceKey, label: service.name }
+          }),
+        ]}
+      >
+        <div class="slot" slot="item" let:item>
+          <ServiceIcon details={item} />
+          {item.label}
+        </div>
+        <div class="slot" slot="selection" let:selection>
+          <ServiceIcon details={selection} />
+          {selection.label}
+        </div>
+      </SvelteSelect>
+    </div>
+  </Row>
+
+  <hr />
+
+  <Row>
+    <Label>{browser.i18n.getMessage("enable") || "Enable"}</Label>
+    <Checkbox
+      checked={serviceOptions.enabled}
+      onChange={e => {
+        serviceOptions.enabled = e.target.checked
+        options.set(_options)
+      }}
+    />
+  </Row>
+
+  <div style={!serviceOptions.enabled && "pointer-events: none;opacity: 0.4;user-select: none;"}>
+    <Row>
+      <Label>{browser.i18n.getMessage("showInPopup") || "Show in popup"}</Label>
+      <Checkbox
+        checked={_options.popupServices.includes(selectedService)}
+        onChange={e => {
+          if (e.target.checked && !_options.popupServices.includes(selectedService)) {
+            _options.popupServices.push(selectedService)
+          } else if (_options.popupServices.includes(selectedService)) {
+            const index = _options.popupServices.indexOf(selectedService)
+            if (index !== -1) _options.popupServices.splice(index, 1)
+          }
+          options.set(_options)
+        }}
+      />
+    </Row>
+
+    <Row>
+      <Label>
+        {browser.i18n.getMessage("frontend") || "Frontend"}:
+        <a href={frontendWebsite} target="_blank" rel="noopener noreferrer">
+          {frontendWebsite}
+        </a>
+      </Label>
+      <div dir="ltr">
+        <SvelteSelect
+          clearable={false}
+          dir="ltr"
+          class="svelte_select"
+          value={serviceOptions.frontend}
+          on:change={e => {
+            serviceOptions.frontend = e.detail.value
+            options.set(_options)
+          }}
+          items={[
+            ...Object.entries(serviceConf.frontends).map(([frontendId, frontend]) => ({
+              value: frontendId,
+              label: frontend.name,
+            })),
+          ]}
+        >
+          <div class="slot" slot="item" let:item>
+            <FrontendIcon details={item} {selectedService} />
+            {item.label}
+          </div>
+          <div class="slot" slot="selection" let:selection>
+            <FrontendIcon details={selection} {selectedService} />
+            {selection.label}
+          </div>
+        </SvelteSelect>
+      </div>
+    </Row>
+
+    <RedirectType {selectedService} />
+
+    <Row>
+      <Label>{browser.i18n.getMessage("unsupportedIframesHandling") || "Unsupported embeds handling"}</Label>
+      <Select
+        value={serviceOptions.unsupportedUrls}
+        onChange={e => {
+          serviceOptions.unsupportedUrls = e.target.options[e.target.options.selectedIndex].value
+          options.set(_options)
+        }}
+        values={[
+          { value: "bypass", name: browser.i18n.getMessage("bypass") || "Bypass" },
+          { value: "block", name: browser.i18n.getMessage("block") || "Block" },
+        ]}
+      />
+    </Row>
+
+    {#if selectedService == "search"}
+      <Row>
+        <Label>
+          {@html browser.i18n.getMessage("searchHint") ||
+            `Set LibRedirect as Default Search Engine. For how to do in chromium browsers, click
+          <a
+            href="https://libredirect.github.io/docs.html#search_engine_chromium"
+            target="_blank"
+            rel="noopener noreferrer"
+            >here
+          </a>.`}
+        </Label>
+      </Row>
+    {/if}
+
+    <Instances
+      {selectedService}
+      selectedFrontend={!serviceConf.frontends[serviceOptions.frontend].desktopApp ||
+      serviceOptions.redirectType == "main_frame"
+        ? serviceOptions.frontend
+        : serviceOptions.embedFrontend}
+    />
+
+    <Row></Row>
+  </div>
+</div>
+
+<style>
+  :global(.svelte_select) {
+    font-weight: bold;
+    --item-padding: 0 10px;
+    --border: none;
+    --border-hover: none;
+    --border-focused: none;
+    --width: 210px;
+    --background: var(--bg-secondary);
+    --list-background: var(--bg-secondary);
+    --item-active-background: red;
+    --item-is-active-bg: grey;
+    --item-hover-bg: grey;
+    --item-is-active-color: var(--text);
+    --padding: 0 0 0 10px;
+    --item-color: var(--text);
+  }
+  :global(.svelte_select .slot) {
+    display: flex;
+    justify-content: start;
+    align-items: center;
+  }
+
+  :global(.svelte_select img, .svelte_select svg) {
+    margin-right: 10px;
+    margin-left: 0;
+    height: 26px;
+    width: 26px;
+    color: var(--text);
+  }
+</style>
diff --git a/src/pages/options_src/Sidebar.svelte b/src/pages/options_src/Sidebar.svelte
new file mode 100644
index 00000000..97780b15
--- /dev/null
+++ b/src/pages/options_src/Sidebar.svelte
@@ -0,0 +1,68 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import { page } from "./stores"
+  import GeneralIcon from "../icons/GeneralIcon.svelte"
+  import ServicesIcon from "../icons/ServicesIcon.svelte"
+  import AboutIcon from "../icons/AboutIcon.svelte"
+</script>
+
+<div>
+  <a href="#general" on:click={() => page.set("general")} style={$page == "general" && "color: var(--active);"}>
+    <GeneralIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("general") || "General"}
+  </a>
+  <a href="#services" on:click={() => page.set("services")} style={$page == "services" && "color: var(--active);"}>
+    <ServicesIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("general") || "Services"}
+  </a>
+  <a href="https://libredirect.github.io" target="_blank" rel="noopener noreferrer">
+    <AboutIcon class="margin margin_{document.body.dir}" />
+    {browser.i18n.getMessage("about") || "About"}
+  </a>
+</div>
+
+<style>
+  div {
+    display: flex;
+    flex-direction: column;
+    margin: 0 20px;
+  }
+
+  a {
+    display: flex;
+    align-items: center;
+    font-size: 18px;
+    text-decoration: none;
+    color: var(--text);
+    transition: 0.1s;
+    margin: 10px;
+  }
+
+  a:hover {
+    color: var(--active);
+  }
+
+  @media (max-width: 1250px) {
+    div {
+      flex-direction: row;
+      justify-content: center;
+      margin: 0;
+    }
+  }
+
+  @media (max-width: 715px) {
+    a {
+      margin: 5px;
+    }
+  }
+
+  :global(.margin) {
+    margin-right: 5px;
+    margin-left: 0;
+  }
+  :global(.margin_rtl) {
+    margin-right: 0;
+    margin-left: 5px;
+  }
+</style>
diff --git a/src/pages/src/main.js b/src/pages/options_src/main.js
index c4012f4a..c4012f4a 100644
--- a/src/pages/src/main.js
+++ b/src/pages/options_src/main.js
diff --git a/src/pages/src/stores.js b/src/pages/options_src/stores.js
index 782f6064..782f6064 100644
--- a/src/pages/src/stores.js
+++ b/src/pages/options_src/stores.js
diff --git a/src/pages/popup/index.html b/src/pages/popup/index.html
new file mode 100644
index 00000000..b197d4a7
--- /dev/null
+++ b/src/pages/popup/index.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset='utf-8'>
+	<meta name='viewport' content='width=device-width,initial-scale=1'>
+	<link rel="icon" type="image/x-icon" href="../../../assets/images/libredirect.svg">
+	<title>Settings</title>
+	<link rel='stylesheet' href='build/bundle.css'>
+	<link rel='stylesheet' href='../fonts/styles.css'>
+	<script defer src='build/bundle.js'></script>
+</head>
+
+<body>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/src/pages/popup/popup.js b/src/pages/popup/popup.js
deleted file mode 100644
index 77a43000..00000000
--- a/src/pages/popup/popup.js
+++ /dev/null
@@ -1,119 +0,0 @@
-"use strict"
-window.browser = window.browser || window.chrome
-
-import servicesHelper from "../../assets/javascripts/services.js"
-import utils from "../../assets/javascripts/utils.js"
-
-document.getElementById("more-options").href = browser.runtime.getURL("pages/options/index.html")
-document.getElementById("more-options").setAttribute("target", "_blank")
-
-await browser.runtime.getPlatformInfo(r => {
-  switch (r.os) {
-    case "fuchsia":
-    case "ios":
-    case "android":
-      document.getElementsByTagName("html")[0].classList.add("mobile")
-  }
-})
-
-const allSites = document.getElementById("all_sites")
-const currSite = document.getElementById("current_site")
-const currentSiteDivider = document.getElementById("current_site_divider")
-
-const config = await utils.getConfig()
-const divs = {}
-
-for (const service in config.services) {
-  divs[service] = {}
-
-  divs[service].all = allSites.getElementsByClassName(service)[0]
-  divs[service].current = currSite.getElementsByClassName(service)[0]
-
-  divs[service].all_toggle = allSites.getElementsByClassName(`${service}-enabled`)[0]
-  divs[service].all_toggle.addEventListener("change", async () => {
-    const options = await utils.getOptions()
-    options[service].enabled = divs[service].all_toggle.checked
-    browser.storage.local.set({ options })
-  })
-
-  allSites.getElementsByClassName(`${service}-change_instance`)[0].addEventListener("click", () => {
-    browser.tabs.query({ active: true, currentWindow: true }, async tabs => {
-      if (tabs[0].url) {
-        const url = new URL(tabs[0].url)
-        browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) })
-      }
-    })
-  })
-
-  divs[service].current_toggle = currSite.getElementsByClassName(`${service}-enabled`)[0]
-  divs[service].current_toggle.addEventListener("change", async () => {
-    const options = await utils.getOptions()
-    options[service].enabled = divs[service].current_toggle.checked
-    browser.storage.local.set({ options })
-  })
-
-  currSite.getElementsByClassName(`${service}-change_instance`)[0].addEventListener("click", () => {
-    browser.tabs.query({ active: true, currentWindow: true }, async tabs => {
-      if (tabs[0].url) {
-        const url = new URL(tabs[0].url)
-        browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) })
-      }
-    })
-  })
-}
-
-browser.tabs.query({ active: true, currentWindow: true }, async tabs => {
-  // Set visibility of control buttons
-  if (tabs[0].url) {
-    const hr = document.getElementById("hr")
-    var url = new URL(tabs[0].url)
-    servicesHelper.switchInstance(url).then(r => {
-      if (r) {
-        document.getElementById("change_instance_div").style.display = ""
-        hr.style.display = ""
-        document
-          .getElementById("change_instance")
-          .addEventListener("click", async () => browser.tabs.update({ url: await servicesHelper.switchInstance(url) }))
-      }
-    })
-    servicesHelper.reverse(url).then(r => {
-      if (r) {
-        hr.style.display = ""
-
-        document.getElementById("copy_original_div").style.display = ""
-        document.getElementById("copy_original").addEventListener("click", () => servicesHelper.copyRaw(url))
-
-        document.getElementById("redirect_to_original_div").style.display = ""
-        document
-          .getElementById("redirect_to_original")
-          .addEventListener("click", () => browser.runtime.sendMessage("reverseTab"))
-      }
-    })
-    servicesHelper.redirectAsync(url, "main_frame", null, true).then(r => {
-      if (r) {
-        document.getElementById("redirect_div").style.display = ""
-        hr.style.display = ""
-        document.getElementById("redirect").addEventListener("click", () => browser.runtime.sendMessage("redirectTab"))
-      }
-    })
-  }
-
-  const options = await utils.getOptions()
-
-  // Set visibility of all service buttons
-  for (const service of options.popupServices) {
-    divs[service].all.classList.remove("hide")
-    divs[service].all_toggle.checked = options[service].enabled
-  }
-
-  // Set visibility of current page service button
-  if (url) {
-    const service = await servicesHelper.computeService(url)
-    if (service) {
-      divs[service].all.classList.add("hide")
-      divs[service].current.classList.remove("hide")
-      divs[service].current_toggle.checked = options[service].enabled
-      currentSiteDivider.style.display = ""
-    }
-  }
-})
diff --git a/src/pages/popup/popup.pug b/src/pages/popup/popup.pug
deleted file mode 100644
index ed4c7319..00000000
--- a/src/pages/popup/popup.pug
+++ /dev/null
@@ -1,53 +0,0 @@
-doctype html
-html(lang="en")
-    head
-        meta(charset="UTF-8")
-        meta(name="viewport" content="width=device-width, initial-scale=1.0")
-        link(href="../stylesheets/styles.css" rel="stylesheet")
-        link(href="./style.css" rel="stylesheet")
-    body(dir="auto")
-        div(class="block" id="change_instance_div" style="display: none")
-            button(class="title button bottom-button" id="change_instance")
-                label(data-localise="__MSG_switchInstance__") Switch Instance
-                svg(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" preserveAspectRatio="xMinYMin meet" fill="currentColor")
-                    path(d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z")
-
-        div(class="block" id="copy_original_div" title="Copy the original redirected link" style="display: none")
-            button(class="title button bottom-button" id="copy_original")
-                label() Copy Original
-                svg(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" preserveAspectRatio="xMinYMin meet" fill="currentColor")
-                    path(d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z")
-
-        div(class="block" id="redirect_div" style="display: none")
-            button(class="title button bottom-button" id="redirect")
-                label Redirect
-                svg(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" preserveAspectRatio="xMinYMin meet" fill="currentColor")
-                    path(d="M7 20v-9q0-.825.588-1.413Q8.175 9 9 9h8.2l-1.6-1.6L17 6l4 4-4 4-1.4-1.4 1.6-1.6H9v9Z")
-
-        div(class="block" id="redirect_to_original_div" style="display: none")
-            button(class="title button bottom-button" id="redirect_to_original")
-                label Redirect To Original
-                svg(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" preserveAspectRatio="xMinYMin meet" fill="currentColor")
-                    path(d="M 17,20 V 11 Q 17,10.175 16.412,9.587 15.825,9 15,9 H 6.8 L 8.4,7.4 7,6 3,10 7,14 8.4,12.6 6.8,11 H 15 v 9 z" id="path2")
-
-        hr(id="hr" style="display: none")
-
-        div(id="current_site")
-            include /src/pages/popup/switches
-            div(id="current_site_divider" style="display: none")
-                hr
-
-        div(id="all_sites")
-            include /src/pages/popup/switches
-
-        hr
-
-        div(class="block")
-            a(class="title button bottom-button" id="more-options")
-                label(data-localise="__MSG_settings__") Settings
-                svg(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" preserveAspectRatio="xMinYMin meet" fill="currentColor")
-                    path(d="m9.25 22-.4-3.2q-.325-.125-.612-.3-.288-.175-.563-.375L4.7 19.375l-2.75-4.75 2.575-1.95Q4.5 12.5 4.5 12.337v-.675q0-.162.025-.337L1.95 9.375l2.75-4.75 2.975 1.25q.275-.2.575-.375.3-.175.6-.3l.4-3.2h5.5l.4 3.2q.325.125.613.3.287.175.562.375l2.975-1.25 2.75 4.75-2.575 1.95q.025.175.025.337v.675q0 .163-.05.338l2.575 1.95-2.75 4.75-2.95-1.25q-.275.2-.575.375-.3.175-.6.3l-.4 3.2Zm2.8-6.5q1.45 0 2.475-1.025Q15.55 13.45 15.55 12q0-1.45-1.025-2.475Q13.5 8.5 12.05 8.5q-1.475 0-2.488 1.025Q8.55 10.55 8.55 12q0 1.45 1.012 2.475Q10.575 15.5 12.05 15.5Z")
-
-        div(class="space")
-        script(type="module" src="../options/init.js")
-        script(type="module" src="./popup.js")
diff --git a/src/pages/popup/style.css b/src/pages/popup/style.css
deleted file mode 100644
index 41510615..00000000
--- a/src/pages/popup/style.css
+++ /dev/null
@@ -1,65 +0,0 @@
-body {
-  width: 270px;
-  min-height: auto;
-}
-
-html,
-body {
-  margin: 0;
-}
-
-.hide {
-  display: none !important;
-}
-
-.button {
-  display: flex;
-  margin: 0 auto;
-  justify-content: space-between;
-}
-
-.button svg {
-  width: 26px;
-  height: 26px;
-}
-
-.bottom-button {
-  width: 100%;
-}
-
-.space {
-  height: 10px;
-}
-
-input {
-  height: 23px;
-  width: 46px;
-}
-
-div.block label {
-  margin: 0;
-  font-size: 18px;
-  font-weight: bold;
-  max-width: 180px;
-}
-
-div.block label:hover {
-  cursor: pointer;
-}
-
-div.block div {
-  display: flex;
-}
-
-html.mobile body {
-  width: 100%;
-}
-
-html.mobile div.block label {
-  font-size: 24px;
-}
-
-html.mobile .button svg {
-  width: 30px;
-  height: 30px;
-}
diff --git a/src/pages/popup/switches.pug b/src/pages/popup/switches.pug
deleted file mode 100644
index 20ed8c61..00000000
--- a/src/pages/popup/switches.pug
+++ /dev/null
@@ -1,14 +0,0 @@
-each _, service in services    
-    div(class=`${service} block hide`)
-        a(class="title" href=services[service].url)
-            if services[service].imageType == 'svgMono'
-                img(class='dark' src=`/assets/images/${service}-icon.svg`)
-                img(class='light' src=`/assets/images/${service}-icon-light.svg`)
-            else
-                img(src=`/assets/images/${service}-icon.${services[service].imageType}`)
-            label=services[service].name
-        div 
-            input(class=`${service}-enabled` type="checkbox" aria-label=`toggle ${services[service].name}`)
-            button(class=`${service}-change_instance title button` aria-label=`change instance for ${services[service].name}`)
-                svg(xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" preserveAspectRatio="xMinYMin meet" fill="currentColor")
-                    path(d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z")
\ No newline at end of file
diff --git a/src/pages/src/App.svelte b/src/pages/popup_src/App.svelte
index 8cceb5d1..df37d55d 100644
--- a/src/pages/src/App.svelte
+++ b/src/pages/popup_src/App.svelte
@@ -1,14 +1,13 @@
 <script>
-  let browser = window.browser || window.chrome
+  const browser = window.browser || window.chrome
 
-  import General from "./General/General.svelte"
   import utils from "../../assets/javascripts/utils.js"
   import { onDestroy } from "svelte"
   import servicesHelper from "../../assets/javascripts/services.js"
   import { onMount } from "svelte"
-  import Sidebar from "./Sidebar.svelte"
+  import Buttons from "./Buttons.svelte"
+
   import { options, config, page } from "./stores"
-  import Services from "./Services/Services.svelte"
 
   let _options
   const unsubscribeOptions = options.subscribe(val => {
@@ -29,7 +28,6 @@
   onMount(async () => {
     let opts = await utils.getOptions()
     if (!opts) {
-      console.log("init defulats")
       await servicesHelper.initDefaults()
       opts = await utils.getOptions()
     }
@@ -82,37 +80,35 @@
     --danger: {cssVariables.danger};
     --light-grey: {cssVariables.lightGrey};"
   >
-    <Sidebar />
-    {#if _page == "general"}
-      <General />
-    {:else if _page == "services"}
-      <Services />
-    {/if}
+    <Buttons />
   </div>
 {:else}
   <p>Loading...</p>
 {/if}
 
 <style>
-  :global(body) {
-    width: 100vw;
-    height: 100vh;
+  :global(html, body) {
+    width: 250px;
+    height: min-content;
+    min-height: auto;
     margin: 0;
     padding: 0;
+    box-sizing: border-box;
+  }
+
+  :global(body) {
+    margin-top: -20px;
   }
 
   div {
+    font-weight: bold;
     height: 100%;
-    display: grid;
-    grid-template-columns: min-content 700px;
     margin: 0;
-    padding-top: 50px;
-    justify-content: center;
+    padding: 10px;
+    padding-top: 20px;
     font-family: "Inter";
-    box-sizing: border-box;
     font-size: 16px;
     background-color: var(--bg-main);
     color: var(--text);
-    overflow: scroll;
   }
 </style>
diff --git a/src/pages/popup_src/Buttons.svelte b/src/pages/popup_src/Buttons.svelte
new file mode 100644
index 00000000..bfa162f8
--- /dev/null
+++ b/src/pages/popup_src/Buttons.svelte
@@ -0,0 +1,118 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import Row from "./components/Row.svelte"
+  import Label from "../components/Label.svelte"
+  import CopyIcon from "../icons/CopyIcon.svelte"
+  import RedirectToOriginalIcon from "../icons/RedirectToOriginalIcon.svelte"
+  import RedirectIcon from "../icons/RedirectIcon.svelte"
+  import SwitchInstanceIcon from "../icons/SwitchInstanceIcon.svelte"
+  import SettingsIcon from "../icons/SettingsIcon.svelte"
+  import { options, config } from "./stores"
+  import { onDestroy } from "svelte"
+  import servicesHelper from "../../assets/javascripts/services"
+  import Switch from "./components/Switch.svelte"
+
+  let _options
+  let _config
+
+  const unsubscribeOptions = options.subscribe(val => (_options = val))
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  let url
+  let switchInstance
+  let redirectToOriginal
+  let redirect
+  let currentService
+  browser.tabs.query({ active: true, currentWindow: true }, async tabs => {
+    if (tabs[0].url) {
+      url = new URL(tabs[0].url)
+      servicesHelper.switchInstance(url).then(r => (switchInstance = r))
+      servicesHelper.reverse(url).then(r => (redirectToOriginal = r))
+      servicesHelper.redirectAsync(url, "main_frame", null, true).then(r => (redirect = r))
+      servicesHelper.computeService(url).then(r => (currentService = r))
+    }
+  })
+</script>
+
+<div class={document.body.dir}>
+  {#if redirect}
+    <Row class="interactive" on:click={() => browser.runtime.sendMessage("redirectTab")}>
+      <Label>{browser.i18n.getMessage("redirect") || "Redirect"}</Label>
+      <RedirectIcon />
+    </Row>
+  {/if}
+
+  {#if switchInstance}
+    <Row
+      class="interactive"
+      on:click={async () => browser.tabs.update({ url: await servicesHelper.switchInstance(url) })}
+    >
+      <Label>{browser.i18n.getMessage("switchInstance") || "Switch Instance"}</Label>
+      <SwitchInstanceIcon />
+    </Row>
+  {/if}
+
+  {#if redirectToOriginal}
+    <Row class="interactive" on:click={() => servicesHelper.copyRaw(url)}>
+      <Label>{browser.i18n.getMessage("copyOriginal") || "Copy Original"}</Label>
+      <CopyIcon />
+    </Row>
+    <Row class="interactive" on:click={() => browser.runtime.sendMessage("reverseTab")}>
+      <Label>{browser.i18n.getMessage("redirectToOriginal" || "Redirect to Original")}</Label>
+      <RedirectToOriginalIcon />
+    </Row>
+  {/if}
+
+  {#if redirect || switchInstance || redirectToOriginal}
+    <hr />
+  {/if}
+
+  {#if currentService}
+    <Switch serviceKey={currentService} {url} />
+    <hr />
+  {/if}
+
+  {#each _options.popupServices as serviceKey}
+    {#if currentService !== serviceKey}
+      <Switch {serviceKey} {url} />
+    {/if}
+  {/each}
+
+  <hr />
+
+  <Row class="interactive" on:click={() => window.open(browser.runtime.getURL("pages/options/index.html"), "_blank")}>
+    <Label>{browser.i18n.getMessage("settings")}</Label>
+    <SettingsIcon />
+  </Row>
+</div>
+
+<style>
+  :global(.interactive) {
+    transition: 0.1s;
+  }
+  :global(.interactive:hover) {
+    color: var(--active);
+    cursor: pointer;
+  }
+  :global(.interactive:active) {
+    transform: translateY(1px);
+  }
+
+  :global(img, svg) {
+    margin-right: 10px;
+    margin-left: 0;
+    height: 26px;
+    width: 26px;
+    color: var(--text);
+  }
+
+  :global(.rtl img, .rtl svg) {
+    margin-right: 0;
+    margin-left: 10px;
+  }
+</style>
diff --git a/src/pages/popup_src/components/Row.svelte b/src/pages/popup_src/components/Row.svelte
new file mode 100644
index 00000000..a4d78f07
--- /dev/null
+++ b/src/pages/popup_src/components/Row.svelte
@@ -0,0 +1,13 @@
+<div {...$$props} on:click>
+    <slot></slot>
+  </div>
+  
+  <style>
+    div {
+      justify-content: space-between;
+      display: flex;
+      align-items: center;
+      margin: 10px 0;
+    }
+  </style>
+  
\ No newline at end of file
diff --git a/src/pages/popup_src/components/ServiceIcon.svelte b/src/pages/popup_src/components/ServiceIcon.svelte
new file mode 100644
index 00000000..89393cf6
--- /dev/null
+++ b/src/pages/popup_src/components/ServiceIcon.svelte
@@ -0,0 +1,40 @@
+<script>
+  import { onDestroy } from "svelte"
+  export let details
+  import { config, options } from "../stores"
+  let _options
+  let _config
+
+  const unsubscribeOptions = options.subscribe(val => (_options = val))
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  let theme
+  $: if (_options) {
+    if (_options.theme == "dark") {
+      theme = "dark"
+    } else if (_options.theme == "light") {
+      theme = "light"
+    } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
+      theme = "dark"
+    } else {
+      theme = "light"
+    }
+  }
+  $: imageType = _config.services[details.value].imageType
+</script>
+
+{#if imageType}
+  {#if imageType == "svgMono"}
+    {#if theme == "dark"}
+      <img src={`/assets/images/${details.value}-icon-light.svg`} alt={details.label} />
+    {:else}
+      <img src={`/assets/images/${details.value}-icon.svg`} alt={details.label} />
+    {/if}
+  {:else}
+    <img src={`/assets/images/${details.value}-icon.${imageType}`} alt={details.label} />
+  {/if}
+{/if}
diff --git a/src/pages/popup_src/components/Switch.svelte b/src/pages/popup_src/components/Switch.svelte
new file mode 100644
index 00000000..e581e5f4
--- /dev/null
+++ b/src/pages/popup_src/components/Switch.svelte
@@ -0,0 +1,67 @@
+<script>
+  const browser = window.browser || window.chrome
+
+  import Checkbox from "../../components/Checkbox.svelte"
+  import Label from "../../components/Label.svelte"
+  import SwitchInstanceIcon from "../../icons/SwitchInstanceIcon.svelte"
+  import Row from "./Row.svelte"
+  import ServiceIcon from "./ServiceIcon.svelte"
+  import { onDestroy } from "svelte"
+  import servicesHelper from "../../../assets/javascripts/services"
+  import { options, config } from "../stores"
+
+  let _options
+  let _config
+
+  const unsubscribeOptions = options.subscribe(val => (_options = val))
+  const unsubscribeConfig = config.subscribe(val => (_config = val))
+  onDestroy(() => {
+    unsubscribeOptions()
+    unsubscribeConfig()
+  })
+
+  export let serviceKey
+  export let url
+</script>
+
+<Row>
+  <div
+    class="interactive"
+    on:keydown={null}
+    on:click={() => window.open(browser.runtime.getURL(_config.services[serviceKey].url), "_blank")}
+  >
+    <ServiceIcon details={{ value: serviceKey, label: _config.services[serviceKey].name }} />
+    <Label>{_config.services[serviceKey].name}</Label>
+  </div>
+  <div>
+    <Checkbox
+      class="margin margin_{document.body.dir}"
+      label="Enable"
+      checked={_options[serviceKey].enabled}
+      onChange={e => {
+        _options[serviceKey].enabled = e.target.checked
+        options.set(_options)
+      }}
+    />
+    <SwitchInstanceIcon
+      class="interactive"
+      on:click={async () => browser.tabs.update({ url: await servicesHelper.switchInstance(url, serviceKey) })}
+    />
+  </div>
+</Row>
+
+<style>
+  div {
+    display: flex;
+    align-items: center;
+  }
+
+  :global(.margin) {
+    margin-right: 5px;
+    margin-left: 0;
+  }
+  :global(.margin_rtl) {
+    margin-right: 0;
+    margin-left: 5px;
+  }
+</style>
diff --git a/src/pages/popup_src/main.js b/src/pages/popup_src/main.js
new file mode 100644
index 00000000..c4012f4a
--- /dev/null
+++ b/src/pages/popup_src/main.js
@@ -0,0 +1,7 @@
+import App from "./App.svelte"
+
+const app = new App({
+  target: document.body,
+})
+
+export default app
diff --git a/src/pages/popup_src/stores.js b/src/pages/popup_src/stores.js
new file mode 100644
index 00000000..782f6064
--- /dev/null
+++ b/src/pages/popup_src/stores.js
@@ -0,0 +1,5 @@
+import { writable } from "svelte/store"
+
+export const options = writable(null)
+export const config = writable(null)
+export const page = writable("general")
diff --git a/src/pages/src/General/General.svelte b/src/pages/src/General/General.svelte
deleted file mode 100644
index 1a5e8329..00000000
--- a/src/pages/src/General/General.svelte
+++ /dev/null
@@ -1,70 +0,0 @@
-<script>
-  let browser = window.browser || window.chrome
-
-  import Exceptions from "./Exceptions.svelte"
-  import SettingsButtons from "./SettingsButtons.svelte"
-  import RowSelect from "../components/RowSelect.svelte"
-  import Checkbox from "../components/RowCheckbox.svelte"
-  import { options } from "../stores"
-  import { onDestroy } from "svelte"
-
-  let _options
-  const unsubscribe = options.subscribe(val => (_options = val))
-  onDestroy(unsubscribe)
-
-  let bookmarksPermission
-  browser.permissions.contains({ permissions: ["bookmarks"] }, r => (bookmarksPermission = r))
-  $: if (bookmarksPermission) {
-    browser.permissions.request({ permissions: ["bookmarks"] }, r => (bookmarksPermission = r))
-  } else {
-    browser.permissions.remove({ permissions: ["bookmarks"] })
-    bookmarksPermission = false
-  }
-</script>
-
-<div>
-  <RowSelect
-    label="Theme"
-    values={[
-      { value: "detect", name: "Auto" },
-      { value: "light", name: "Light" },
-      { value: "dark", name: "Dark" },
-    ]}
-    value={_options.theme}
-    onChange={e => {
-      _options["theme"] = e.target.options[e.target.options.selectedIndex].value
-      options.set(_options)
-    }}
-    ariaLabel="select theme"
-  />
-
-  <RowSelect
-    label="Fetch public instances"
-    value={_options.fetchInstances}
-    onChange={e => {
-      _options["fetchInstances"] = e.target.options[e.target.options.selectedIndex].value
-      options.set(_options)
-    }}
-    ariaLabel="Select fetch public instances"
-    values={[
-      { value: "github", name: "GitHub" },
-      { value: "codeberg", name: "Codeberg" },
-      { value: "disable", name: "Disable" },
-    ]}
-  />
-
-  <Checkbox
-    label="Redirect Only in Incognito"
-    checked={_options.redirectOnlyInIncognito}
-    onChange={e => {
-      _options["redirectOnlyInIncognito"] = e.target.checked
-      options.set(_options)
-    }}
-  />
-
-  <Checkbox label="Bookmarks menu" bind:checked={bookmarksPermission} />
-
-  <Exceptions opts={_options} />
-
-  <SettingsButtons opts={_options} />
-</div>
diff --git a/src/pages/src/Services/RedirectType.svelte b/src/pages/src/Services/RedirectType.svelte
deleted file mode 100644
index 92b8c6d1..00000000
--- a/src/pages/src/Services/RedirectType.svelte
+++ /dev/null
@@ -1,84 +0,0 @@
-<script>
-  import { onDestroy } from "svelte"
-
-  import RowSelect from "../components/RowSelect.svelte"
-  import { options, config } from "../stores"
-
-  let _options
-  let _config
-
-  const unsubscribeOptions = options.subscribe(val => (_options = val))
-  const unsubscribeConfig = config.subscribe(val => (_config = val))
-  onDestroy(() => {
-    unsubscribeOptions()
-    unsubscribeConfig()
-  })
-
-  export let selectedService
-
-  $: serviceConf = _config.services[selectedService]
-  $: serviceOptions = _options[selectedService]
-  $: frontendName = _options[selectedService].frontend
-
-  let values
-  $: if (serviceConf.frontends[frontendName].embeddable) {
-    values = [
-      { value: "both", name: "Both" },
-      { value: "sub_frame", name: "Only Embedded" },
-      { value: "main_frame", name: "Only Not Embedded" },
-    ]
-  } else if (
-    serviceConf.frontends[frontendName].desktopApp &&
-    Object.values(serviceConf.frontends).some(frontend => frontend.embeddable)
-  ) {
-    values = [
-      { value: "both", name: "both" },
-      { value: "main_frame", name: "Only Not Embedded" },
-    ]
-    if (serviceOptions.redirectType == "sub_frame") {
-      serviceOptions.redirectType = "main_frame"
-      options.set(_options)
-    }
-  } else {
-    values = [{ value: "main_frame", name: "Only Not Embedded" }]
-    serviceOptions.redirectType = "main_frame"
-    options.set(_options)
-  }
-
-  let embeddableFrontends = []
-  $: (() => {
-    if (serviceConf) {
-      embeddableFrontends = []
-      for (const [frontendId, frontendConf] of Object.entries(serviceConf.frontends)) {
-        if (frontendConf.embeddable && frontendConf.instanceList) {
-          embeddableFrontends.push({
-            value: frontendId,
-            name: frontendConf.name,
-          })
-        }
-      }
-    }
-  })()
-</script>
-
-<RowSelect
-  label="Redirect Type"
-  value={serviceOptions.redirectType}
-  onChange={e => {
-    serviceOptions.redirectType = e.target.options[e.target.options.selectedIndex].value
-    options.set(_options)
-  }}
-  {values}
-/>
-
-{#if serviceConf.frontends[frontendName].desktopApp && serviceOptions.redirectType != "main_frame"}
-  <RowSelect
-    label="Embed Frontend"
-    value={_options.embedFrontend}
-    onChange={e => {
-      serviceOptions.embedFrontend = e.target.options[e.target.options.selectedIndex].value
-      options.set(_options)
-    }}
-    values={embeddableFrontends}
-  />
-{/if}
diff --git a/src/pages/src/Services/Services.svelte b/src/pages/src/Services/Services.svelte
deleted file mode 100644
index b5d9285c..00000000
--- a/src/pages/src/Services/Services.svelte
+++ /dev/null
@@ -1,119 +0,0 @@
-<script>
-  let browser = window.browser || window.chrome
-
-  import Checkbox from "../components/RowCheckbox.svelte"
-  import RowSelect from "../components/RowSelect.svelte"
-  import Row from "../components/Row.svelte"
-  import Label from "../components/Label.svelte"
-  import Select from "../components/Select.svelte"
-  import { options, config } from "../stores"
-  import RedirectType from "./RedirectType.svelte"
-  import { onDestroy, onMount } from "svelte"
-  import Instances from "./Instances.svelte"
-
-  let _options
-  let _config
-
-  const unsubscribeOptions = options.subscribe(val => (_options = val))
-  const unsubscribeConfig = config.subscribe(val => (_config = val))
-  onDestroy(() => {
-    unsubscribeOptions()
-    unsubscribeConfig()
-  })
-
-  let selectedService = "youtube"
-
-  $: serviceConf = _config.services[selectedService]
-  $: serviceOptions = _options[selectedService]
-</script>
-
-<div>
-  <Row>
-    <Label>
-      Service:
-      <a href={serviceConf.url} target="_blank" rel="noopener noreferrer">{serviceConf.url}</a>
-    </Label>
-    <Select
-      value={selectedService}
-      values={[
-        ...Object.entries(_config.services).map(([serviceId, service]) => {
-          return { value: serviceId, name: service.name }
-        }),
-      ]}
-      onChange={e => (selectedService = e.target.options[e.target.options.selectedIndex].value)}
-    />
-  </Row>
-
-  <hr />
-
-  <Checkbox
-    label="Enable"
-    checked={serviceOptions.enabled}
-    onChange={e => {
-      serviceOptions.enabled = e.target.checked
-      options.set(_options)
-    }}
-  />
-
-  <div style={!serviceOptions.enabled && "pointer-events: none;opacity: 0.4;user-select: none;"}>
-    <Checkbox
-      label="Show in popup"
-      checked={_options.popupServices.includes(selectedService)}
-      onChange={e => {
-        if (e.target.checked && !_options.popupServices.includes(selectedService)) {
-          _options.popupServices.push(selectedService)
-        } else if (_options.popupServices.includes(selectedService)) {
-          const index = _options.popupServices.indexOf(selectedService)
-          if (index !== -1) _options.popupServices.splice(index, 1)
-        }
-        options.set(_options)
-      }}
-    />
-
-    <Row>
-      <Label>
-        Frontend:
-        <a href={serviceConf.frontends[serviceOptions.frontend].url} target="_blank" rel="noopener noreferrer"
-          >{serviceConf.frontends[serviceOptions.frontend].url}</a
-        >
-      </Label>
-      <Select
-        value={serviceOptions.frontend}
-        values={[
-          ...Object.entries(serviceConf.frontends).map(([frontendId, frontend]) => ({
-            value: frontendId,
-            name: frontend.name,
-          })),
-        ]}
-        onChange={e => {
-          serviceOptions.frontend = e.target.options[e.target.options.selectedIndex].value
-          options.set(_options)
-        }}
-      />
-    </Row>
-
-    <RedirectType {selectedService} />
-
-    <RowSelect
-      label="Unsupported iframes handling"
-      value={serviceOptions.unsupportedUrls}
-      onChange={e => {
-        serviceOptions.unsupportedUrls = e.target.options[e.target.options.selectedIndex].value
-        options.set(_options)
-      }}
-      values={[
-        { value: "bypass", name: "Bypass" },
-        { value: "block", name: "Block" },
-      ]}
-    />
-
-    {#if selectedService == "search"}
-      <div>
-        Set LibRedirect as Default Search Engine. For how to do in chromium browsers, click
-        <a href="https://libredirect.github.io/docs.html#search_engine_chromium">here</a>.
-      </div>
-    {/if}
-
-    <Instances {selectedService} />
-  </div>
-</div>
diff --git a/src/pages/src/Sidebar.svelte b/src/pages/src/Sidebar.svelte
deleted file mode 100644
index be59a731..00000000
--- a/src/pages/src/Sidebar.svelte
+++ /dev/null
@@ -1,43 +0,0 @@
-<script>
-  import { page } from "./stores"
-  import GeneralIcon from "./icons/GeneralIcon.svelte"
-  import ServicesIcon from "./icons/ServicesIcon.svelte"
-  import AboutIcon from "./icons/AboutIcon.svelte"
-</script>
-
-<div>
-  <a href="#general" on:click={() => page.set("general")} style={$page == "general" && "color: var(--active);"}>
-    <GeneralIcon style="margin-right: 5px" />
-    <span data-localise="__MSG_general__">General</span>
-  </a>
-  <a href="#services" on:click={() => page.set("services")} style={$page == "services" && "color: var(--active);"}>
-    <ServicesIcon style="margin-right: 5px" />
-    <span data-localise="__MSG_general__">Services</span>
-  </a>
-  <a href="https://libredirect.github.io" target="_blank" rel="noopener noreferrer">
-    <AboutIcon style="margin-right: 5px" />
-    <span data-localise="__MSG_about__">About</span>
-  </a>
-</div>
-
-<style>
-  div {
-    display: flex;
-    flex-direction: column;
-    margin: 0 20px;
-  }
-
-  a {
-    display: flex;
-    align-items: center;
-    font-size: 18px;
-    text-decoration: none;
-    color: var(--text);
-    transition: 0.1s;
-    margin: 10px;
-  }
-
-  a:hover {
-    color: var(--active);
-  }
-</style>
diff --git a/src/pages/src/components/RowCheckbox.svelte b/src/pages/src/components/RowCheckbox.svelte
deleted file mode 100644
index b7ccab93..00000000
--- a/src/pages/src/components/RowCheckbox.svelte
+++ /dev/null
@@ -1,14 +0,0 @@
-<script>
-  import Row from "./Row.svelte"
-  import Checkbox from "./Checkbox.svelte"
-  import Label from "./Label.svelte"
-
-  export let label
-  export let checked
-  export let onChange
-</script>
-
-<Row>
-  <Label>{label}</Label>
-  <Checkbox bind:checked {onChange} />
-</Row>
diff --git a/src/pages/src/components/RowSelect.svelte b/src/pages/src/components/RowSelect.svelte
deleted file mode 100644
index d685803e..00000000
--- a/src/pages/src/components/RowSelect.svelte
+++ /dev/null
@@ -1,19 +0,0 @@
-<script>
-  import Row from "./Row.svelte"
-  import Select from "./Select.svelte"
-  import Label from "./Label.svelte"
-
-  export let label
-  export let values
-  export let value
-  export let onChange
-  export let ariaLabel
-</script>
-
-<Row>
-  <Label>{label}</Label>
-  <Select {value} {values} {onChange} {ariaLabel} />
-</Row>
-
-<style>
-</style>
diff --git a/src/pages/src/icons/ImportIcon.svelte b/src/pages/src/icons/ImportIcon.svelte
deleted file mode 100644
index f022b4f0..00000000
--- a/src/pages/src/icons/ImportIcon.svelte
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
-    <path
-      d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"
-    />
-  </svg>
\ No newline at end of file
diff --git a/src/pages/stylesheets/styles.css b/src/pages/stylesheets/styles.css
deleted file mode 100644
index ca6f0dca..00000000
--- a/src/pages/stylesheets/styles.css
+++ /dev/null
@@ -1,449 +0,0 @@
-body {
-  --text: #fff;
-  --bg-main: #121212;
-  --bg-secondary: #202020;
-  --active: #fbc117;
-  --danger: #f04141;
-  --light-grey: #c3c3c3;
-}
-
-@font-face {
-  font-family: "Inter";
-  src: url("Inter-VariableFont_slnt,wght.ttf");
-  font-weight: normal;
-  font-style: normal;
-}
-
-@font-face {
-  font-family: "Vazirmatn";
-  src: url("Vazirmatn-VariableFont_wght.ttf");
-  font-weight: normal;
-  font-style: normal;
-}
-
-body {
-  margin: auto;
-  padding: 0;
-  font-family: "Inter";
-  font-size: 16px;
-  background-color: var(--bg-main);
-  color: var(--text);
-}
-
-body * {
-  font-family: "Inter";
-}
-
-body.rtl {
-  font-family: "Vazirmatn";
-}
-
-body.rtl * {
-  font-family: "Vazirmatn";
-}
-
-div.block input[type="checkbox"] {
-  appearance: none;
-  -moz-appearance: none;
-  -webkit-appearance: none;
-}
-
-.title {
-  display: flex;
-  align-items: center;
-  text-decoration: none;
-  width: min-content;
-  color: var(--text);
-  transition: 0.1s;
-}
-
-.title:hover {
-  opacity: 1 !important;
-}
-
-.title:hover a {
-  color: var(--active);
-}
-
-img,
-svg {
-  margin-right: 10px;
-  height: 26px;
-  width: 26px;
-  color: var(--text);
-}
-
-body.rtl img,
-body.rtl svg {
-  margin-right: 0px;
-  margin-left: 10px;
-}
-
-input[type="url"],
-input[type="text"],
-select {
-  font-weight: bold;
-  box-sizing: border-box;
-  border-style: solid;
-  border-color: #767676;
-  color: var(--text);
-  font-size: 16px;
-  padding: 8px;
-  background-color: var(--bg-secondary);
-  border: none;
-  margin: 0;
-  max-width: 500px;
-  border-radius: 3px;
-}
-
-input[type="url"],
-input[type="text"] {
-  width: 400px;
-  cursor: text;
-}
-
-input:invalid {
-  color: var(--danger);
-}
-
-.button svg {
-  height: 18px;
-  width: 18px;
-}
-
-section.block-option {
-  width: 750px;
-  margin: 0 50px;
-}
-
-section.block-option h2 {
-  margin: 0;
-}
-
-body.option {
-  display: flex;
-  padding: 40px;
-  width: 1160px;
-}
-
-section.links {
-  display: flex;
-  flex-wrap: wrap;
-  flex-direction: column;
-  width: 350px;
-  max-height: 1030px;
-}
-
-section.links div {
-  margin: 10px;
-  width: max-content;
-}
-
-a {
-  text-decoration: none;
-  color: var(--text);
-  transition: 0.1s;
-}
-
-a:hover {
-  color: var(--active);
-}
-
-section.links a {
-  display: flex;
-  align-items: center;
-  font-size: 18px;
-  text-decoration: none;
-  color: white;
-  transition: 0.1s;
-}
-
-section.links a:hover,
-section.links .selected {
-  opacity: 1 !important;
-}
-
-section.links .selected a {
-  color: var(--active);
-}
-
-::placeholder {
-  color: var(--text);
-  opacity: 0.7;
-}
-
-hr {
-  height: 2px;
-  margin: 0 15px;
-  background-color: rgb(77, 77, 77);
-  border: none;
-}
-
-div.block {
-  padding: 0 15px;
-  justify-content: space-between;
-  display: flex;
-  align-items: center;
-  margin-top: 10px;
-  margin-bottom: 10px;
-}
-
-div.block-option {
-  margin: 30px 0;
-}
-
-div.block-option label {
-  margin-right: 5px;
-  width: 80%;
-  min-width: 150px;
-  font-size: 18px;
-}
-
-div.block-option h1 {
-  margin: 0;
-  font-size: 28px;
-  color: var(--text);
-}
-
-div.block-option div {
-  text-align: center;
-}
-
-div.block input[type="checkbox"] {
-  width: 46px;
-  height: 24px;
-  background-color: var(--light-grey);
-  border-radius: 50px;
-  transition: 0.4s;
-  cursor: pointer;
-}
-
-div.block input[type="checkbox"]:checked {
-  background-color: var(--active);
-}
-
-div.block input[type="checkbox"]::before {
-  content: "";
-  display: inline-block;
-  width: 18px;
-  height: 18px;
-  box-sizing: border-box;
-  position: relative;
-  top: 2.5px;
-  left: 3.5px;
-  background-color: white;
-  border-radius: 50%;
-  transition: 0.3s;
-}
-
-body.rtl div.block input[type="checkbox"]::before {
-  left: auto;
-  right: 4px;
-}
-
-div.block input[type="checkbox"]:checked::before {
-  left: 24px;
-}
-
-body.rtl div.block input[type="checkbox"]:checked::before {
-  left: auto;
-  right: 24px;
-}
-
-div.buttons {
-  display: flex;
-  margin: 0 15px;
-  margin-bottom: 15px;
-  margin-top: 15px;
-  flex-wrap: wrap;
-  align-items: center;
-  justify-content: start;
-}
-
-.button {
-  color: var(--text);
-  font-size: 16px;
-  font-weight: bold;
-  text-decoration: none;
-  cursor: pointer;
-  transition-duration: 0.1s;
-}
-
-.button:hover {
-  color: var(--active);
-}
-
-.button svg {
-  width: auto;
-  height: auto;
-  padding: 0;
-  margin-right: 5px;
-}
-
-.button:hover svg {
-  color: var(--active);
-}
-
-.button-inline {
-  display: inline-flex;
-  align-items: center;
-  margin: 7.5px 0;
-  background-color: var(--bg-secondary);
-  border-radius: 5px;
-  padding: 10px;
-}
-
-.button:active {
-  transform: translateY(1px);
-}
-
-button svg {
-  color: var(--text);
-}
-
-div.checklist div {
-  justify-content: space-between;
-  margin: 5px 15px;
-  padding: 10px 0;
-  word-wrap: break-word;
-  display: flex;
-}
-
-div.checklist a {
-  text-decoration: none;
-  color: var(--text);
-}
-
-div.checklist a:hover {
-  text-decoration: underline;
-}
-
-div.custom-checklist x a {
-  color: var(--active);
-}
-
-button.add {
-  background-color: transparent;
-  border: none;
-  padding: 0;
-  margin: 0;
-  text-decoration: none;
-  display: inline-block;
-  cursor: pointer;
-}
-
-body.light-theme {
-  --text: black;
-  --bg-main: white;
-  --bg-secondary: #e4e4e4;
-  --active: #fb9817;
-}
-
-body.light-theme select {
-  border: 1px solid black;
-}
-
-body.light-theme a {
-  color: black;
-}
-
-body.light-theme a:hover {
-  color: var(--active);
-}
-
-button {
-  background-color: transparent;
-  color: var(--text);
-  border: none;
-  text-decoration: none;
-  display: inline-block;
-  cursor: pointer;
-  border-radius: 5px;
-}
-
-body div section {
-  display: none;
-}
-
-select:disabled {
-  opacity: 0.6;
-  cursor: not-allowed;
-}
-
-input:disabled {
-  opacity: 0.6;
-  cursor: not-allowed;
-}
-
-@media (max-width: 1250px) {
-  body.option {
-    flex-direction: column;
-    width: 95vw;
-    align-items: center;
-    padding: 40px 0px;
-  }
-
-  section.links {
-    flex-direction: row;
-    width: 95vw;
-    padding: 0 55px;
-  }
-
-  section.block-option {
-    width: 95vw;
-  }
-
-  div.checklist div x {
-    overflow: hidden;
-  }
-}
-
-html.mobile img,
-html.mobile svg {
-  margin-right: 10px;
-  height: 30px;
-  width: 30px;
-  color: var(--text);
-}
-
-html.mobile div.block {
-  padding: 0 15px;
-  justify-content: space-between;
-  display: flex;
-  align-items: center;
-  margin-top: 20px;
-  margin-bottom: 20px;
-}
-
-html.mobile div.block input[type="checkbox"] {
-  width: 58px;
-  height: 30px;
-}
-
-html.mobile div.block input[type="checkbox"]::before {
-  width: 24px;
-  height: 24px;
-  top: 3px;
-  left: 3.5px;
-}
-
-html.mobile div.block input[type="checkbox"]:checked::before {
-  left: 30px;
-}
-
-html.mobile body.option {
-  flex-direction: column;
-  width: 100%;
-  padding: 0;
-  align-items: center;
-}
-
-html.mobile section.links {
-  flex-direction: row;
-  width: 100%;
-  padding: 0 55px;
-}
-
-html.mobile section.block-option {
-  width: 100%;
-}