diff --git a/frontend/index.html b/frontend/index.html
index 5a7f4d6db21c7194e334243fadfb42241524e331..387fb00d45527d90846ea8e111d48d0d7cfe8a03 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1,38 +1,38 @@
 <!DOCTYPE html>
 <html lang="en">
 
-<head>
-  <meta charset="UTF-8" />
-  <link rel="icon" type="image/svg+xml" href="/favicon.png" />
-  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-  <title>AnythingLLM | Your personal LLM trained on anything</title>
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/favicon.png" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>AnythingLLM | Your personal LLM trained on anything</title>
 
-  <meta name="title" content="AnythingLLM | Your personal LLM trained on anything">
-  <meta name="description" content="AnythingLLM | Your personal LLM trained on anything">
+    <meta name="title" content="AnythingLLM | Your personal LLM trained on anything">
+    <meta name="description" content="AnythingLLM | Your personal LLM trained on anything">
 
-  <!-- Facebook -->
-  <meta property="og:type" content="website">
-  <meta property="og:url" content="https://useanything.com">
-  <meta property="og:title" content="AnythingLLM | Your personal LLM trained on anything">
-  <meta property="og:description" content="AnythingLLM | Your personal LLM trained on anything">
-  <meta property="og:image"
-    content="https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/master/images/promo.png">
+    <!-- Facebook -->
+    <meta property="og:type" content="website">
+    <meta property="og:url" content="https://useanything.com">
+    <meta property="og:title" content="AnythingLLM | Your personal LLM trained on anything">
+    <meta property="og:description" content="AnythingLLM | Your personal LLM trained on anything">
+    <meta property="og:image"
+      content="https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/master/images/promo.png">
 
-  <!-- Twitter -->
-  <meta property="twitter:card" content="summary_large_image">
-  <meta property="twitter:url" content="https://useanything.com">
-  <meta property="twitter:title" content="AnythingLLM | Your personal LLM trained on anything">
-  <meta property="twitter:description" content="AnythingLLM | Your personal LLM trained on anything">
-  <meta property="twitter:image"
-    content="https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/master/images/promo.png">
+    <!-- Twitter -->
+    <meta property="twitter:card" content="summary_large_image">
+    <meta property="twitter:url" content="https://useanything.com">
+    <meta property="twitter:title" content="AnythingLLM | Your personal LLM trained on anything">
+    <meta property="twitter:description" content="AnythingLLM | Your personal LLM trained on anything">
+    <meta property="twitter:image"
+      content="https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/master/images/promo.png">
 
-  <link rel="icon" href="/favicon.png" />
-  <link rel="apple-touch-icon" href="/favicon.png" />
-</head>
+    <link rel="icon" href="/favicon.png" />
+    <link rel="apple-touch-icon" href="/favicon.png" />
+  </head>
 
-<body>
-  <div id="root" class="h-screen"></div>
-  <script type="module" src="/src/main.jsx"></script>
-</body>
+  <body>
+    <div id="root" class="h-screen"></div>
+    <script type="module" src="/src/main.jsx"></script>
+  </body>
 
 </html>
\ No newline at end of file
diff --git a/frontend/package.json b/frontend/package.json
index 3aa23b20cbd6c425251b63adb69d8fcfe56a74dd..a5f754a3c6f36190179705bf16853cbbc9c0061b 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -6,7 +6,7 @@
   "scripts": {
     "start": "vite --open",
     "dev": "NODE_ENV=development vite --debug --host=0.0.0.0",
-    "build": "vite build",
+    "build": "vite build && node scripts/postbuild.js",
     "lint": "yarn prettier --ignore-path ../.prettierignore --write ./src",
     "preview": "vite preview"
   },
