about summary refs log tree commit diff stats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/_locales/cs/messages.json4
-rw-r--r--src/_locales/en/messages.json2
-rw-r--r--src/_locales/fa/messages.json137
-rw-r--r--src/_locales/fi/messages.json45
-rw-r--r--src/_locales/fil/messages.json137
-rw-r--r--src/_locales/fr/messages.json160
-rw-r--r--src/_locales/gl/messages.json4
-rw-r--r--src/_locales/hu/messages.json137
-rw-r--r--src/_locales/id/messages.json43
-rw-r--r--src/_locales/nl/messages.json41
-rw-r--r--src/_locales/ru/messages.json2
-rw-r--r--src/_locales/ta/messages.json137
-rw-r--r--src/_locales/uk/messages.json20
-rw-r--r--src/assets/images/chatGpt-icon-light.svg10
-rw-r--r--src/assets/images/chatGpt-icon.svg1
-rw-r--r--src/assets/images/chefkoch-icon.svg43
-rw-r--r--src/assets/javascripts/services.js188
-rw-r--r--src/assets/javascripts/utils.js20
-rw-r--r--src/config.json128
-rw-r--r--src/manifest.json2
-rw-r--r--src/pages/background/background.js46
-rw-r--r--src/pages/components/Label.svelte2
-rw-r--r--src/pages/messages_src/App.svelte104
-rw-r--r--src/pages/options_src/General/SettingsButtons.svelte2
-rw-r--r--src/pages/options_src/Services/Instances.svelte93
-rw-r--r--src/pages/options_src/Services/Services.svelte32
-rw-r--r--src/pages/popup_src/Buttons.svelte142
-rw-r--r--src/pages/popup_src/components/Row.svelte23
-rw-r--r--src/updates/updates.xml2
29 files changed, 1385 insertions, 322 deletions
diff --git a/src/_locales/cs/messages.json b/src/_locales/cs/messages.json
index 48bb0d7c..790bb612 100644
--- a/src/_locales/cs/messages.json
+++ b/src/_locales/cs/messages.json
@@ -143,7 +143,7 @@
         "message": "Přesměrovat"
     },
     "autoPickInstance": {
-        "message": "Automaticky vybrat instanci"
+        "message": "Automaticky zvolit instanci"
     },
     "searchService": {
         "message": "Služba vyhledávání"
@@ -152,7 +152,7 @@
         "message": "Přesměrovat Google"
     },
     "search_frontend": {
-        "message": "Frontend vyhledávání"
+        "message": "Hledat frontend"
     },
     "embedFrontend": {
         "message": "Vložený frontend"
diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json
index 1fd7306b..1a641f5b 100644
--- a/src/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
@@ -143,7 +143,7 @@
         "message": "Redirect"
     },
     "autoPickInstance": {
-        "message": "Auto Pick Instance"
+        "message": "Auto-pick Instance"
     },
     "redirectGoogle": {
         "message": "Redirect Google"
diff --git a/src/_locales/fa/messages.json b/src/_locales/fa/messages.json
new file mode 100644
index 00000000..9ededff6
--- /dev/null
+++ b/src/_locales/fa/messages.json
@@ -0,0 +1,137 @@
+{
+    "both": {
+        "message": "هر دو"
+    },
+    "exportSettings": {
+        "message": "خروجی گرفتن از تنظیمات"
+    },
+    "extensionName": {
+        "message": "LibRedirect"
+    },
+    "settings": {
+        "message": "تنظیمات"
+    },
+    "switchInstance": {
+        "message": "جایگزینی نمونه"
+    },
+    "general": {
+        "message": "عمومی"
+    },
+    "theme": {
+        "message": "پوسته"
+    },
+    "auto": {
+        "message": "خودکار"
+    },
+    "excludeFromRedirecting": {
+        "message": "چشم‌پوشی از هدایت کردن"
+    },
+    "importSettings": {
+        "message": "واردکردن تنظیمات"
+    },
+    "resetSettings": {
+        "message": "بازنشانی تنظیمات"
+    },
+    "enable": {
+        "message": "فعال‌کردن"
+    },
+    "frontend": {
+        "message": "پیشگاه"
+    },
+    "redirectType": {
+        "message": "نوع هدایت"
+    },
+    "onlyEmbedded": {
+        "message": "تنها جاسازی شده"
+    },
+    "onlyNotEmbedded": {
+        "message": "تنها جاسازی نشده"
+    },
+    "addYourFavoriteInstances": {
+        "message": "افزودن نمونه‌های مورد پسند شما"
+    },
+    "light": {
+        "message": "روشن"
+    },
+    "dark": {
+        "message": "تیره"
+    },
+    "showInPopup": {
+        "message": "نمایش در بازشونده"
+    },
+    "copyOriginal": {
+        "message": "رونویسی اصلی"
+    },
+    "copied": {
+        "message": "رونویسی شد"
+    },
+    "redirectToOriginal": {
+        "message": "هدایت به اصلی"
+    },
+    "about": {
+        "message": "درباره"
+    },
+    "unsupportedIframesHandling": {
+        "message": "مدیریت جاسازی‌های پشتیبانی نشده"
+    },
+    "disable": {
+        "message": "غیر‌فعال کردن"
+    },
+    "pingInstances": {
+        "message": "پینگ گرفتن از نمونه‌ها"
+    },
+    "exportSettingsToSync": {
+        "message": "خروجی گرفتن از تنظیمات برای همگام‌سازی"
+    },
+    "importSettingsFromSync": {
+        "message": "واردکردن تنظیمات برای همگام‌سازی"
+    },
+    "services": {
+        "message": "سامانه‌ها"
+    },
+    "service": {
+        "message": "سامانه"
+    },
+    "redirectOnlyInIncognito": {
+        "message": "تنها هدایت کردن در حالت خصوصی"
+    },
+    "bypass": {
+        "message": "دور زدن"
+    },
+    "block": {
+        "message": "مسدود کردن"
+    },
+    "redirect": {
+        "message": "هدایت کردن"
+    },
+    "autoPickInstance": {
+        "message": "گزینش خودکار نمونه"
+    },
+    "redirectGoogle": {
+        "message": "هدایت کردن گوگل"
+    },
+    "search_frontend": {
+        "message": "جستجو پیشگاه"
+    },
+    "searchService": {
+        "message": "جستجو سامانه"
+    },
+    "embedFrontend": {
+        "message": "پیشگاه جاسازی‌شده"
+    },
+    "extensionDescription": {
+        "message": "یک افزونه مرورگر که وبگاه های محبوب را به نمونه‌های دوست‌دار حریم خصوصی هدایت میکند"
+    },
+    "bookmarksMenu": {
+        "message": "فهرست نشان شده‌ها"
+    },
+    "redirectLink": {
+        "message": "تلاش برای هدایت"
+    },
+    "fetchPublicInstances": {
+        "message": "دریافت نمونه‌های عمومی"
+    },
+    "searchHint": {
+        "message": "LIBREDIRECT را به عنوان موتور جستجوی پیش‌فرض تنظیم کنید. برای نحوه انجام در مرورگرهای کروم ، روی <a href='https://libredirect.github.io/docs.html#search_engine_chromium' target='_blank' rel='noopener noreferrer'>اینجا</a> ضربه بزنید."
+    }
+}
diff --git a/src/_locales/fi/messages.json b/src/_locales/fi/messages.json
index ee2793b5..f1f8ca71 100644
--- a/src/_locales/fi/messages.json
+++ b/src/_locales/fi/messages.json
@@ -72,11 +72,11 @@
         "description": "used in the settings page"
     },
     "onlyEmbedded": {
-        "message": "vain upotteet",
+        "message": "vain upotetut",
         "description": "used in the settings page"
     },
     "onlyNotEmbedded": {
-        "message": "vain muut kuin upotteet",
+        "message": "vain muut kuin upotetut",
         "description": "used in the settings page"
     },
     "addYourFavoriteInstances": {
@@ -84,7 +84,7 @@
         "description": "used in the settings page"
     },
     "copyOriginal": {
-        "message": "Copy Original"
+        "message": "Kopioi alkuperäinen"
     },
     "copied": {
         "message": "Kopioitu"
@@ -101,7 +101,7 @@
         "message": "Tietoja"
     },
     "unsupportedIframesHandling": {
-        "message": "Tukemattomien iframejen käsittely"
+        "message": "Tukemattomien upotusten käsittely"
     },
     "fetchPublicInstances": {
         "message": "Hae julkiset instanssit"
@@ -110,36 +110,51 @@
         "message": "Poista käytöstä"
     },
     "pingInstances": {
-        "message": "Ping Instances"
+        "message": "Kokeile yhteyttä instanssiin"
     },
     "exportSettingsToSync": {
-        "message": "Export Settings to Sync"
+        "message": "Vie asetukset Sync:iin"
     },
     "importSettingsFromSync": {
-        "message": "Import Settings from Sync"
+        "message": "Tuo asetukset Sync:istä"
     },
     "services": {
-        "message": "Services"
+        "message": "Palvelut"
     },
     "service": {
-        "message": "Service"
+        "message": "Palvelu"
     },
     "bookmarksMenu": {
-        "message": "Bookmarks menu"
+        "message": "Kirjanmerkkipalkki"
     },
     "redirectOnlyInIncognito": {
-        "message": "Redirect Only in Incognito"
+        "message": "Uudelleenohjaa vain yksityisikkunassa"
     },
     "bypass": {
-        "message": "Bypass"
+        "message": "Ohita"
     },
     "block": {
-        "message": "Block"
+        "message": "Estä"
     },
     "searchHint": {
-        "message": "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>."
+        "message": "Aseta LibRedirect oletushakukoneeksi. Ohjeita varten chromium-selaimissa, paina <a href='https://libredirect.github.io/docs.html#search_engine_chromium' target='_blank' rel='noopener noreferrer'>tästä</a>."
     },
     "redirect": {
-        "message": "Redirect"
+        "message": "Uudelleenohjaa"
+    },
+    "autoPickInstance": {
+        "message": "Automaattisesti valitse instanssi"
+    },
+    "redirectGoogle": {
+        "message": "Uudelleenohjaa Googleen"
+    },
+    "search_frontend": {
+        "message": "Hae käyttöliittymää"
+    },
+    "searchService": {
+        "message": "Hae palveluja"
+    },
+    "embedFrontend": {
+        "message": "Upota käyttöliittymä"
     }
 }