diff --git a/frontend/scripts/postbuild.js b/frontend/scripts/postbuild.js
new file mode 100644
index 0000000000000000000000000000000000000000..bcba17bae273a3a36beb87fe5f402b850be2db40
--- /dev/null
+++ b/frontend/scripts/postbuild.js
@@ -0,0 +1,8 @@
+import { renameSync } from 'fs';
+import { fileURLToPath } from 'url';
+import path from 'path';
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+console.log(`Running frontend post build script...`)
+renameSync(path.resolve(__dirname, '../dist/index.html'), path.resolve(__dirname, '../dist/_index.html'));
+console.log(`index.html renamed to _index.html so SSR of the index page can be assumed.`);
\ No newline at end of file
diff --git a/frontend/src/pages/GeneralSettings/Appearance/CustomSiteSettings/index.jsx b/frontend/src/pages/GeneralSettings/Appearance/CustomSiteSettings/index.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..c68d53681fdb07a450b53d1b8292f73a34ea5d0f
--- /dev/null
+++ b/frontend/src/pages/GeneralSettings/Appearance/CustomSiteSettings/index.jsx
@@ -0,0 +1,120 @@
+import { useEffect, useState } from "react";
+import Admin from "@/models/admin";
+import showToast from "@/utils/toast";
+
+export default function CustomSiteSettings() {
+  const [hasChanges, setHasChanges] = useState(false);
+  const [settings, setSettings] = useState({
+    title: null,
+    faviconUrl: null,
+  });
+
+  useEffect(() => {
+    Admin.systemPreferences().then(({ settings }) => {
+      setSettings({
+        title: settings?.meta_page_title,
+        faviconUrl: settings?.meta_page_favicon,
+      });
+    });
+  }, []);
+
+  async function handleSiteSettingUpdate(e) {
+    e.preventDefault();
+    await Admin.updateSystemPreferences({
+      meta_page_title: settings.title ?? null,
+      meta_page_favicon: settings.faviconUrl ?? null,
+    });
+    showToast(
+      "Site preferences updated! They will reflect on page reload.",
+      "success",
+      { clear: true }
+    );
+    setHasChanges(false);
+    return;
+  }
+
+  return (
+    <form
+      className="mb-6"
+      onChange={() => setHasChanges(true)}
+      onSubmit={handleSiteSettingUpdate}
+    >
+      <div className="flex flex-col border-t border-white/30 pt-4 gap-y-2">
+        <div className="flex flex-col gap-y-1">
+          <h2 className="text-base leading-6 font-bold text-white">
+            Custom Site Settings
+          </h2>
+          <p className="text-xs leading-[18px] font-base text-white/60">
+            Change the content of the browser tab for customization and
+            branding.
+          </p>
+        </div>
+
+        <div className="w-fit">
+          <div className="flex flex-col gap-y-1">
+            <h2 className="text-sm leading-6 text-white">Tab Title</h2>
+            <p className="text-xs leading-[18px] font-base text-white/60">
+              Set a custom tab title when the app is open in a browser.
+            </p>
+          </div>
+          <div className="flex items-center gap-x-4">
+            <input
+              name="meta_page_title"
+              type="text"
+              className="border-none bg-zinc-900 mt-3 text-white text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 max-w-[400px] placeholder:text-white/20"
+              placeholder="AnythingLLM | Your personal LLM trained on anything"
+              autoComplete="off"
+              onChange={(e) => {
+                setSettings((prev) => {
+                  return { ...prev, title: e.target.value };
+                });
+              }}
+              value={
+                settings.title ??
+                "AnythingLLM | Your personal LLM trained on anything"
+              }
+            />
+          </div>
+        </div>
+
+        <div className="w-fit">
+          <div className="flex flex-col gap-y-1">
+            <h2 className="text-sm leading-6 text-white">Tab Favicon</h2>
+            <p className="text-xs leading-[18px] font-base text-white/60">
+              Define a url to an image to use for your favicon
+            </p>
+          </div>
+          <div className="flex items-center gap-x-2">
+            <img
+              src={settings.faviconUrl ?? "/favicon.png"}
+              onError={(e) => (e.target.src = "/favicon.png")}
+              className="h-10 w-10 rounded-lg mt-2.5"
+            />
+            <input
+              name="meta_page_favicon"
+              type="url"
+              className="border-none bg-zinc-900 mt-3 text-white text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 max-w-[400px] placeholder:text-white/20"
+              placeholder="url to your image"
+              onChange={(e) => {
+                setSettings((prev) => {
+                  return { ...prev, faviconUrl: e.target.value };
+                });
+              }}
+              autoComplete="off"
+              value={settings.faviconUrl ?? ""}
+            />
+          </div>
+        </div>
+
+        {hasChanges && (
+          <button
+            type="submit"
+            className="border-none transition-all mt-6 w-fit duration-300 border border-slate-200 px-5 py-2.5 rounded-lg text-white text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 focus:ring-gray-800"
+          >
+            Save
+          </button>
+        )}
+      </div>
+    </form>
+  );
+}
diff --git a/frontend/src/pages/GeneralSettings/Appearance/index.jsx b/frontend/src/pages/GeneralSettings/Appearance/index.jsx
index 5894a642c12e9f41990d495cab92d7fa58fe0789..ec3ff2672870c7101d4ab75705803c4fad10fc79 100644
--- a/frontend/src/pages/GeneralSettings/Appearance/index.jsx
+++ b/frontend/src/pages/GeneralSettings/Appearance/index.jsx
@@ -7,6 +7,7 @@ import CustomMessages from "./CustomMessages";
 import { useTranslation } from "react-i18next";
 import CustomAppName from "./CustomAppName";
 import LanguagePreference from "./LanguagePreference";
+import CustomSiteSettings from "./CustomSiteSettings";
 
 export default function Appearance() {
   const { t } = useTranslation();
@@ -34,6 +35,7 @@ export default function Appearance() {
           <CustomMessages />
           <FooterCustomization />
           <SupportEmail />
+          <CustomSiteSettings />
         </div>
       </div>
     </div>
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index ff96bdcd20764399bd48e64badb65b3bee9f2545..b67e9ef7cea9e4cc6238aaafb38a93ee5e8cdf89 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -49,6 +49,15 @@ export default defineConfig({
   },
   build: {
     rollupOptions: {
+      output: {
+        // These settings ensure the primary JS and CSS file references are always index.{js,css}
+        // so we can SSR the index.html as text response from server/index.js without breaking references each build.
+        entryFileNames: 'index.js',
+        assetFileNames: (assetInfo) => {
+          if (assetInfo.name === 'index.css') return `index.css`;
+          return assetInfo.name;
+        },
+      },
       external: [
         // Reduces transformation time by 50% and we don't even use this variant, so we can ignore.
         /@phosphor-icons\/react\/dist\/ssr/
diff --git a/server/endpoints/admin.js b/server/endpoints/admin.js
index d7cab1f584604037b8d2d9091fbcb7113fbf609c..457d7567b95da0fe1536bd7e09deec7bbac5a9af 100644
--- a/server/endpoints/admin.js
+++ b/server/endpoints/admin.js
@@ -356,6 +356,14 @@ function adminEndpoints(app) {
             (await SystemSettings.get({ label: "custom_app_name" }))?.value ||
             null,
           feature_flags: (await SystemSettings.getFeatureFlags()) || {},
+          meta_page_title: await SystemSettings.getValueOrFallback(
+            { label: "meta_page_title" },
+            null
+          ),
+          meta_page_favicon: await SystemSettings.getValueOrFallback(
+            { label: "meta_page_favicon" },
+            null
+          ),
         };
         response.status(200).json({ settings });
       } catch (e) {
diff --git a/server/index.js b/server/index.js
index 141fe665c8d0cfafa834f2260be439f9e9a0889e..c2f584443cc5de50b158c83b86e3e6828861c38b 100644
--- a/server/index.js
+++ b/server/index.js
@@ -63,6 +63,9 @@ developerEndpoints(app, apiRouter);
 embeddedEndpoints(apiRouter);
 
 if (process.env.NODE_ENV !== "development") {
+  const { MetaGenerator } = require("./utils/boot/MetaGenerator");
+  const IndexPage = new MetaGenerator();
+
   app.use(
     express.static(path.resolve(__dirname, "public"), {
       extensions: ["js"],
@@ -75,7 +78,8 @@ if (process.env.NODE_ENV !== "development") {
   );
 
   app.use("/", function (_, response) {
-    response.sendFile(path.join(__dirname, "public", "index.html"));
+    IndexPage.generate(response);
+    return;
   });
 
   app.get("/robots.txt", function (_, response) {
diff --git a/server/models/systemSettings.js b/server/models/systemSettings.js
index ea1dd01e43489ffdc08b4907a76583e5b17623a9..70ed526e781b53d11b5ad1a3a63b2d4fe0105514 100644
--- a/server/models/systemSettings.js
+++ b/server/models/systemSettings.js
@@ -6,6 +6,7 @@ const { default: slugify } = require("slugify");
 const { isValidUrl, safeJsonParse } = require("../utils/http");
 const prisma = require("../utils/prisma");
 const { v4 } = require("uuid");
+const { MetaGenerator } = require("../utils/boot/MetaGenerator");
 
 function isNullOrNaN(value) {
   if (value === null) return true;
@@ -21,6 +22,7 @@ const SystemSettings = {
     "telemetry_id",
     "footer_data",
     "support_email",
+
     "text_splitter_chunk_size",
     "text_splitter_chunk_overlap",
     "agent_search_provider",
@@ -28,6 +30,10 @@ const SystemSettings = {
     "agent_sql_connections",
     "custom_app_name",
 
+    // Meta page customization
+    "meta_page_title",
+    "meta_page_favicon",
+
     // beta feature flags
     "experimental_live_file_sync",
   ],
@@ -122,6 +128,27 @@ const SystemSettings = {
       if (!["enabled", "disabled"].includes(update)) return "disabled";
       return String(update);
     },
+    meta_page_title: (newTitle) => {
+      try {
+        if (typeof newTitle !== "string" || !newTitle) return null;
+        return String(newTitle);
+      } catch {
+        return null;
+      } finally {
+        new MetaGenerator().clearConfig();
+      }
+    },
+    meta_page_favicon: (faviconUrl) => {
+      if (!faviconUrl) return null;
+      try {
+        const url = new URL(faviconUrl);
+        return url.toString();
+      } catch {
+        return null;
+      } finally {
+        new MetaGenerator().clearConfig();
+      }
+    },
   },
   currentSettings: async function () {
     const { hasVectorCachedFiles } = require("../utils/files");
diff --git a/server/utils/boot/MetaGenerator.js b/server/utils/boot/MetaGenerator.js
new file mode 100644
index 0000000000000000000000000000000000000000..ebf7eab504d33ccac0e45ec16b24479d4ea7bffe
--- /dev/null
+++ b/server/utils/boot/MetaGenerator.js
@@ -0,0 +1,233 @@
+/**
+ * @typedef MetaTagDefinition
+ * @property {('link'|'meta')} tag - the type of meta tag element
+ * @property {{string:string}|null} props - the inner key/values of a meta tag
+ * @property {string|null} content - Text content to be injected between tags. If null self-closing.
+ */
+
+/**
+ * This class serves the default index.html page that is not present when built in production.
+ * and therefore this class should not be called when in development mode since it is unused.
+ * All this class does is basically emulate SSR for the meta-tag generation of the root index page.
+ * Since we are an SPA, we can just render the primary page and the known entrypoints for the index.{js,css}
+ * we can always start at the right place and dynamically load in lazy-loaded as we typically normally would
+ * and we dont have any of the overhead that would normally come with having the rewrite the whole app in next or something.
+ * Lastly, this class is singleton, so once instantiate the same refernce is shared for as long as the server is alive.
+ * the main function is `.generate()` which will return the index HTML. These settings are stored in the #customConfig
+ * static property and will not be reloaded until the page is loaded AND #customConfig is explicity null. So anytime a setting
+ * for meta-props is updated you should get this singleton class and call `.clearConfig` so the next page load will show the new props.
+ */
+class MetaGenerator {
+  name = "MetaGenerator";
+
+  /** @type {MetaGenerator|null} */
+  static _instance = null;
+
+  /** @type {MetaTagDefinition[]|null} */
+  #customConfig = null;
+
+  constructor() {
+    if (MetaGenerator._instance) return MetaGenerator._instance;
+    MetaGenerator._instance = this;
+  }
+
+  #log(text, ...args) {
+    console.log(`\x1b[36m[${this.name}]\x1b[0m ${text}`, ...args);
+  }
+
+  #defaultMeta() {
+    return [
+      {
+        tag: "link",
+        props: { type: "image/svg+xml", href: "/favicon.png" },
+        content: null,
+      },
+      {
+        tag: "title",
+        props: null,
+        content: "AnythingLLM | Your personal LLM trained on anything",
+      },
+
+      {
+        tag: "meta",
+        props: {
+          name: "title",
+          content: "AnythingLLM | Your personal LLM trained on anything",
+        },
+      },
+      {
+        tag: "meta",
+        props: {
+          description: "title",
+          content: "AnythingLLM | Your personal LLM trained on anything",
+        },
+      },
+
+      // <!-- Facebook -->
+      { tag: "meta", props: { property: "og:type", content: "website" } },
+      {
+        tag: "meta",
+        props: { property: "og:url", content: "https://useanything.com" },
+      },
+      {
+        tag: "meta",
+        props: {
+          property: "og:title",
+          content: "AnythingLLM | Your personal LLM trained on anything",
+        },
+      },
+      {
+        tag: "meta",
+        props: {
+          property: "og:description",
+          content: "AnythingLLM | Your personal LLM trained on anything",
+        },
+      },
+      {
+        tag: "meta",
+        props: {
+          property: "og:image",
+          content:
+            "https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/master/images/promo.png",
+        },
+      },
+
+      // <!-- Twitter -->
+      {
+        tag: "meta",
+        props: { property: "twitter:card", content: "summary_large_image" },
+      },
+      {
+        tag: "meta",
+        props: { property: "twitter:url", content: "https://useanything.com" },
+      },
+      {
+        tag: "meta",
+        props: {
+          property: "twitter:title",
+          content: "AnythingLLM | Your personal LLM trained on anything",
+        },
+      },
+      {
+        tag: "meta",
+        props: {
+          property: "twitter:description",
+          content: "AnythingLLM | Your personal LLM trained on anything",
+        },
+      },
+      {
+        tag: "meta",
+        props: {
+          property: "twitter:image",
+          content:
+            "https://raw.githubusercontent.com/Mintplex-Labs/anything-llm/master/images/promo.png",
+        },
+      },
+
+      { tag: "link", props: { rel: "icon", href: "/favicon.png" } },
+      { tag: "link", props: { rel: "apple-touch-icon", href: "/favicon.png" } },
+    ];
+  }
+
+  /**
+   * Assembles Meta tags as one large string
+   * @param {MetaTagDefinition[]} tagArray
+   * @returns {string}
+   */
+  #assembleMeta() {
+    const output = [];
+    for (const tag of this.#customConfig) {
+      let htmlString;
+      htmlString = `<${tag.tag} `;
+
+      if (tag.props !== null) {
+        for (const [key, value] of Object.entries(tag.props))
+          htmlString += `${key}="${value}" `;
+      }
+
+      if (tag.content) {
+        htmlString += `>${tag.content}</${tag.tag}>`;
+      } else {
+        htmlString += `>`;
+      }
+      output.push(htmlString);
+    }
+    return output.join("\n");
+  }
+
+  #validUrl(faviconUrl = null) {
+    if (faviconUrl === null) return "/favicon.png";
+    try {
+      const url = new URL(faviconUrl);
+      return url.toString();
+    } catch {
+      return "/favicon.png";
+    }
+  }
+
+  async #fetchConfg() {
+    this.#log(`fetching custome meta tag settings...`);
+    const { SystemSettings } = require("../../models/systemSettings");
+    const customTitle = await SystemSettings.getValueOrFallback(
+      { label: "meta_page_title" },
+      null
+    );
+    const faviconURL = await SystemSettings.getValueOrFallback(
+      { label: "meta_page_favicon" },
+      null
+    );
+
+    // If nothing defined - assume defaults.
+    if (customTitle === null && faviconURL === null) {
+      this.#customConfig = this.#defaultMeta();
+    } else {
+      this.#customConfig = [
+        {
+          tag: "link",
+          props: { rel: "icon", href: this.#validUrl(faviconURL) },
+        },
+        {
+          tag: "title",
+          props: null,
+          content:
+            customTitle ??
+            "AnythingLLM | Your personal LLM trained on anything",
+        },
+      ];
+    }
+
+    return this.#customConfig;
+  }
+
+  /**
+   * Clears the current config so it can be refetched on the server for next render.
+   */
+  clearConfig() {
+    this.#customConfig = null;
+  }
+
+  /**
+   *
+   * @param {import('express').Response} response
+   * @param {number} code
+   */
+  async generate(response, code = 200) {
+    if (this.#customConfig === null) await this.#fetchConfg();
+    response.status(code).send(`
+       <!DOCTYPE html>
+        <html lang="en">
+          <head>
+            <meta charset="UTF-8" />
+            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+            ${this.#assembleMeta()}
+            <script type="module" crossorigin src="/index.js"></script>
+            <link rel="stylesheet" href="/index.css">
+          </head>
+          <body>
+            <div id="root" class="h-screen"></div>
+          </body>
+        </html>`);
+  }
+}
+
+module.exports.MetaGenerator = MetaGenerator;