diff --git a/src/_locales/fil/messages.json b/src/_locales/fil/messages.json
new file mode 100644
index 00000000..9dbf07b5
--- /dev/null
+++ b/src/_locales/fil/messages.json
@@ -0,0 +1,137 @@
+{
+    "resetSettings": {
+        "message": "I-reset ang mga setting"
+    },
+    "fetchPublicInstances": {
+        "message": "Kunin ang mga publikong instansya"
+    },
+    "searchHint": {
+        "message": "Itakda ang LibRedirect bilang Default na Search Engine. Para sa kung paano gawin sa mga Chromium browser, mag-click <a href='https://libredirect.github.io/docs.html#search_engine_chromium' target='_blank' rel='noopener noreferrer'>dito</a>."
+    },
+    "unsupportedIframesHandling": {
+        "message": "Pag-handle sa mga hindi sinusuportahang embed"
+    },
+    "extensionDescription": {
+        "message": "Isang web extension na nagre-redirect ng mga popular na site sa mga alternatibong privacy-friendly na frontend at backend"
+    },
+    "service": {
+        "message": "Serbisyo"
+    },
+    "extensionName": {
+        "message": "LibRedirect"
+    },
+    "light": {
+        "message": "Maliwanag"
+    },
+    "switchInstance": {
+        "message": "Palitan ang Instansya"
+    },
+    "settings": {
+        "message": "Mga Setting"
+    },
+    "general": {
+        "message": "General"
+    },
+    "theme": {
+        "message": "Tema"
+    },
+    "dark": {
+        "message": "Madilim"
+    },
+    "auto": {
+        "message": "Awto"
+    },
+    "excludeFromRedirecting": {
+        "message": "Hindi kasama mula sa pag-redirect"
+    },
+    "importSettings": {
+        "message": "I-import ang mga setting"
+    },
+    "exportSettings": {
+        "message": "I-export ang mga setting"
+    },
+    "enable": {
+        "message": "I-enable"
+    },
+    "frontend": {
+        "message": "Frontend"
+    },
+    "redirectType": {
+        "message": "Uri ng Redirect"
+    },
+    "both": {
+        "message": "pareho"
+    },
+    "onlyEmbedded": {
+        "message": "embedded lamang"
+    },
+    "onlyNotEmbedded": {
+        "message": "mga hindi embedded lamang"
+    },
+    "addYourFavoriteInstances": {
+        "message": "Idagdag ang iyong mga paboritong instansya"
+    },
+    "copyOriginal": {
+        "message": "Kopyahin ang Orihinal"
+    },
+    "copied": {
+        "message": "Kinopya"
+    },
+    "redirectToOriginal": {
+        "message": "Mag-redirect sa orihinal"
+    },
+    "about": {
+        "message": "Tungkol sa"
+    },
+    "disable": {
+        "message": "I-disable"
+    },
+    "pingInstances": {
+        "message": "I-ping ang Mga Instansya"
+    },
+    "exportSettingsToSync": {
+        "message": "I-export ang Mga Setting para Mag-sync"
+    },
+    "importSettingsFromSync": {
+        "message": "I-import ang Mga Setting mula sa Sync"
+    },
+    "services": {
+        "message": "Mga Serbisyo"
+    },
+    "bookmarksMenu": {
+        "message": "Menu ng mga bookmark"
+    },
+    "redirectOnlyInIncognito": {
+        "message": "Mag-redirect lamang sa Incognito"
+    },
+    "bypass": {
+        "message": "I-bypass"
+    },
+    "block": {
+        "message": "I-block"
+    },
+    "redirect": {
+        "message": "I-redirect"
+    },
+    "autoPickInstance": {
+        "message": "Awtomatikong piliin ang Instansya"
+    },
+    "redirectGoogle": {
+        "message": "I-redirect ang Google"
+    },
+    "search_frontend": {
+        "message": "Frontend ng Paghahanap"
+    },
+    "searchService": {
+        "message": "Serbisyo ng Paghahanap"
+    },
+    "embedFrontend": {
+        "message": "Frontend ng Embed"
+    },
+    "showInPopup": {
+        "message": "Ipakita sa popup"
+    },
+    "redirectLink": {
+        "message": "Subukang mag-redirect"
+    }
+}
diff --git a/src/_locales/fr/messages.json b/src/_locales/fr/messages.json
new file mode 100644
index 00000000..76930ce0
--- /dev/null
+++ b/src/_locales/fr/messages.json
@@ -0,0 +1,160 @@
+{
+    "extensionName": {
+        "message": "LibRedirect",
+        "description": "name of the extension"
+    },
+    "extensionDescription": {
+        "message": "Une extension web qui redirige les sites populaires vers des interfaces et des serveurs alternatifs respectueux de la vie privée",
+        "description": "description of the extension"
+    },
+    "switchInstance": {
+        "message": "Changer d'instance",
+        "description": "used in manifest.json as shortcut description"
+    },
+    "settings": {
+        "message": "Paramètres",
+        "description": "used in the popup"
+    },
+    "general": {
+        "message": "Général",
+        "description": "used in the settings page"
+    },
+    "theme": {
+        "message": "Thème",
+        "description": "used in the settings page"
+    },
+    "light": {
+        "message": "Clair",
+        "description": "used in the settings page"
+    },
+    "dark": {
+        "message": "Sombre",
+        "description": "used in the settings page"
+    },
+    "auto": {
+        "message": "Auto",
+        "description": "used in the settings page"
+    },
+    "excludeFromRedirecting": {
+        "message": "Exclus de la redirection",
+        "description": "used in the settings page"
+    },
+    "importSettings": {
+        "message": "Importer les paramètres",
+        "description": "used in the settings page"
+    },
+    "exportSettings": {
+        "message": "Exporter les paramètres",
+        "description": "used in the settings page"
+    },
+    "resetSettings": {
+        "message": "Réinitialiser les paramètres",
+        "description": "used in the settings page"
+    },
+    "enable": {
+        "message": "Activer",
+        "description": "used in the settings page"
+    },
+    "showInPopup": {
+        "message": "Afficher dans la fenêtre contextuelle de l'extension",
+        "description": "used in the settings page"
+    },
+    "frontend": {
+        "message": "Interface",
+        "description": "used in the settings page"
+    },
+    "redirectType": {
+        "message": "Type de redirection",
+        "description": "used in the settings page"
+    },
+    "both": {
+        "message": "les deux",
+        "description": "used in the settings page"
+    },
+    "onlyEmbedded": {
+        "message": "éléments embarqués seulement",
+        "description": "used in the settings page"
+    },
+    "onlyNotEmbedded": {
+        "message": "tout sauf éléments embarqués",
+        "description": "used in the settings page"
+    },
+    "addYourFavoriteInstances": {
+        "message": "Ajoutez vos instances favorites",
+        "description": "used in the settings page"
+    },
+    "copyOriginal": {
+        "message": "Copier l'original"
+    },
+    "copied": {
+        "message": "Copié"
+    },
+    "redirectToOriginal": {
+        "message": "Rediriger vers l'original",
+        "description": "Used in context menus when right clicking on a page/tab"
+    },
+    "redirectLink": {
+        "message": "Essayer de rediriger",
+        "description": "Used in context menus when right clicking on a hyperlink"
+    },
+    "about": {
+        "message": "À propos"
+    },
+    "unsupportedIframesHandling": {
+        "message": "Gestion des éléments embarqués non-pris-en-charge"
+    },
+    "fetchPublicInstances": {
+        "message": "Récupérer des instances publiques"
+    },
+    "disable": {
+        "message": "Désactiver"
+    },
+    "pingInstances": {
+        "message": "Envoyer un ping aux instances"
+    },
+    "exportSettingsToSync": {
+        "message": "Exporter les paramètres vers Sync"
+    },
+    "importSettingsFromSync": {
+        "message": "Importer les paramètres depuis Sync"
+    },
+    "services": {
+        "message": "Services"
+    },
+    "service": {
+        "message": "Service"
+    },
+    "bookmarksMenu": {
+        "message": "Menu des marque-pages"
+    },
+    "redirectOnlyInIncognito": {
+        "message": "Rediriger seulement en Mode Incognito"
+    },
+    "bypass": {
+        "message": "Laisser tel quel"
+    },
+    "block": {
+        "message": "Bloquer"
+    },
+    "searchHint": {
+        "message": "Paramétrez LibRedirect pour être votre moteur de recherche par défaut. Pour savoir comment faire sur un navigateur chromium, cliquez <a href='https://libredirect.github.io/docs.html#search_engine_chromium' target='_blank' rel='noopener noreferrer'>ici</a>."
+    },
+    "redirect": {
+        "message": "Rediriger"
+    },
+    "autoPickInstance": {
+        "message": "Choix d'instance automatique"
+    },
+    "redirectGoogle": {
+        "message": "Rediriger Google"
+    },
+    "search_frontend": {
+        "message": "Chercher une interface"
+    },
+    "searchService": {
+        "message": "Chercher un service"
+    },
+    "embedFrontend": {
+        "message": "Interface des éléments embarqués"
+    }
+}
diff --git a/src/_locales/gl/messages.json b/src/_locales/gl/messages.json
index 5fe31474..f8ba00f8 100644
--- a/src/_locales/gl/messages.json
+++ b/src/_locales/gl/messages.json
@@ -98,7 +98,7 @@
         "description": "Used in context menus when right clicking on a hyperlink"
     },
     "about": {
-        "message": "Acerca de"
+        "message": "Sobre"
     },
     "unsupportedIframesHandling": {
         "message": "Xestión de incrustacións sen soporte"
@@ -143,7 +143,7 @@
         "message": "Redirect"
     },
     "autoPickInstance": {
-        "message": "Selección Autom. de instancia"
+        "message": "Selecc. automática instancia"
     },
     "redirectGoogle": {
         "message": "Redirect a Google"
diff --git a/src/_locales/hu/messages.json b/src/_locales/hu/messages.json
new file mode 100644
index 00000000..e5354d11
--- /dev/null
+++ b/src/_locales/hu/messages.json
@@ -0,0 +1,137 @@
+{
+    "settings": {
+        "message": "Beállítások"
+    },
+    "extensionDescription": {
+        "message": "Egy webes kiterjesztés, amely népszerű webhelyeket irányít át alternatív, adatvédelemet tiszteletben tartó elő- és háttérprogramokra"
+    },
+    "general": {
+        "message": "Általános"
+    },
+    "theme": {
+        "message": "Téma"
+    },
+    "light": {
+        "message": "Világos"
+    },
+    "exportSettings": {
+        "message": "Beállítások exportálása"
+    },
+    "both": {
+        "message": "mindkettő"
+    },
+    "dark": {
+        "message": "Sötét"
+    },
+    "auto": {
+        "message": "Automatikus"
+    },
+    "excludeFromRedirecting": {
+        "message": "Átirányításból kizárt"
+    },
+    "importSettings": {
+        "message": "Beállítások importálása"
+    },
+    "resetSettings": {
+        "message": "Beállítások visszaállítása"
+    },
+    "onlyEmbedded": {
+        "message": "csak beágyazott"
+    },
+    "enable": {
+        "message": "Engedélyezés"
+    },
+    "showInPopup": {
+        "message": "Megjelenítés felugró ablakban"
+    },
+    "onlyNotEmbedded": {
+        "message": "csak nem beágyazott"
+    },
+    "copied": {
+        "message": "Másolva"
+    },
+    "redirectLink": {
+        "message": "Kísérlet az átirányításra"
+    },
+    "fetchPublicInstances": {
+        "message": "Nyilvános példányok lekérése"
+    },
+    "addYourFavoriteInstances": {
+        "message": "Adja hozzá kedvenc példányait"
+    },
+    "copyOriginal": {
+        "message": "Eredeti másolása"
+    },
+    "redirectToOriginal": {
+        "message": "Átirányítás az eredetire"
+    },
+    "about": {
+        "message": "Rólunk"
+    },
+    "unsupportedIframesHandling": {
+        "message": "Nem támogatott beágyazások kezelése"
+    },
+    "disable": {
+        "message": "Tiltás"
+    },
+    "services": {
+        "message": "Szolgáltatások"
+    },
+    "pingInstances": {
+        "message": "Példányok pingelése"
+    },
+    "exportSettingsToSync": {
+        "message": "Beállítások exportálása a szinkronizáláshoz"
+    },
+    "importSettingsFromSync": {
+        "message": "Beállítások importálása a szinkronizációból"
+    },
+    "service": {
+        "message": "Szolgáltatás"
+    },
+    "bookmarksMenu": {
+        "message": "Könyvjelzők menü"
+    },
+    "block": {
+        "message": "Letiltás"
+    },
+    "redirectOnlyInIncognito": {
+        "message": "Átirányítás csak inkognitóban"
+    },
+    "redirect": {
+        "message": "Átirányítás"
+    },
+    "switchInstance": {
+        "message": "Példány váltása"
+    },
+    "frontend": {
+        "message": "Előtétprogram"
+    },
+    "redirectType": {
+        "message": "Átirányítás típusa"
+    },
+    "autoPickInstance": {
+        "message": "Példány automatikus kiválasztása"
+    },
+    "redirectGoogle": {
+        "message": "Google átirányítása"
+    },
+    "search_frontend": {
+        "message": "Előtétprogram keresése"
+    },
+    "extensionName": {
+        "message": "LibRedirect"
+    },
+    "bypass": {
+        "message": "Megkerülés"
+    },
+    "searchHint": {
+        "message": "LibRedirect beállítása alapértelmezett keresőmotornak. A Chromium böngészőkben történő művelethez kattintson <a href='https://libredirect.github.io/docs.html#search_engine_chromium' target='_blank' rel='noopener noreferrer'>ide</a>."
+    },
+    "searchService": {
+        "message": "Szolgáltatás keresése"
+    },
+    "embedFrontend": {
+        "message": "Beágyazott előtétprogram"
+    }
+}
diff --git a/src/_locales/id/messages.json b/src/_locales/id/messages.json
index dbacc848..f60c4fcf 100644
--- a/src/_locales/id/messages.json
+++ b/src/_locales/id/messages.json
@@ -8,11 +8,11 @@
         "description": "description of the extension"
     },
     "switchInstance": {
-        "message": "Tukar Instansi",
+        "message": "Ganti Server",
         "description": "used in manifest.json as shortcut description"
     },
     "settings": {
-        "message": "Pengaturan",
+        "message": "Setelan",
         "description": "used in the popup"
     },
     "general": {
@@ -84,7 +84,7 @@
         "description": "used in the settings page"
     },
     "copyOriginal": {
-        "message": "Copy Original"
+        "message": "Salin Asli"
     },
     "copied": {
         "message": "Disalin"
@@ -101,7 +101,7 @@
         "message": "Tentang"
     },
     "unsupportedIframesHandling": {
-        "message": "Penanganan iframe tifak didukung"
+        "message": "Penanganan sematan tidak didukung"
     },
     "fetchPublicInstances": {
         "message": "Dapatkan server publik"
@@ -110,36 +110,51 @@
         "message": "Nonaktifkan"
     },
     "pingInstances": {
-        "message": "Ping Instances"
+        "message": "Ping Server"
     },
     "exportSettingsToSync": {
-        "message": "Export Settings to Sync"
+        "message": "Pengaturan Ekspor ke Sinkronisasi"
     },
     "importSettingsFromSync": {
-        "message": "Import Settings from Sync"
+        "message": "Mengimpor Pengaturan dari Sinkronisasi"
     },
     "services": {
-        "message": "Services"
+        "message": "Layanan"
     },
     "service": {
         "message": "Service"
     },
     "bookmarksMenu": {
-        "message": "Bookmarks menu"
+        "message": "Menu penanda"
     },
     "redirectOnlyInIncognito": {
-        "message": "Redirect Only in Incognito"
+        "message": "Alihkan Hanya dalam Penyamaran"
     },
     "bypass": {
-        "message": "Bypass"
+        "message": "Mengakali"
     },
     "block": {
         "message": "Block"
     },
     "searchHint": {
-        "message": "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>."
+        "message": "Tetapkan LibRedirect sebagai Mesin Pencari Default. Untuk cara melakukannya di browser kromium, klik<a href='https://libredirect.github.io/docs.html#search_engine_chromium' target='_blank' rel='noopener noreferrer'>here</a>."
     },
     "redirect": {
-        "message": "Redirect"
+        "message": "Pengalihan"
+    },
+    "autoPickInstance": {
+        "message": "Pilih Server Otomatis"
+    },
+    "redirectGoogle": {
+        "message": "Alihkan Google"
+    },
+    "search_frontend": {
+        "message": "Frontend Pencarian"
+    },
+    "searchService": {
+        "message": "Layanan Pencarian"
+    },
+    "embedFrontend": {
+        "message": "Frontend Sematan"
     }
-}
\ No newline at end of file
+}
diff --git a/src/_locales/nl/messages.json b/src/_locales/nl/messages.json
index 65e71f31..a6e9e889 100644
--- a/src/_locales/nl/messages.json
+++ b/src/_locales/nl/messages.json
@@ -84,7 +84,7 @@
         "description": "used in the settings page"
     },
     "copyOriginal": {
-        "message": "Copy Original"
+        "message": "Origineel kopiëren"
     },
     "copied": {
         "message": "Gekopieerd"
@@ -101,7 +101,7 @@
         "message": "Over"
     },
     "unsupportedIframesHandling": {
-        "message": "Niet-ondersteunde iframes-afhandeling"
+        "message": "Niet-ondersteunde insluitafhandeling"
     },
     "fetchPublicInstances": {
         "message": "Openbare instanties ophalen"
@@ -110,36 +110,51 @@
         "message": "Uitschakelen"
     },
     "pingInstances": {
-        "message": "Ping Instances"
+        "message": "Instanties pingen"
     },
     "exportSettingsToSync": {
-        "message": "Export Settings to Sync"
+        "message": "Instellingen synchroniseren"
     },
     "importSettingsFromSync": {
-        "message": "Import Settings from Sync"
+        "message": "Instellingen ophalen uit synchronisatie"
     },
     "services": {
-        "message": "Services"
+        "message": "Diensten"
     },
     "service": {
-        "message": "Service"
+        "message": "Dienst"
     },
     "bookmarksMenu": {
-        "message": "Bookmarks menu"
+        "message": "Bladwijzermenu"
     },
     "redirectOnlyInIncognito": {
-        "message": "Redirect Only in Incognito"
+        "message": "Alleen doorverwijzen in privévensters"
     },
     "bypass": {
-        "message": "Bypass"
+        "message": "Omzeilen"
     },
     "block": {
-        "message": "Block"
+        "message": "Blokkeren"
     },
     "searchHint": {
-        "message": "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>."
+        "message": "Stel LibRedirect in als de standaard zoekmachine. Hoe je dit doet in op Chromium gebaseerde browsers, lees je <a href='' target='_blank' rel='noopener noreferrer'>hier</a>."
     },
     "redirect": {
-        "message": "Redirect"
+        "message": "Doorverwijzen"
+    },
+    "autoPickInstance": {
+        "message": "Automatisch instantie kiezen"
+    },
+    "redirectGoogle": {
+        "message": "Google doorverwijzen"
+    },
+    "searchService": {
+        "message": "Zoeken naar dienst"
+    },
+    "search_frontend": {
+        "message": "Zoeken naar front-end"
+    },
+    "embedFrontend": {
+        "message": "Front-end insluiten"
     }
 }
\ No newline at end of file
diff --git a/src/_locales/ru/messages.json b/src/_locales/ru/messages.json
index 0b3a816e..08757a5c 100644
--- a/src/_locales/ru/messages.json
+++ b/src/_locales/ru/messages.json
@@ -146,7 +146,7 @@
         "message": "Перенаправление Google"
     },
     "autoPickInstance": {
-        "message": "Выбирать сервер автоматически"
+        "message": "Выбрать сервер автоматически"
     },
     "searchService": {
         "message": "Служба поиска"
diff --git a/src/_locales/ta/messages.json b/src/_locales/ta/messages.json
new file mode 100644
index 00000000..d566ddaa
--- /dev/null
+++ b/src/_locales/ta/messages.json
@@ -0,0 +1,137 @@
+{
+    "extensionName": {
+        "message": "லிப்ரெடிரிடர்"
+    },
+    "switchInstance": {
+        "message": "சான்று"
+    },
+    "copyOriginal": {
+        "message": "அசல் நகலெடுக்கவும்"
+    },
+    "autoPickInstance": {
+        "message": "ஆட்டோ-பிக் நிகழ்வு"
+    },
+    "extensionDescription": {
+        "message": "பிரபலமான தளங்களை மாற்று தனியுரிமை நட்பு முன்பக்கங்கள் மற்றும் பின்தளத்தில் திருப்பி விடும் ஒரு வலை நீட்டிப்பு"
+    },
+    "settings": {
+        "message": "அமைப்புகள்"
+    },
+    "general": {
+        "message": "பொது"
+    },
+    "theme": {
+        "message": "கருப்பொருள்"
+    },
+    "light": {
+        "message": "ஒளி"
+    },
+    "dark": {
+        "message": "இருண்ட"
+    },
+    "auto": {
+        "message": "தானி"
+    },
+    "excludeFromRedirecting": {
+        "message": "திருப்பிவிடுவதிலிருந்து விலக்கப்பட்டது"
+    },
+    "importSettings": {
+        "message": "அமைப்புகளை இறக்குமதி செய்யுங்கள்"
+    },
+    "exportSettings": {
+        "message": "ஏற்றுமதி அமைப்புகள்"
+    },
+    "resetSettings": {
+        "message": "அமைப்புகளை மீட்டமைக்கவும்"
+    },
+    "enable": {
+        "message": "இயக்கு"
+    },
+    "showInPopup": {
+        "message": "பாப்அப்பில் காட்டு"
+    },
+    "frontend": {
+        "message": "ஃபிரான்ட்"
+    },
+    "redirectType": {
+        "message": "திருப்பி வகை"
+    },
+    "both": {
+        "message": "இரண்டும்"
+    },
+    "onlyEmbedded": {
+        "message": "உட்பொதிக்கப்பட்டது"
+    },
+    "onlyNotEmbedded": {
+        "message": "உட்பொதிக்கப்படவில்லை"
+    },
+    "addYourFavoriteInstances": {
+        "message": "உங்களுக்கு பிடித்த நிகழ்வுகளைச் சேர்க்கவும்"
+    },
+    "copied": {
+        "message": "நகலெடுக்கப்பட்டது"
+    },
+    "redirectToOriginal": {
+        "message": "அசலுக்கு திருப்பி விடுங்கள்"
+    },
+    "redirectLink": {
+        "message": "திருப்பிவிட முயற்சி"
+    },
+    "about": {
+        "message": "பற்றி"
+    },
+    "unsupportedIframesHandling": {
+        "message": "ஆதரிக்கப்படாத உட்பொதிகள் கையாளுதல்"
+    },
+    "fetchPublicInstances": {
+        "message": "பொது நிகழ்வுகளைப் பெறுங்கள்"
+    },
+    "disable": {
+        "message": "முடக்கு"
+    },
+    "pingInstances": {
+        "message": "பிங் நிகழ்வுகள்"
+    },
+    "exportSettingsToSync": {
+        "message": "ஒத்திசைக்க அமைப்புகளை ஏற்றுமதி செய்யுங்கள்"
+    },
+    "importSettingsFromSync": {
+        "message": "ஒத்திசைவிலிருந்து அமைப்புகளை இறக்குமதி செய்யுங்கள்"
+    },
+    "services": {
+        "message": "சேவைகள்"
+    },
+    "service": {
+        "message": "பணி"
+    },
+    "bookmarksMenu": {
+        "message": "புக்மார்க்ச் பட்டியல்"
+    },
+    "redirectOnlyInIncognito": {
+        "message": "மறைமுகத்தில் மட்டுமே திருப்பி விடுங்கள்"
+    },
+    "bypass": {
+        "message": "பைபாச்"
+    },
+    "block": {
+        "message": "தொகுதி"
+    },
+    "searchHint": {
+        "message": "இயல்புநிலை தேடுபொறியாக Lirbredirect ஐ அமைக்கவும். குரோமியம் உலாவிகளில் எவ்வாறு செய்வது என்பதற்கு, <a href = 'https: //libredirect.github.io/docs.html#search_engine_chromium' target = '_ வெற்று' rel = 'noopener norferrer'> இங்கே </a>."
+    },
+    "redirect": {
+        "message": "திருப்பி விடுங்கள்"
+    },
+    "redirectGoogle": {
+        "message": "Google ஐ திருப்பி விடுங்கள்"
+    },
+    "search_frontend": {
+        "message": "முன்பக்கத்தைத் தேடுங்கள்"
+    },
+    "searchService": {
+        "message": "தேடல் பணி"
+    },
+    "embedFrontend": {
+        "message": "ஃபிரான்டெண்ட் உட்பொதிக்கவும்"
+    }
+}
diff --git a/src/_locales/uk/messages.json b/src/_locales/uk/messages.json
index 7d79fbde..6efe626f 100644
--- a/src/_locales/uk/messages.json
+++ b/src/_locales/uk/messages.json
@@ -110,13 +110,13 @@
         "message": "Вимкнути"
     },
     "pingInstances": {
-        "message": "Ping Instances"
+        "message": "Опитати сервери"
     },
     "exportSettingsToSync": {
-        "message": "Export Settings to Sync"
+        "message": "Експорт налаштувань до служби синхронізації"
     },
     "importSettingsFromSync": {
-        "message": "Import Settings from Sync"
+        "message": "Імпорт налаштувань зі служби синхронізації"
     },
     "services": {
         "message": "Служби"
@@ -128,19 +128,19 @@
         "message": "Меню закладок"
     },
     "redirectOnlyInIncognito": {
-        "message": "Redirect Only in Incognito"
+        "message": "Переспрямовувати лише в режимі інкогніто"
     },
     "bypass": {
-        "message": "Bypass"
+        "message": "Обхід"
     },
     "block": {
         "message": "Block"
     },
     "searchHint": {
-        "message": "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>."
+        "message": "Установити LibRedirect усталеним засобом пошуку. Як це зробити у браузерах на основі chromium, читайте <a href='https://libredirect.github.io/docs.html#search_engine_chromium' target='_blank' rel='noopener noreferrer'>тут</a>."
     },
     "redirect": {
-        "message": "Redirect"
+        "message": "Переспрямувати"
     },
     "autoPickInstance": {
         "message": "Автопідбір сервера"
@@ -150,5 +150,11 @@
     },
     "searchService": {
         "message": "Служба пошуку"
+    },
+    "search_frontend": {
+        "message": "Пошуковий інтерфейс"
+    },
+    "embedFrontend": {
+        "message": "Вбудований інтерфейс"
     }
 }
\ No newline at end of file
diff --git a/src/assets/images/chatGpt-icon-light.svg b/src/assets/images/chatGpt-icon-light.svg
new file mode 100644
index 00000000..b3df81fb
--- /dev/null
+++ b/src/assets/images/chatGpt-icon-light.svg
@@ -0,0 +1,10 @@
+<svg width="320" height="320" viewBox="0 0 320 320" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_10145_290560)">
+<path d="M297.06 130.97C304.32 109.18 301.82 85.31 290.21 65.49C272.75 35.09 237.65 19.45 203.37 26.81C188.12 9.63002 166.21 -0.139981 143.24 1.93887e-05C108.2 -0.0799806 77.11 22.48 66.33 55.82C43.82 60.43 24.39 74.52 13.02 94.49C-4.57001 124.81 -0.560007 163.03 22.94 189.03C15.68 210.82 18.18 234.69 29.79 254.51C47.25 284.91 82.35 300.55 116.63 293.19C131.87 310.37 153.79 320.14 176.76 319.99C211.82 320.08 242.92 297.5 253.7 264.13C276.21 259.52 295.64 245.43 307.01 225.46C324.58 195.14 320.56 156.95 297.07 130.95L297.06 130.97ZM176.78 299.08C162.75 299.1 149.16 294.19 138.39 285.2C138.88 284.94 139.73 284.47 140.28 284.13L204 247.33C207.26 245.48 209.26 242.01 209.24 238.26V148.43L236.17 163.98C236.46 164.12 236.65 164.4 236.69 164.72V239.11C236.65 272.19 209.86 299.01 176.78 299.08ZM47.94 244.05C40.91 231.91 38.38 217.68 40.79 203.87C41.26 204.15 42.09 204.66 42.68 205L106.4 241.8C109.63 243.69 113.63 243.69 116.87 241.8L194.66 196.88V227.98C194.68 228.3 194.53 228.61 194.28 228.81L129.87 266C101.18 282.52 64.54 272.7 47.95 244.05H47.94ZM31.17 104.96C38.17 92.8 49.22 83.5 62.38 78.67C62.38 79.22 62.35 80.19 62.35 80.87V154.48C62.33 158.22 64.33 161.69 67.58 163.54L145.37 208.45L118.44 224C118.17 224.18 117.83 224.21 117.53 224.08L53.11 186.86C24.48 170.28 14.66 133.65 31.16 104.97L31.17 104.96ZM252.43 156.45L174.64 111.53L201.57 95.99C201.84 95.81 202.18 95.78 202.48 95.91L266.9 133.1C295.58 149.67 305.41 186.36 288.84 215.04C281.83 227.18 270.79 236.48 257.64 241.32V165.51C257.67 161.77 255.68 158.31 252.44 156.45H252.43ZM279.23 116.11C278.76 115.82 277.93 115.32 277.34 114.98L213.62 78.18C210.39 76.29 206.39 76.29 203.15 78.18L125.36 123.1V92C125.34 91.68 125.49 91.37 125.74 91.17L190.15 54.01C218.84 37.46 255.52 47.31 272.06 76.01C279.05 88.13 281.58 102.32 279.21 116.11H279.23ZM110.72 171.54L83.78 155.99C83.49 155.85 83.3 155.57 83.26 155.25V80.86C83.28 47.74 110.15 20.9 143.27 20.92C157.28 20.92 170.84 25.84 181.61 34.8C181.12 35.06 180.28 35.53 179.72 35.87L116 72.67C112.74 74.52 110.74 77.98 110.76 81.73L110.72 171.52V171.54ZM125.35 140L160 119.99L194.65 139.99V180L160 200L125.35 180V140Z" fill="white"/>
+</g>
+<defs>
+<clipPath id="clip0_10145_290560">
+<rect width="320" height="320" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/src/assets/images/chatGpt-icon.svg b/src/assets/images/chatGpt-icon.svg
new file mode 100644
index 00000000..e04db75a
--- /dev/null
+++ b/src/assets/images/chatGpt-icon.svg
@@ -0,0 +1 @@
+<svg viewBox="0 0 320 320" xmlns="http://www.w3.org/2000/svg"><path d="m297.06 130.97c7.26-21.79 4.76-45.66-6.85-65.48-17.46-30.4-52.56-46.04-86.84-38.68-15.25-17.18-37.16-26.95-60.13-26.81-35.04-.08-66.13 22.48-76.91 55.82-22.51 4.61-41.94 18.7-53.31 38.67-17.59 30.32-13.58 68.54 9.92 94.54-7.26 21.79-4.76 45.66 6.85 65.48 17.46 30.4 52.56 46.04 86.84 38.68 15.24 17.18 37.16 26.95 60.13 26.8 35.06.09 66.16-22.49 76.94-55.86 22.51-4.61 41.94-18.7 53.31-38.67 17.57-30.32 13.55-68.51-9.94-94.51zm-120.28 168.11c-14.03.02-27.62-4.89-38.39-13.88.49-.26 1.34-.73 1.89-1.07l63.72-36.8c3.26-1.85 5.26-5.32 5.24-9.07v-89.83l26.93 15.55c.29.14.48.42.52.74v74.39c-.04 33.08-26.83 59.9-59.91 59.97zm-128.84-55.03c-7.03-12.14-9.56-26.37-7.15-40.18.47.28 1.3.79 1.89 1.13l63.72 36.8c3.23 1.89 7.23 1.89 10.47 0l77.79-44.92v31.1c.02.32-.13.63-.38.83l-64.41 37.19c-28.69 16.52-65.33 6.7-81.92-21.95zm-16.77-139.09c7-12.16 18.05-21.46 31.21-26.29 0 .55-.03 1.52-.03 2.2v73.61c-.02 3.74 1.98 7.21 5.23 9.06l77.79 44.91-26.93 15.55c-.27.18-.61.21-.91.08l-64.42-37.22c-28.63-16.58-38.45-53.21-21.95-81.89zm221.26 51.49-77.79-44.92 26.93-15.54c.27-.18.61-.21.91-.08l64.42 37.19c28.68 16.57 38.51 53.26 21.94 81.94-7.01 12.14-18.05 21.44-31.2 26.28v-75.81c.03-3.74-1.96-7.2-5.2-9.06zm26.8-40.34c-.47-.29-1.3-.79-1.89-1.13l-63.72-36.8c-3.23-1.89-7.23-1.89-10.47 0l-77.79 44.92v-31.1c-.02-.32.13-.63.38-.83l64.41-37.16c28.69-16.55 65.37-6.7 81.91 22 6.99 12.12 9.52 26.31 7.15 40.1zm-168.51 55.43-26.94-15.55c-.29-.14-.48-.42-.52-.74v-74.39c.02-33.12 26.89-59.96 60.01-59.94 14.01 0 27.57 4.92 38.34 13.88-.49.26-1.33.73-1.89 1.07l-63.72 36.8c-3.26 1.85-5.26 5.31-5.24 9.06l-.04 89.79zm14.63-31.54 34.65-20.01 34.65 20v40.01l-34.65 20-34.65-20z"/></svg>
\ No newline at end of file
diff --git a/src/assets/images/chefkoch-icon.svg b/src/assets/images/chefkoch-icon.svg
new file mode 100644
index 00000000..12e1f3ba
--- /dev/null
+++ b/src/assets/images/chefkoch-icon.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   class="w-logo"
+   width="35.532116"
+   height="35.532116"
+   viewBox="0 0 35.532115 35.532115"
+   fill="none"
+   data-v-73c3726b=""
+   version="1.1"
+   id="svg9"
+   sodipodi:docname="logo.svg"
+   inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <defs
+     id="defs9" />
+  <sodipodi:namedview
+     id="namedview9"
+     pagecolor="#ffffff"
+     bordercolor="#000000"
+     borderopacity="0.25"
+     inkscape:showpageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:deskcolor="#d1d1d1"
+     inkscape:zoom="5.6568542"
+     inkscape:cx="10.69499"
+     inkscape:cy="32.880465"
+     inkscape:window-width="1888"
+     inkscape:window-height="1052"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg9" />
+  <path
+     class="w-logo__hat"
+     data-testid="logo-hat"
+     d="m 28.25197,6.8567782 -1.5339,15.1350798 -0.3608,3.3157 c -0.0677,0.3158 -0.2707,0.609 -0.8572,0.7669 -0.1579,0.0451 -0.3158,0.0902 -0.4962,0.1128 -0.3158,0.0677 -0.6316,-0.1805 -0.5865,-0.5188 l 1.3308,-17.3680898 c 0.0452,-0.47368 -0.3157,-0.87969 -0.7894,-0.90224 h -0.0902 c -0.4737,-0.04511 -0.8797,0.31578 -0.9023,0.78946 l -1.3533,17.7740698 c -0.0226,0.3835 -0.3158,0.6767 -0.6993,0.7218 -0.2255,0.0226 -0.4737,0.0451 -0.6992,0.0677 -0.3383,0.0225 -0.6316,-0.2481 -0.6316,-0.5865 l 0.3609,-18.4958598 c 0.0226,-0.47368 -0.3609,-0.85713 -0.812,-0.87968 h -0.0902 c -0.4737,-0.02256 -0.8571,0.36089 -0.8797,0.81201 l -0.3609,18.6312298 c -0.0226,0.3609 -0.3158,0.6541 -0.6541,0.6541 -0.2481,0 -0.4963,0 -0.7444,0 -0.3609,0 -0.6541,-0.2932 -0.6766,-0.6541 L 16.29727,8.9093782 c -0.0226,-0.47368 -0.406,-0.83457 -0.8797,-0.81202 h -0.09022 c -0.47368,0.02256 -0.834569,0.40601 -0.812009,0.87969 L 14.9439,26.164658 c 0,0.3384 -0.270669,0.609 -0.631569,0.5865 -0.22556,-0.0226 -0.45112,-0.0451 -0.67668,-0.0677 -0.38345,-0.0451 -0.67668,-0.3383 -0.69923,-0.7218 L 11.628171,8.3905882 c -0.04511,-0.47367 -0.45112,-0.81201 -0.90224,-0.78946 h -0.09022 c -0.47368,0.04511 -0.8120199,0.45112 -0.7894599,0.90224 L 11.131941,25.668458 c 0.02256,0.3383 -0.27067,0.5865 -0.58646,0.5188 -0.18044,-0.0451 -0.36089,-0.0902 -0.54134,-0.1353 -0.6090098,-0.1805 -0.7894598,-0.4737 -0.8571298,-0.8121 -0.04511,-0.4736 -0.31578,-3.1578 -0.33833,-3.248 -0.33834,-3.2932 -1.51125,-14.8418498 -1.51125,-14.8418498 -0.02256,-1.10524 -0.04512,-1.57892 1.08268,-2.14282 3.0450598,-1.51125 6.9246888,-0.06766 6.9246888,-0.06766 l 2.00747,-0.76691 c 2.6842,-0.9699 6.5638,-0.87968 9.4058,0.76691 0.5414,0.31578 1.6241,0.83457 1.5339,1.91725 z m -2.0752,21.7439798 c 0,0 0,0.7669 -0.0226,1.1503 -0.0225,0.4737 -0.0225,1.0376 -0.9473,1.2632 -4.8721,1.2857 -9.9923,1.2405 -14.886949,0 -0.9473498,-0.2481 -0.9247898,-0.7444 -0.9473498,-1.1955 -0.02255,-0.3834 -0.02255,-1.218 -0.02255,-1.2406 -0.02256,-0.4737 0.3383399,-0.7443 0.8120098,-0.6541 5.007429,0.9925 10.172739,0.9925 15.180139,0 0.4737,-0.0902 0.8572,0.203 0.8346,0.6767 z m 3.5864,-23.7063398 c -0.5865,-0.81202 -2.5037,-1.80448 -3.8571,-2.345826 -3.4961,-1.263135 -7.466,-0.924796 -10.57872,0.496226 l -0.40601,-0.11278 c -2.639039,-0.857123 -5.7743288,-0.406003 -7.5787988,0.5639 -1.127802,0.60901 -1.6465891,1.10525 -1.8270361,1.89471 -0.1127804,0.31578 -0.1804486,0.87968 -0.090225,1.8947 0,0.04511 -4e-7,0.06767 0.022556,0.11278 0.2706721,3.2029498 2.0300352,18.9921298 2.0525952,19.0147298 0.29323,3.1352 -0.15789,4.3984 0.47367,5.2329 0.04512,0.0677 0.09023,0.1128 0.13534,0.1579 0.27067,0.2707 0.65412,0.4963 1.26313,0.7218 0.11278,0.0451 0.24812,0.0902 0.3608998,0.1354 0.4962299,0.1804 1.0375699,0.3383 1.6014699,0.4736 2.12026,0.4963 4.375829,0.6316 6.428429,0.6316 2.0526,0 4.3308,-0.1353 6.4285,-0.6316 0.5639,-0.1353 1.1278,-0.2932 1.6015,-0.4736 0.1127,-0.0452 0.2481,-0.0903 0.3608,-0.1354 0.6091,-0.2481 1.0151,-0.4737 1.2632,-0.7218 0.0451,-0.0451 0.0902,-0.0902 0.1353,-0.1579 0.6316,-0.8345 0.203,-2.0977 0.4737,-5.2329 0,-0.0226 1.7819,-15.81178 2.0526,-19.0147298 0,-0.04511 0,-0.09023 0.0225,-0.11278 0.1579,-1.6917 -0.1127,-2.0526 -0.3383,-2.39093 z"
+     fill="#3b8047"
+     id="path1" />
+</svg>
diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js
index 7213380f..961759c2 100644
--- a/src/assets/javascripts/services.js
+++ b/src/assets/javascripts/services.js
@@ -54,9 +54,10 @@ function regexArray(service, url, config, options, frontend) {
  * @param {URL} url
  * @param {string} frontend
  * @param {string} randomInstance
+ * @param {string} type
  * @returns {undefined|string}
  */
-function rewrite(url, originUrl, frontend, randomInstance) {
+function rewrite(url, originUrl, frontend, randomInstance, type) {
   switch (frontend) {
     case "hyperpipe":
       for (const key of [...url.searchParams.keys()]) if (key !== "q") url.searchParams.delete(key)
@@ -99,6 +100,7 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       if (/\/@[a-z]+\//.exec(url.pathname)) return randomInstance
       return `${randomInstance}${url.pathname}${url.search}`
     }
+    case "small":
     case "libMedium":
     case "scribe": {
       const regex = url.hostname.match(/^(link|cdn-images-\d+|.*)\.medium\.com/)
@@ -220,9 +222,9 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       return `${randomInstance}${url.pathname}${url.search}`
     case "redlib":
     case "libreddit": {
-      const subdomain = url.hostname.match(/^(?:(?:external-)?preview|i)(?=\.redd\.it)/)
+      const subdomain = url.hostname.match(/^(?:((?:external-)?preview|i)\.)?redd\.it/)
       if (!subdomain) return `${randomInstance}${url.pathname}${url.search}`
-      switch (subdomain[0]) {
+      switch (subdomain[1]) {
         case "preview":
           return `${randomInstance}/preview/pre${url.pathname}${url.search}`
         case "external-preview":
@@ -230,7 +232,7 @@ function rewrite(url, originUrl, frontend, randomInstance) {
         case "i":
           return `${randomInstance}/img${url.pathname}`
       }
-      return randomInstance
+      return `${randomInstance}/comments${url.pathname}`
     }
     case "teddit":
       if (/^(?:(?:external-)?preview|i)\.redd\.it/.test(url.hostname)) {
@@ -238,6 +240,7 @@ function rewrite(url, originUrl, frontend, randomInstance) {
         else return `${randomInstance}${url.pathname}${url.search}&teddit_proxy=${url.hostname}`
       }
       return `${randomInstance}${url.pathname}${url.search}`
+    case "troddit":
     case "eddrit":
       if (/^(?:(?:external-)?preview|i)\.redd\.it/.test(url.hostname)) return randomInstance
       return `${randomInstance}${url.pathname}${url.search}`
@@ -267,8 +270,11 @@ function rewrite(url, originUrl, frontend, randomInstance) {
         // https://stackexchange.com or https://superuser.com
         return `${randomInstance}${url.pathname}${url.search}`
       }
-      const regex = url.href.match(/https?:\/{2}(?:([a-zA-Z0-9-]+)\.)?stackexchange\.com\//)
+      const regex = url.href.match(/https?:\/{2}(?:([a-zA-Z0-9-]+)\.(meta\.)?)?stackexchange\.com\//)
       if (regex && regex.length > 1) {
+        if (regex[2]) {
+          return `${randomInstance}/exchange/${url.hostname}${url.pathname}${url.search}`
+        }
         const subdomain = regex[1]
         return `${randomInstance}/exchange/${subdomain}${url.pathname}${url.search}`
       }
@@ -282,6 +288,15 @@ function rewrite(url, originUrl, frontend, randomInstance) {
     }
     case "biblioReads":
       return `${randomInstance}${url.pathname}${url.search}`
+    case "wikimore": {
+      let hostSplit = url.host.split(".")
+      // wikiless doesn't have mobile view support yet
+      if (hostSplit[0] != "wikipedia" && hostSplit[0] != "www") {
+        const lang = url.hostname.split(".")[0]
+        return `${randomInstance}/wiki/${lang}${url.pathname}${url.search}${url.hash}`
+      }
+      return `${randomInstance}${url.pathname}${url.search}${url.hash}`
+    }
     case "wikiless": {
       let hostSplit = url.host.split(".")
       // wikiless doesn't have mobile view support yet
@@ -292,6 +307,7 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       }
       return `${randomInstance}${url.pathname}${url.search}${url.hash}`
     }
+    case "offtiktok":
     case "proxiTok":
       if (url.pathname.startsWith("/email")) return randomInstance
       return `${randomInstance}${url.pathname}${url.search}`
@@ -353,7 +369,10 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       }
     }
     case "binternet":
-      if (url.hostname == "i.pinimg.com") return `${randomInstance}/image_proxy.php?url=${url.href}`
+      if (url.hostname == "i.pinimg.com") return `${randomInstance}/image_proxy.php?url=${encodeURIComponent(url.href)}`
+      return `${randomInstance}${url.pathname}${url.search}`
+    case "painterest":
+      if (url.hostname == "i.pinimg.com") return `${randomInstance}/_/proxy?url=${encodeURIComponent(url.href)}`
       return `${randomInstance}${url.pathname}${url.search}`
     case "laboratory": {
       let path = url.pathname
@@ -378,11 +397,24 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       }
       return `${randomInstance}${url.pathname}${url.search}`
     }
+    case "vixipy": {
+      const regex = /\/[a-z]{1,3}\/(.*)/.exec(url.pathname)
+      if (regex) {
+        let path = regex[1]
+        if (path.startsWith("tags/")) path = path.replace(/tags/, "tag")
+        return `${randomInstance}/${path}${url.search}`
+      }
+      return `${randomInstance}${url.pathname}${url.search}`
+    }
     case "invidious": {
+      // tracker
       url.searchParams.delete("si")
+
+      if (type == "sub_frame") url.searchParams.append("autoplay", "0")
+
       if (url.hostname == "youtu.be" || (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live"))) {
         const watch = url.pathname.substring(url.pathname.lastIndexOf("/") + 1)
-        return `${randomInstance}/watch?v=${watch}${url.search.replace("?", "&")}`
+        return `${randomInstance}/watch?v=${watch}&${url.search.substring(1)}`
       }
       if (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/redirect?")) return url.href
       return `${randomInstance}${url.pathname}${url.search}`
@@ -501,6 +533,7 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       }
       return `${randomInstance}${url.pathname}${url.search}`
     }
+    case "ultimateTab":
     case "freetar":
       if (url.pathname.startsWith("/search.php")) {
         url.searchParams.set("search_term", url.searchParams.get("value"))
@@ -519,16 +552,16 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       return `${randomInstance}${url.pathname}${url.search}`
     }
     case "skunkyArt": {
-      if (url.pathname.startsWith("/search")) return `${randomInstance}${url.pathname}${url.search}&scope=all`
+      if (url.pathname.startsWith("/search")) return `${randomInstance}${url.pathname}${url.search}&type=all`
 
-      const artReg = /^\/.*?\/art\/(.*)\/?/.exec(url.pathname)
-      if (artReg) return `${randomInstance}/post/art/${artReg[1]}${url.search}`
+      const artReg = /^\/(.*?)\/art\/(.*)\/?/.exec(url.pathname)
+      if (artReg) return `${randomInstance}/post/${artReg[1]}/${artReg[2]}${url.search}`
 
       const userReg = /^\/([^\/]+)$/.exec(url.pathname)
-      if (userReg) return `${randomInstance}/user/${userReg[1]}${url.search}`
+      if (userReg) return `${randomInstance}/group_user?q=${userReg[1]}&type=about`
 
-      const galleryReg = /^\/.*?\/gallery(\/$|$)$/.exec(url.pathname)
-      if (galleryReg) return `${randomInstance}/user/${userReg[1]}?a=gallery`
+      const galleryReg = /^\/(.*?)\/gallery(\/$|$)$/.exec(url.pathname)
+      if (galleryReg) return `${randomInstance}/group_user?q=${galleryReg[1]}&type=gallery`
 
       return `${randomInstance}${url.pathname}${url.search}`
     }
@@ -550,6 +583,43 @@ function rewrite(url, originUrl, frontend, randomInstance) {
       const accountReg = /^\/([^\/]+)\/?$/.exec(url.pathname)
       if (accountReg) return `${randomInstance}/account${url.pathname}${url.search}`
 
+    case "duckDuckGoAiChat":
+      return "https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=1"
+
+    case "soundcloak":
+      if (url.pathname.startsWith("/feed") || url.pathname.startsWith("/stream")) {
+        // this feature requires authentication and is unsupported, so just redirect to main page
+        return randomInstance
+      }
+
+      if (url.pathname.startsWith("/search")) {
+        if (!url.search) {
+          return randomInstance
+        }
+
+        let type = ""
+        if (url.pathname.startsWith("/search/sounds")) {
+          type = "tracks"
+        } else if (url.pathname.startsWith("/search/people")) {
+          type = "users"
+        } else if (url.pathname.startsWith("/search/albums") || url.pathname.startsWith("/search/sets")) {
+          type = "playlists"
+        }
+
+        if (type) {
+          type = "&type=" + type
+        } else {
+          return randomInstance // fallback for unsupported search types (searching for anything for example)
+        }
+
+        return `${randomInstance}/search${url.search}${type}`
+      }
+
+      if (url.host == "on.soundcloud.com") {
+        return `${randomInstance}/on${url.pathname}`
+      }
+
+      return `${randomInstance}${url.pathname}${url.search}`
     case "piped":
     case "pipedMaterial":
     case "cloudtube":
@@ -627,7 +697,7 @@ function redirect(url, type, originUrl, documentUrl, incognito, forceRedirection
   }
   if (!frontend) return
 
-  return rewrite(url, originUrl, frontend, randomInstance)
+  return rewrite(url, originUrl, frontend, randomInstance, type)
 }
 
 /**
@@ -647,30 +717,19 @@ async function redirectAsync(url, type, originUrl, documentUrl, incognito, force
 /**
  * @param {URL} url
  */
-function computeService(url) {
-  return new Promise(async resolve => {
-    const config = await utils.getConfig()
-    const options = await utils.getOptions()
-    for (const service in config.services) {
-      if (regexArray(service, url, config, options)) {
-        resolve(service)
-        return
-      } else {
-        for (const frontend in config.services[service].frontends) {
-          if (all(service, frontend, options, config).findIndex(instance => url.href.startsWith(instance)) >= 0) {
-            return resolve(service)
-          }
-        }
-      }
-    }
-    resolve()
-  })
-}
-export function computeFrontend(url) {
+async function computeServiceFrontend(url) {
+  const config = await utils.getConfig()
+  const options = await utils.getOptions()
   for (const service in config.services) {
-    for (const frontend in config.services[service].frontends) {
-      if (all(service, frontend, options, config).findIndex(instance => url.href.startsWith(instance)) >= 0) {
-        return { service, frontend }
+    if (regexArray(service, url, config, options)) {
+      return { service, frontend: null }
+    } else {
+      for (const frontend in config.services[service].frontends) {
+        const instances = all(service, frontend, options, config)
+        const i = instances.findIndex(instance => url.href.startsWith(instance))
+        if (i >= 0) {
+          return { service, frontend }
+        }
       }
     }
   }
@@ -765,6 +824,39 @@ async function reverse(url) {
         return `${config.services[service].url}/${url.search.slice(1)}`
       case "goodreads":
         return `https://goodreads.com${url.pathname}${url.search}`
+      case "soundcloud":
+        if (frontend == "soundcloak") {
+          if (url.pathname.includes("/_/")) {
+            // soundcloak-specific pages
+            return `${config.services[service].url}${url.pathname.split("/_/")[0]}`
+          }
+
+          if (url.pathname == "/search") {
+            let type = url.searchParams.get("type")
+            switch (type) {
+              case "playlists":
+                type = "sets"
+                break
+              case "tracks":
+                type = "sounds"
+                break
+              case "users":
+                type = "people"
+                break
+              default:
+                type = ""
+            }
+
+            url.searchParams.delete("type")
+            if (!type) {
+              return `${config.services[service].url}/search?${url.searchParams.toString()}`
+            } else {
+              return `${config.services[service].url}/search/${type}?${url.searchParams.toString()}`
+            }
+          }
+
+          return `${config.services[service].url}${url.pathname}`
+        }
       default:
         return
     }
@@ -783,9 +875,12 @@ const defaultInstances = {
   poketube: ["https://poketube.fun"],
   proxiTok: ["https://proxitok.pabloferreiro.es"],
   redlib: ["https://libreddit.vhack.eu"],
+  offtiktok: ["https://www.offtiktok.com"],
   eddrit: ["https://eddrit.com"],
+  troddit: ["https://www.troddit.com"],
   scribe: ["https://scribe.rip"],
   libMedium: ["https://md.vern.cc"],
+  small: ["https://small.bloat.cat"],
   quetre: ["https://quetre.iket.me"],
   libremdb: ["https://libremdb.iket.me"],
   simplyTranslate: ["https://simplytranslate.org"],
@@ -811,27 +906,36 @@ const defaultInstances = {
   wolfreeAlpha: ["https://gqq.gitlab.io", "https://uqq.gitlab.io"],
   laboratory: ["https://lab.vern.cc"],
   binternet: ["https://bn.bloat.cat"],
+  painterest: ["https://pt.bloat.cat"],
   pixivFe: ["https://pixivfe.exozy.me"],
   liteXiv: ["https://litexiv.exozy.me"],
+  vixipy: ["https://vx.maid.zone"],
   indestructables: ["https://indestructables.private.coffee"],
   destructables: ["https://ds.vern.cc"],
+  structables: ["https://structables.private.coffee"],
   safetwitch: ["https://safetwitch.drgns.space"],
   twineo: ["https://twineo.exozy.me"],
   proxigram: ["https://ig.opnxng.com"],
-  tuboYoutube: ["https://tubo.migalmoreno.com"],
-  tuboSoundcloud: ["https://tubo.migalmoreno.com"],
+  tuboYoutube: ["https://tubo.media"],
+  tuboSoundcloud: ["https://tubo.media"],
   tekstoLibre: ["https://davilarek.github.io/TekstoLibre"],
   skyview: ["https://skyview.social"],
   priviblur: ["https://pb.bloat.cat"],
   nitter: ["https://nitter.privacydev.net"],
   pasted: ["https://pasted.drakeerv.com"],
+  pasty: ["https://pasty.lus.pm"],
   freetar: ["https://freetar.de"],
+  ultimateTab: ["https://ultimate-tab.com"],
   ratAintTieba: ["https://rat.fis.land"],
   shoelace: ["https://shoelace.mint.lgbt"],
   skunkyArt: ["https://skunky.bloat.cat"],
-  ytify: ["https://ytify.netlify.app"],
+  ytify: ["https://ytify.us.kg"],
   nerdsForNerds: ["https://nn.vern.cc"],
+  ducksForDucks: ["https://ducksforducks.private.coffee"],
   koub: ["https://koub.clovius.club"],
+  soundcloak: ["https://soundcloak.fly.dev"],
+  gocook: ["https://cook.adminforge.de"],
+  wikimore: ["https://wikimore.private.coffee"],
 }
 
 async function getDefaults() {
@@ -942,6 +1046,7 @@ async function copyRaw(url) {
  * @param {URL} url
  */
 function isException(url) {
+  if (!options) return false
   if (!options.exceptions) return false
   let exceptions = options.exceptions
   if (exceptions && url) {
@@ -968,12 +1073,11 @@ function isException(url) {
 export default {
   redirect,
   redirectAsync,
-  computeService,
+  computeServiceFrontend,
   reverse,
   initDefaults,
   processUpdate,
   copyRaw,
   switchInstance,
   isException,
-  computeFrontend,
 }
diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js
index e5b8ba46..f360a15b 100644
--- a/src/assets/javascripts/utils.js
+++ b/src/assets/javascripts/utils.js
@@ -31,7 +31,8 @@ function protocolHost(url) {
   if (url.pathname == "/TekstoLibre/" && url.host.endsWith("github.io"))
     return `${url.protocol}//${url.host}${url.pathname.slice(0, -1)}`
 
-  return `${url.protocol}//${url.host}${url.pathname}`
+  const pathname = url.pathname != "/" ? url.pathname : ""
+  return `${url.protocol}//${url.host}${pathname}`
 }
 
 /**
@@ -221,6 +222,22 @@ export function randomInstances(clearnet, n) {
   }
   return instances
 }
+
+async function autoPickInstance(clearnet, url) {
+  if (url) {
+    const i = clearnet.findIndex(instance => url.href.startsWith(instance))
+    if (i >= 0) clearnet.splice(i, 1)
+  }
+  const random = randomInstances(clearnet, 5)
+  const pings = await Promise.all([
+    ...random.map(async instance => {
+      return [instance, await ping(instance)]
+    }),
+  ])
+  pings.sort((a, b) => a[1] - b[1])
+  return pings[0][0]
+}
+
 export function style(options, window) {
   const vars = cssVariables(options, window)
   return `--text: ${vars.text};
@@ -276,4 +293,5 @@ export default {
   convertMapCentre,
   randomInstances,
   style,
+  autoPickInstance,
 }
diff --git a/src/config.json b/src/config.json
index 713345fa..b6338462 100644
--- a/src/config.json
+++ b/src/config.json
@@ -57,10 +57,10 @@
             2,
             3
           ],
-          "name": "PokeTube",
+          "name": "Poke",
           "embeddable": true,
           "instanceList": true,
-          "url": "https://codeberg.org/Ashley/poketube"
+          "url": "https://codeberg.org/ashley/poke"
         },
         "cloudtube": {
           "name": "CloudTube",
@@ -82,7 +82,7 @@
           "name": "Tubo",
           "embeddable": false,
           "instanceList": true,
-          "url": "https://git.migalmoreno.com/tubo/about/",
+          "url": "https://github.com/migalmoreno/tubo",
           "excludeTargets": [
             2,
             3
@@ -122,7 +122,7 @@
         },
         "viewtube": {
           "name": "ViewTube",
-          "embeddable": false,
+          "embeddable": true,
           "instanceList": true,
           "url": "https://github.com/ViewTube/viewtube"
         },
@@ -219,6 +219,25 @@
       "embeddable": true,
       "url": "https://twitter.com"
     },
+    "chatGpt": {
+      "frontends": {
+        "duckDuckGoAiChat": {
+          "name": "DuckDuckGo AI Chat",
+          "instanceList": false,
+          "url": "https://duckduckgo.com/duckduckgo-help-pages/aichat/"
+        }
+      },
+      "targets": ["^https?:\\/{2}chatgpt\\.com"],
+      "name": "ChatGPT",
+      "options": {
+        "enabled": false,
+        "unsupportedUrls": "bypass",
+        "frontend": "duckDuckGoAiChat",
+        "redirectOnlyInIncognito": false
+      },
+      "imageType": "svgMono",
+      "url": "https://chatgpt.com/"
+    },
     "bluesky": {
       "frontends": {
         "skyview": {
@@ -265,11 +284,17 @@
           "instanceList": true,
           "url": "https://github.com/corenting/eddrit",
           "localhost": false
+        },
+        "troddit": {
+          "name": "Troddit",
+          "instanceList": false,
+          "url": "https://github.com/burhan-syed/troddit",
+          "localhost": false
         }
       },
       "targets": [
-        "^https?:\\/{2}(www\\.|old\\.|np\\.|new\\.|amp\\.)?(reddit|reddittorjg6rue252oqsxryoxengawnmo46qy4kyii5wtqnwfj4ooad)\\.(com|onion)(?=\\/u(ser)?\\/|\\/r\\/|\\/search|\\/new|\\/?$)",
-        "^https?:\\/{2}(i|(external-)?preview)\\.redd\\.it"
+        "^https?:\\/{2}(www\\.|old\\.|np\\.|new\\.|amp\\.)?(reddit|reddittorjg6rue252oqsxryoxengawnmo46qy4kyii5wtqnwfj4ooad)\\.(com|onion)(?=\\/u(ser)?\\/|\\/r\\/|\\/search|\\/new|\\/comments|\\/?$)",
+        "^https?:\\/{2}((i|(external-)?preview)\\.)?redd\\.it"
       ],
       "name": "Reddit",
       "options": {
@@ -350,6 +375,12 @@
           "instanceList": true,
           "url": "https://github.com/pablouser1/ProxiTok",
           "localhost": true
+        },
+        "offtiktok": {
+          "name": "Offtiktok",
+          "instanceList": true,
+          "url": "https://github.com/MarsHeer/offtiktok",
+          "localhost": false
         }
       },
       "targets": [
@@ -446,6 +477,11 @@
           "name": "LiteXiv",
           "instanceList": true,
           "url": "https://codeberg.org/Peaksol/LiteXiv"
+        },
+        "vixipy": {
+          "name": "Vixipy",
+          "instanceList": true,
+          "url": "https://codeberg.org/vixipy/Vixipy"
         }
       },
       "targets": [
@@ -516,6 +552,12 @@
           "instanceList": true,
           "url": "https://github.com/Ahwxorg/Binternet",
           "embeddable": true
+        },
+        "painterest": {
+          "name": "Painterest",
+          "instanceList": true,
+          "url": "https://codeberg.org/thirtysix/painterest",
+          "embeddable": true
         }
       },
       "targets": [
@@ -539,7 +581,13 @@
           "name": "Tubo",
           "embeddable": false,
           "instanceList": true,
-          "url": "https://git.migalmoreno.com/tubo/about/"
+          "url": "https://github.com/migalmoreno/tubo"
+        },
+        "soundcloak": {
+          "name": "soundcloak",
+          "embeddable": false,
+          "instanceList": true,
+          "url": "https://git.maid.zone/stuff/soundcloak"
         }
       },
       "targets": [
@@ -640,6 +688,11 @@
           "name": "LibMedium",
           "instanceList": true,
           "url": "https://github.com/realaravinth/libmedium"
+        },
+        "small": {
+          "name": "Small",
+          "instanceList": true,
+          "url": "https://git.private.coffee/PrivateCoffee/small"
         }
       },
       "targets": [
@@ -753,7 +806,7 @@
       },
       "targets": [
         "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?stackoverflow\\.com\\/",
-        "(?!^https?:\\/{2}(api|data|blog)\\.)^https?:\\/{2}([a-zA-Z0-9-]+\\.)stackexchange\\.com\\/",
+        "^https?:\\/{2}((?!(api|data|blog)\\.)[a-zA-Z0-9-]+\\.(meta\\.)?)?stackexchange\\.com\\/",
         "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?(askubuntu\\.com|mathoverflow\\.net|serverfault\\.com|stackapps\\.com|superuser\\.com)\\/"
       ],
       "name": "Stack Overflow",
@@ -940,15 +993,20 @@
     "instructables": {
       "name": "Instructables",
       "frontends": {
-        "indestructables": {
-          "name": "Indestructables",
+        "structables": {
+          "name": "Structables",
           "instanceList": true,
-          "url": "https://indestructables.codeberg.page"
+          "url": "https://github.com/PrivateCoffee/structables"
         },
         "destructables": {
           "name": "Destructables",
           "instanceList": true,
           "url": "https://git.vern.cc/cobra/Destructables"
+        },
+        "indestructables": {
+          "name": "Indestructables",
+          "instanceList": true,
+          "url": "https://indestructables.codeberg.page"
         }
       },
       "targets": [
@@ -957,7 +1015,7 @@
       "options": {
         "enabled": false,
         "unsupportedUrls": "bypass",
-        "frontend": "indestructables",
+        "frontend": "structables",
         "redirectOnlyInIncognito": false
       },
       "imageType": "svg",
@@ -969,6 +1027,11 @@
           "name": "Wikiless",
           "instanceList": true,
           "url": "https://wikiless.org"
+        },
+        "wikimore": {
+          "name": "Wikimore",
+          "instanceList": true,
+          "url": "https://git.private.coffee/privatecoffee/wikimore"
         }
       },
       "targets": [
@@ -1147,7 +1210,8 @@
       },
       "targets": [
         "^https?:\\/{2}maps\\.libredirect\\.invalid",
-        "^https?:\\/{2}(((www|maps)\\.)?(google\\.).*(\\/maps)|maps\\.(google\\.).*)"
+        "^https?:\\/{2}(www\\.)?maps\\.google(\\.[a-z]{2,3}){1,2}\\/",
+        "^https?:\\/{2}(www\\.)?google(\\.[a-z]{2,3}){1,2}\\/maps\\/?"
       ],
       "name": "Maps",
       "options": {
@@ -1215,6 +1279,11 @@
           "name": "Pasted",
           "instanceList": true,
           "url": "https://github.com/Dragynfruit/pasted"
+        },
+        "pasty": {
+          "name": "Pasty",
+          "instanceList": true,
+          "url": "https://github.com/lus/pasty"
         }
       },
       "targets": [
@@ -1236,6 +1305,11 @@
           "name": "Freetar",
           "instanceList": true,
           "url": "https://github.com/kmille/freetar"
+        },
+        "ultimateTab": {
+          "name": "Ultimate Tab",
+          "instanceList": false,
+          "url": "https://github.com/BenoitBellegarde/UltimateTab"
         }
       },
       "targets": [
@@ -1298,7 +1372,7 @@
         "skunkyArt": {
           "name": "SkunkyArt",
           "instanceList": true,
-          "url": "https://git.sr.ht/~nixgoat/shoelace"
+          "url": "https://codeberg.org/skunky/skunkyart"
         }
       },
       "targets": [
@@ -1320,6 +1394,11 @@
           "name": "NerdsforNerds",
           "instanceList": true,
           "url": "https://git.vern.cc/cobra/NerdsforNerds"
+        },
+        "ducksForDucks": {
+          "name": "Ducks for Ducks",
+          "instanceList": true,
+          "url": "https://git.private.coffee/PrivateCoffee/ducksforducks"
         }
       },
       "targets": [
@@ -1355,6 +1434,27 @@
       },
       "imageType": "svg",
       "url": "https://coub.com"
+    },
+    "chefkoch": {
+      "frontends": {
+        "gocook": {
+          "name": "GoCook",
+          "instanceList": true,
+          "url": "https://github.com/NoUmlautsAllowed/gocook"
+        }
+      },
+      "targets": [
+        "^https?:\\/{2}(www\\.)?chefkoch\\.de"
+      ],
+      "name": "Chefkoch",
+      "options": {
+        "enabled": false,
+        "unsupportedUrls": "bypass",
+        "frontend": "gocook",
+        "redirectOnlyInIncognito": false
+      },
+      "imageType": "svg",
+      "url": "https://www.chefkoch.de"
     }
   }
 }
diff --git a/src/manifest.json b/src/manifest.json
index 4de112c0..60e9f6cb 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,7 +1,7 @@
 {
   "name": "__MSG_extensionName__",
   "description": "__MSG_extensionDescription__",
-  "version": "2.9.1",
+  "version": "3.0.2",
   "manifest_version": 2,
   "browser_specific_settings": {
     "gecko": {
diff --git a/src/pages/background/background.js b/src/pages/background/background.js
index 1fcba190..49bae0bf 100644
--- a/src/pages/background/background.js
+++ b/src/pages/background/background.js
@@ -53,6 +53,7 @@ browser.webRequest.onBeforeRequest.addListener(
     let documentUrl
     try {
       if (details.originUrl) originUrl = new URL(details.originUrl)
+      else if (details.initiator) originUrl = new URL(details.initiator)
       if (details.documentUrl) documentUrl = new URL(details.documentUrl)
     } catch {
       return null
@@ -71,6 +72,7 @@ browser.webRequest.onBeforeRequest.addListener(
       (newUrl && newUrl.startsWith("https://no-instance.libredirect.invalid")) ||
       (!newUrl && url.href.startsWith("https://no-instance.libredirect.invalid"))
     ) {
+      if (details.type != "main_frame") return null
       newUrl = newUrl ? new URL(newUrl) : url
       const frontend = newUrl.searchParams.get("frontend")
       const oldUrl = new URL(newUrl.searchParams.get("url"))
@@ -85,17 +87,16 @@ browser.webRequest.onBeforeRequest.addListener(
       return { cancel: true }
     }
 
-    if (!newUrl) {
-      if (url.href.match(/^https?:\/{2}(.*\.)?libredirect\.invalid.*/)) {
-        const params = new URLSearchParams({
-          message: "disabled",
-          url: url.href,
-        })
-        browser.tabs.update({
-          url: browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`),
-        })
-        return { cancel: true }
-      }
+    if (!newUrl && url.href.match(/^https?:\/{2}(.*\.)?libredirect\.invalid.*/)) {
+      if (details.type != "main_frame") return null
+      const params = new URLSearchParams({
+        message: "disabled",
+        url: url.href,
+      })
+      browser.tabs.update({
+        url: browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`),
+      })
+      return { cancel: true }
     }
 
     if (newUrl === "CANCEL") {
@@ -117,29 +118,6 @@ browser.webRequest.onBeforeRequest.addListener(
   ["blocking"]
 )
 
-browser.webRequest.onHeadersReceived.addListener(
-  details => {
-    if (details.statusCode >= 501 || details.statusCode == 429 || details.statusCode == 403) {
-      const url = new URL(details.url)
-      const { service, frontend } = servicesHelper.computeFrontend(url)
-      if (!service) return
-      const params = new URLSearchParams({
-        message: "server_error",
-        code: details.statusCode,
-        url: url.href,
-        frontend: frontend,
-        service: service,
-      })
-      setTimeout(() => {
-        browser.tabs.update({
-          url: browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`),
-        })
-      }, 2000)
-    }
-  },
-  { urls: ["<all_urls>"] }
-)
-
 browser.tabs.onRemoved.addListener(tabId => {
   if (tabIdRedirects[tabId] != undefined) {
     delete tabIdRedirects[tabId]
diff --git a/src/pages/components/Label.svelte b/src/pages/components/Label.svelte
index 39930cd1..d59b9436 100644
--- a/src/pages/components/Label.svelte
+++ b/src/pages/components/Label.svelte
@@ -1,4 +1,4 @@
-<span>
+<span {...$$restProps}>
   <slot></slot>
 </span>
 
diff --git a/src/pages/messages_src/App.svelte b/src/pages/messages_src/App.svelte
index 1c5170dd..82526530 100644
--- a/src/pages/messages_src/App.svelte
+++ b/src/pages/messages_src/App.svelte
@@ -9,7 +9,6 @@
   import { options, config, page } from "./stores"
   import Button from "../components/Button.svelte"
   import AutoPickIcon from "../icons/AutoPickIcon.svelte"
-  import SwitchInstanceIcon from "../icons/SwitchInstanceIcon.svelte"
 
   let _options
   const unsubscribeOptions = options.subscribe(val => {
@@ -49,70 +48,20 @@
   const oldUrl = new URL(params.get("url"))
 
   async function autoPick() {
-    const frontend = params.get("frontend")
     autoPicking = true
+    const frontend = params.get("frontend")
     const redirects = await utils.getList(_options)
-    const instances = utils.randomInstances(redirects[frontend]["clearnet"], 5)
-    const pings = await Promise.all([
-      ...instances.map(async instance => {
-        return [instance, await utils.ping(instance)]
-      }),
-    ])
-    pings.sort((a, b) => a[1] - b[1])
-    _options[frontend].push(pings[0][0])
+    const clearnet = redirects[frontend]["clearnet"]
+    const instance = await utils.autoPickInstance(clearnet)
+    _options[frontend].push(instance)
     options.set(_options)
     autoPicking = false
   }
 
-  async function autoPickInstance() {
-    await autoPick()
-    await redirectUrl()
-  }
-
-  async function enableService() {
-    const service = await servicesHelper.computeService(oldUrl)
-    _options[service].enabled = true
-    options.set(_options)
-    await redirectUrl()
-  }
-
   async function redirectUrl() {
     const newUrl = await servicesHelper.redirectAsync(oldUrl, "main_frame", null, null, false, true)
     browser.tabs.update({ url: newUrl })
   }
-
-  async function switchInstance() {
-    const newUrl = await servicesHelper.switchInstance(oldUrl)
-    browser.tabs.update({ url: newUrl })
-  }
-
-  async function removeInstance() {
-    const service = await servicesHelper.computeService(oldUrl)
-    const frontend = params.get("frontend")
-    const i = _options[frontend].findIndex(instance => oldUrl.href.startsWith(instance))
-    _options[frontend].splice(i, 1)
-    options.set(_options)
-    const newUrl = await servicesHelper.switchInstance(oldUrl, service)
-    browser.tabs.update({ url: newUrl })
-  }
-
-  async function removeAndAutoPickInstance() {
-    const service = await servicesHelper.computeService(oldUrl)
-
-    const frontend = params.get("frontend")
-    const i = _options[frontend].findIndex(instance => oldUrl.href.startsWith(instance))
-    _options[frontend].splice(i, 1)
-    options.set(_options)
-    await autoPick()
-    const newUrl = await servicesHelper.switchInstance(oldUrl, service)
-    browser.tabs.update({ url: newUrl })
-  }
-
-  async function addAutoPickInstance() {
-    await autoPick()
-    const newUrl = await servicesHelper.switchInstance(oldUrl)
-    browser.tabs.update({ url: newUrl })
-  }
 </script>
 
 {#if _options && _config}
@@ -120,42 +69,27 @@
     {#if params.get("message") == "disabled"}
       <div>
         <h1>You disabled redirections for this service</h1>
-        <Button on:click={enableService}>
+        <Button
+          on:click={async () => {
+            const { service } = await servicesHelper.computeServiceFrontend(oldUrl)
+            _options[service].enabled = true
+            options.set(_options)
+            await redirectUrl()
+          }}
+        >
           {browser.i18n.getMessage("enable") || "Enable"}
         </Button>
       </div>
-    {:else if params.get("message") == "server_error"}
-      <!-- https://httpstat.us/403 for testing -->
-      <div>
-        <h1>Your selected instance gave out an error: {params.get("code")}</h1>
-        {#if _options[params.get("frontend")].length > 1}
-          <Button on:click={switchInstance}>
-            <SwitchInstanceIcon class="margin margin_{document.body.dir}" />
-            {browser.i18n.getMessage("switchInstance") || "Switch Instance"}
-          </Button>
-          <Button on:click={removeInstance}>
-            <SwitchInstanceIcon class="margin margin_{document.body.dir}" />
-            {browser.i18n.getMessage("removeInstance") || "Remove Instance"}
-            +
-            {browser.i18n.getMessage("switchInstance") || "Switch Instance"}
-          </Button>
-        {:else}
-          <Button on:click={addAutoPickInstance} disabled={autoPicking}>
-            <AutoPickIcon class="margin margin_{document.body.dir}" />
-            {browser.i18n.getMessage("autoPickInstance") || "Auto Pick Instance"}
-          </Button>
-          <Button on:click={removeAndAutoPickInstance} disabled={autoPicking}>
-            <AutoPickIcon class="margin margin_{document.body.dir}" />
-            {browser.i18n.getMessage("removeInstance") || "Remove Instance"}
-            +
-            {browser.i18n.getMessage("autoPickInstance") || "Auto Pick Instance"}
-          </Button>
-        {/if}
-      </div>
     {:else if params.get("message") == "no_instance"}
       <div>
         <h1>You have no instance selected for this frontend</h1>
-        <Button on:click={autoPickInstance} disabled={autoPicking}>
+        <Button
+          on:click={async () => {
+            await autoPick()
+            await redirectUrl()
+          }}
+          disabled={autoPicking}
+        >
           <AutoPickIcon class="margin margin_{document.body.dir}" />
           {browser.i18n.getMessage("autoPickInstance") || "Auto Pick Instance"}
         </Button>
diff --git a/src/pages/options_src/General/SettingsButtons.svelte b/src/pages/options_src/General/SettingsButtons.svelte
index 4be747fe..1b92ecbc 100644
--- a/src/pages/options_src/General/SettingsButtons.svelte
+++ b/src/pages/options_src/General/SettingsButtons.svelte
@@ -38,7 +38,7 @@
     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.download = `libredirect-settings-v${_options.version}-${(new Date().toISOString().replace(':','-').slice(0,-5))}.json`
     anchor.click()
   }
 
diff --git a/src/pages/options_src/Services/Instances.svelte b/src/pages/options_src/Services/Instances.svelte
index 4e5d1e7d..b37c3904 100644
--- a/src/pages/options_src/Services/Instances.svelte
+++ b/src/pages/options_src/Services/Instances.svelte
@@ -56,30 +56,6 @@
     return true
   }
 
-  async function pingInstances() {
-    pingCache = {}
-    for (const instance of allInstances) {
-      pingCache[instance] = { color: "lightblue", value: "pinging..." }
-      const time = await utils.ping(instance)
-      pingCache[instance] = colorTime(time)
-    }
-  }
-
-  async function autoPickInstance() {
-    const instances = utils.randomInstances(redirects[selectedFrontend]["clearnet"], 5)
-    const myInstancesCache = []
-    for (const instance of instances) {
-      pingCache[instance] = { color: "lightblue", value: "pinging..." }
-      const time = await utils.ping(instance)
-      pingCache[instance] = colorTime(time)
-      myInstancesCache.push([instance, time])
-    }
-    myInstancesCache.sort((a, b) => a[1] - b[1])
-
-    _options[selectedFrontend].push(myInstancesCache[0][0])
-    options.set(_options)
-  }
-
   function colorTime(time) {
     let value
     let color
@@ -113,17 +89,46 @@
       options.set(_options)
     }
   }
+
+  let autoPicking = false
+  let pinging = false
 </script>
 
 {#if serviceConf.frontends[selectedFrontend].instanceList && redirects && blacklist}
   <hr />
 
   <div>
-    <Button on:click={pingInstances}>
+    <Button
+      on:click={async () => {
+        pinging = true
+        pingCache = {}
+        for (const instance of allInstances) {
+          pingCache[instance] = { color: "lightblue", value: "pinging..." }
+          const time = await utils.ping(instance)
+          pingCache[instance] = colorTime(time)
+        }
+        pinging = false
+      }}
+      disabled={pinging}
+    >
       <PingIcon class="margin margin_{document.body.dir}" />
       {browser.i18n.getMessage("pingInstances") || "Ping Instances"}
     </Button>
-    <Button on:click={autoPickInstance}>
+    <Button
+      on:click={async () => {
+        autoPicking = true
+        const clearnet = redirects[selectedFrontend]["clearnet"]
+        for (const instance of _options[selectedFrontend]) {
+          const i = clearnet.indexOf(instance)
+          if (i >= 0) clearnet.splice(i, 1)
+        }
+        const instance = await utils.autoPickInstance(clearnet)
+        _options[selectedFrontend].push(instance)
+        options.set(_options)
+        autoPicking = false
+      }}
+      disabled={autoPicking}
+    >
       <AutoPickIcon class="margin margin_{document.body.dir}" />
       {browser.i18n.getMessage("autoPickInstance") || "Auto Pick Instance"}
     </Button>
@@ -202,20 +207,34 @@
                     <span style="color:{pingCache[instance].color}">{pingCache[instance].value}</span>
                   {/if}
                 </span>
-                <button
-                  class="add"
-                  aria-label="Add instance"
-                  on:click={() => {
-                    if (_options[selectedFrontend]) {
-                      if (!_options[selectedFrontend].includes(instance)) {
+                {#if !_options[selectedFrontend].includes(instance)}
+                  <button
+                    class="add"
+                    aria-label="Add instance"
+                    on:click={() => {
+                      if (_options[selectedFrontend]) {
                         _options[selectedFrontend].push(instance)
                         options.set(_options)
                       }
-                    }
-                  }}
-                >
-                  <AddIcon />
-                </button>
+                    }}
+                  >
+                    <AddIcon />
+                  </button>
+                {:else}
+                  <button
+                    class="add"
+                    aria-label="Remove Instance"
+                    on:click={() => {
+                      const index = _options[selectedFrontend].indexOf(instance)
+                      if (index > -1) {
+                        _options[selectedFrontend].splice(index, 1)
+                        options.set(_options)
+                      }
+                    }}
+                  >
+                    <CloseIcon />
+                  </button>
+                {/if}
               </Row>
               <hr />
             {/each}
diff --git a/src/pages/options_src/Services/Services.svelte b/src/pages/options_src/Services/Services.svelte
index db2977f9..dcc826fa 100644
--- a/src/pages/options_src/Services/Services.svelte
+++ b/src/pages/options_src/Services/Services.svelte
@@ -94,23 +94,23 @@
     />
   </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("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>
 
+  <div style={!serviceOptions.enabled && "pointer-events: none;opacity: 0.4;user-select: none;"}>
     <Row>
       <Label>
         <a href={frontendWebsite} style="text-decoration: underline;" target="_blank" rel="noopener noreferrer">
diff --git a/src/pages/popup_src/Buttons.svelte b/src/pages/popup_src/Buttons.svelte
index ab5682dc..2354fcac 100644
--- a/src/pages/popup_src/Buttons.svelte
+++ b/src/pages/popup_src/Buttons.svelte
@@ -12,6 +12,8 @@
   import { onDestroy } from "svelte"
   import servicesHelper from "../../assets/javascripts/services"
   import Switch from "./components/Switch.svelte"
+  import AutoPickIcon from "../icons/AutoPickIcon.svelte"
+  import utils from "../../assets/javascripts/utils"
 
   let _options
   let _config
@@ -27,16 +29,28 @@
   let switchInstance
   let redirectToOriginal
   let redirect
-  let currentService
+  let frontend
+  let service
   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, null, false, true).then(r => (redirect = r))
-      servicesHelper.computeService(url).then(r => (currentService = r))
+      servicesHelper.computeServiceFrontend(url).then(r => ({ service, frontend } = r))
     }
   })
+
+  let autoPicking = false
+  async function autoPick() {
+    autoPicking = true
+    const redirects = await utils.getList(_options)
+    const clearnet = redirects[frontend]["clearnet"]
+    const instance = await utils.autoPickInstance(clearnet, url)
+    _options[frontend].push(instance)
+    options.set(_options)
+    autoPicking = false
+  }
 </script>
 
 <div class={document.body.dir}>
@@ -46,32 +60,91 @@
       on:click={() => {
         browser.tabs.query({ active: true, currentWindow: true }, tabs => {
           browser.runtime.sendMessage({ message: "redirect", tabId: tabs[0].id }, () => {
-            browser.tabs.update({ url: redirect })
+            browser.tabs.update({ url: redirect }, () => {
+              window.close()
+            })
           })
         })
       }}
     >
-      <Label>{browser.i18n.getMessage("redirect") || "Redirect"}</Label>
+      <Label class="margin">{browser.i18n.getMessage("redirect") || "Redirect"}</Label>
       <RedirectIcon />
     </Row>
   {/if}
 
-  {#if switchInstance}
-    <Row
-      class="interactive"
-      on:click={async () =>
-        browser.tabs.update({ url: switchInstance }, () => {
-          window.close()
-        })}
-    >
-      <Label>{browser.i18n.getMessage("switchInstance") || "Switch Instance"}</Label>
-      <SwitchInstanceIcon />
-    </Row>
+  {#if service && frontend}
+    {#if _options[frontend].length > 1}
+      {#if switchInstance}
+        <Row
+          class="interactive"
+          on:click={async () =>
+            browser.tabs.update({ url: switchInstance }, () => {
+              window.close()
+            })}
+        >
+          <Label class="margin">{browser.i18n.getMessage("switchInstance") || "Switch Instance"}</Label>
+          <SwitchInstanceIcon />
+        </Row>
+      {/if}
+      <Row
+        class="interactive"
+        on:click={async () => {
+          const i = _options[frontend].findIndex(instance => url.href.startsWith(instance))
+          _options[frontend].splice(i, 1)
+          options.set(_options)
+          const newUrl = await servicesHelper.switchInstance(url, service)
+          browser.tabs.update({ url: newUrl }, () => {
+            window.close()
+          })
+        }}
+      >
+        <Label class="margin">
+          {browser.i18n.getMessage("remove") || "Remove"}
+          +
+          {browser.i18n.getMessage("switchInstance") || "Switch Instance"}
+        </Label>
+        <SwitchInstanceIcon />
+      </Row>
+    {:else}
+      <Row
+        class={"interactive " + (autoPicking ? "disabled" : "")}
+        on:click={async () => {
+          const i = _options[frontend].findIndex(instance => url.href.startsWith(instance))
+          _options[frontend].splice(i, 1)
+          options.set(_options)
+          await autoPick()
+          browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) }, () => {
+            window.close()
+          })
+        }}
+      >
+        <Label class="margin">
+          {browser.i18n.getMessage("remove") || "Remove"}
+          +
+          {browser.i18n.getMessage("autoPickInstance") || "Auto Pick Instance"}
+        </Label>
+        <AutoPickIcon />
+      </Row>
+      <Row
+        class={"interactive " + (autoPicking ? "disabled" : "")}
+        on:click={async () => {
+          await autoPick()
+          browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) }, () => {
+            window.close()
+          })
+        }}
+      >
+        <Label class="margin">
+          {browser.i18n.getMessage("autoPickInstance") || "Auto Pick Instance"}
+        </Label>
+        <AutoPickIcon />
+      </Row>
+    {/if}
   {/if}
 
   {#if redirectToOriginal}
     <Row class="interactive" on:click={() => servicesHelper.copyRaw(url)}>
-      <Label>{browser.i18n.getMessage("copyOriginal") || "Copy Original"}</Label>
+      <Label class="margin">{browser.i18n.getMessage("copyOriginal") || "Copy Original"}</Label>
       <CopyIcon />
     </Row>
     <Row
@@ -79,12 +152,14 @@
       on:click={() => {
         browser.tabs.query({ active: true, currentWindow: true }, tabs => {
           browser.runtime.sendMessage({ message: "reverse", tabId: tabs[0].id }, () => {
-            browser.tabs.update({ url: redirectToOriginal })
+            browser.tabs.update({ url: redirectToOriginal }, () => {
+              window.close()
+            })
           })
         })
       }}
     >
-      <Label>{browser.i18n.getMessage("redirectToOriginal" || "Redirect to Original")}</Label>
+      <Label class="margin">{browser.i18n.getMessage("redirectToOriginal" || "Redirect to Original")}</Label>
       <RedirectToOriginalIcon />
     </Row>
   {/if}
@@ -93,13 +168,13 @@
     <hr />
   {/if}
 
-  {#if currentService}
-    <Switch serviceKey={currentService} {url} />
+  {#if service}
+    <Switch serviceKey={service} {url} />
     <hr />
   {/if}
 
   {#each _options.popupServices as serviceKey}
-    {#if currentService !== serviceKey}
+    {#if service !== serviceKey}
       <Switch {serviceKey} {url} />
     {/if}
   {/each}
@@ -113,7 +188,7 @@
         window.close()
       })}
   >
-    <Label>{browser.i18n.getMessage("settings")}</Label>
+    <Label class="margin">{browser.i18n.getMessage("settings")}</Label>
     <SettingsIcon />
   </Row>
 </div>
@@ -130,6 +205,20 @@
     transform: translateY(1px);
   }
 
+  :global(.disabled) {
+    cursor: not-allowed;
+    opacity: 0.5;
+  }
+
+  :global(.disabled:hover) {
+    color: var(--text);
+    cursor: not-allowed;
+  }
+
+  :global(.disabled:active) {
+    transform: none;
+  }
+
   :global(img, svg) {
     margin-right: 5px;
     margin-left: 0;
@@ -142,4 +231,13 @@
     margin-right: 0;
     margin-left: 5px;
   }
+
+  :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/components/Row.svelte b/src/pages/popup_src/components/Row.svelte
index a4d78f07..064942da 100644
--- a/src/pages/popup_src/components/Row.svelte
+++ b/src/pages/popup_src/components/Row.svelte
@@ -1,13 +1,12 @@
 <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
+  <slot></slot>
+</div>
+
+<style>
+  div {
+    justify-content: space-between;
+    display: flex;
+    align-items: center;
+    margin: 10px 0;
+  }
+</style>
diff --git a/src/updates/updates.xml b/src/updates/updates.xml
index ea0d5882..7dd1fabb 100644
--- a/src/updates/updates.xml
+++ b/src/updates/updates.xml
@@ -1,6 +1,6 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
     <app appid='oladmjdebphlnjjcnomfhhbfdldiimaf'>
-        <updatecheck codebase='https://github.com/libredirect/libredirect/releases/download/v2.9.1/libredirect-2.9.1.crx' version='2.9.1' />
+        <updatecheck codebase='https://github.com/libredirect/libredirect/releases/download/v3.0.2/libredirect-3.0.2.crx' version='3.0.2' />
     </app>
 </gupdate>