diff --git a/avia_core/repofrontend.js b/avia_core/repofrontend.js
new file mode 100644
index 0000000..1675eb8
--- /dev/null
+++ b/avia_core/repofrontend.js
@@ -0,0 +1,479 @@
+(function () {
+
+ if (window.__AVIA_OFFICIAL_REPO_LOADED__) return;
+ window.__AVIA_OFFICIAL_REPO_LOADED__ = true;
+
+ const STORAGE_KEY = "avia_plugins";
+ const OFFICIAL_REPO_URL = "https://avalilac.github.io/PluginRepo/pluginrepobackend.js";
+ const THEMES_REGISTRY_URL = "https://avalilac.github.io/PluginRepo/themebackend/themerepobackend.js";
+
+ const getPlugins = () => JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]");
+ const setPlugins = (data) => localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
+
+ let repoContent;
+ let currentRepoData = [];
+ let currentThemeData = [];
+ let searchInput;
+ let activeTab = "plugins"; // "plugins" | "themes"
+
+ document.getElementById("avia-official-repo-btn")?.remove();
+
+ function triggerManagerRefresh() {
+ const panel = document.getElementById("avia-plugins-panel");
+ if (!panel) return;
+ const refreshBtn = Array.from(panel.querySelectorAll("button"))
+ .find(b => b.textContent.trim() === "Refresh");
+ if (refreshBtn) refreshBtn.click();
+ }
+
+ function updateInstallStates() {
+ if (!repoContent) return;
+ const installed = getPlugins().map(p => p.url);
+ repoContent.querySelectorAll("[data-link]").forEach(row => {
+ const link = row.getAttribute("data-link");
+ const btn = row.querySelector("button.install-btn");
+ if (!btn) return;
+ if (installed.includes(link)) {
+ btn.textContent = "Installed";
+ btn.disabled = true;
+ } else {
+ btn.textContent = "Install";
+ btn.disabled = false;
+ }
+ });
+ }
+
+ function renderRepo(data, filter = "") {
+ if (!repoContent) return;
+
+ currentRepoData = data.plugins;
+ repoContent.innerHTML = "";
+
+ const filtered = currentRepoData.filter(p =>
+ (p.name + " " + (p.author || "") + " " + (p.description || ""))
+ .toLowerCase()
+ .includes(filter.toLowerCase())
+ );
+
+ if (filtered.length === 0) {
+ repoContent.innerHTML = `
No plugins found.
`;
+ return;
+ }
+
+ filtered.forEach(repoPlugin => {
+ const row = document.createElement("div");
+ row.style.cssText = "display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;width:100%;min-width:0;";
+ row.setAttribute("data-link", repoPlugin.link);
+
+ const left = document.createElement("div");
+ left.style.cssText = "display:flex;flex-direction:column;flex:1;min-width:0;";
+
+ const title = document.createElement("div");
+ title.textContent = `${repoPlugin.name} — ${repoPlugin.author || "Unknown"}`;
+ title.style.cssText = "font-weight:500;word-break:break-word;";
+
+ const desc = document.createElement("div");
+ desc.textContent = repoPlugin.description || "";
+ desc.style.cssText = "font-size:12px;opacity:0.7;word-break:break-word;";
+
+ left.appendChild(title);
+ left.appendChild(desc);
+
+ const installBtn = document.createElement("button");
+ installBtn.className = "install-btn";
+ Object.assign(installBtn.style, {
+ padding: "6px 10px",
+ borderRadius: "8px",
+ border: "none",
+ cursor: "pointer",
+ background: "rgba(255,255,255,0.08)",
+ color: "#fff",
+ flexShrink: "0"
+ });
+
+ installBtn.onclick = () => {
+ const plugins = getPlugins();
+ if (!plugins.some(p => p.url === repoPlugin.link)) {
+ plugins.push({ name: repoPlugin.name, url: repoPlugin.link, enabled: false });
+ setPlugins(plugins);
+ window.dispatchEvent(new Event("avia-plugin-list-changed"));
+ triggerManagerRefresh();
+ renderRepo({ plugins: currentRepoData }, searchInput.value);
+ }
+ };
+
+ row.appendChild(left);
+ row.appendChild(installBtn);
+ repoContent.appendChild(row);
+ });
+
+ updateInstallStates();
+ }
+
+ function refetchPlugins() {
+ if (!repoContent) return;
+ repoContent.innerHTML = "Loading...";
+
+ function electronFetch() {
+ try {
+ const https = require("https");
+ https.get(OFFICIAL_REPO_URL, res => {
+ let data = "";
+ res.on("data", chunk => data += chunk);
+ res.on("end", () => renderRepo(JSON.parse(data)));
+ }).on("error", () => {
+ repoContent.innerHTML = "Failed to fetch repo.";
+ });
+ } catch {
+ repoContent.innerHTML = "Failed to fetch repo.";
+ }
+ }
+
+ try {
+ fetch(OFFICIAL_REPO_URL)
+ .then(res => res.json())
+ .then(data => renderRepo(data))
+ .catch(() => electronFetch());
+ } catch {
+ electronFetch();
+ }
+ }
+
+ const THEMES_STORAGE_KEY = "avia_themes";
+ const getStoredThemes = () => JSON.parse(localStorage.getItem(THEMES_STORAGE_KEY) || "[]");
+ const setStoredThemes = (data) => localStorage.setItem(THEMES_STORAGE_KEY, JSON.stringify(data));
+
+ function buildThemeCSS(theme, rawCSS) {
+
+ const header = `/* @name ${theme.name}\n @author ${theme.author || "Unknown"}\n @version 1.0\n @description Installed from Trusted Themes Repo\n*/\n`;
+ return header + rawCSS;
+ }
+
+ function installThemeCSS(theme, btn) {
+ btn.disabled = true;
+ btn.textContent = "Installing…";
+
+ fetch(theme.download)
+ .then(r => r.text())
+ .then(rawCSS => {
+ const css = buildThemeCSS(theme, rawCSS);
+ const themes = getStoredThemes();
+
+ const alreadyInstalled = themes.some(t => {
+ const match = t.css.match(/@name\s+(.+)/);
+ return match && match[1].trim() === theme.name;
+ });
+
+ if (alreadyInstalled) {
+ btn.textContent = "Installed";
+
+ return;
+ }
+
+ themes.push({ id: crypto.randomUUID(), css, enabled: true });
+ setStoredThemes(themes);
+
+ document.querySelectorAll(".avia-theme-style").forEach(e => e.remove());
+ getStoredThemes().forEach(t => {
+ if (!t.enabled) return;
+ const style = document.createElement("style");
+ style.className = "avia-theme-style";
+ style.textContent = t.css;
+ document.head.appendChild(style);
+ });
+
+ if (typeof window.__avia_refresh_themes_panel === "function") {
+ window.__avia_refresh_themes_panel();
+ }
+
+ btn.textContent = "Installed";
+
+ })
+ .catch(() => {
+ btn.textContent = "Install CSS";
+ btn.disabled = false;
+ alert("Failed to fetch theme CSS.");
+ });
+ }
+
+ function renderThemes(filter = "") {
+ if (!repoContent) return;
+ repoContent.innerHTML = "";
+
+ const filtered = currentThemeData.filter(t =>
+ (t.name + " " + (t.author || ""))
+ .toLowerCase()
+ .includes(filter.toLowerCase())
+ );
+
+ if (filtered.length === 0) {
+ repoContent.innerHTML = `No themes found.
`;
+ return;
+ }
+
+ filtered.forEach(theme => {
+ const card = document.createElement("div");
+ card.style.cssText = "margin-bottom:14px;background:rgba(255,255,255,0.04);border-radius:12px;overflow:hidden;border:1px solid rgba(255,255,255,0.07);";
+
+ if (theme.preview) {
+ const img = document.createElement("img");
+ img.src = theme.preview;
+ img.alt = theme.name;
+ img.style.cssText = "width:100%;display:block;background:#111;object-fit:contain;";
+ img.onerror = () => img.style.display = "none";
+ card.appendChild(img);
+ }
+
+ const info = document.createElement("div");
+ info.style.cssText = "display:flex;justify-content:space-between;align-items:center;padding:10px 12px;gap:8px;";
+
+ const meta = document.createElement("div");
+ meta.style.cssText = "display:flex;flex-direction:column;min-width:0;flex:1;";
+
+ const name = document.createElement("div");
+ name.textContent = theme.name;
+ name.style.cssText = "font-weight:500;word-break:break-word;";
+
+ const author = document.createElement("div");
+ author.textContent = `by ${theme.author || "Unknown"}`;
+ author.style.cssText = "font-size:12px;opacity:0.6;";
+
+ meta.appendChild(name);
+ meta.appendChild(author);
+
+ const alreadyInstalled = getStoredThemes().some(t => {
+ const match = t.css.match(/@name\s+(.+)/);
+ return match && match[1].trim() === theme.name;
+ });
+
+ const dlBtn = document.createElement("button");
+ dlBtn.textContent = alreadyInstalled ? "Installed" : "Install CSS";
+ dlBtn.disabled = alreadyInstalled;
+ Object.assign(dlBtn.style, {
+ padding: "6px 10px",
+ borderRadius: "8px",
+ border: "none",
+ cursor: alreadyInstalled ? "default" : "pointer",
+ background: "rgba(255,255,255,0.08)",
+ color: "#fff",
+ flexShrink: "0",
+ fontSize: "12px",
+ whiteSpace: "nowrap"
+ });
+ dlBtn.onclick = () => installThemeCSS(theme, dlBtn);
+
+ info.appendChild(meta);
+ info.appendChild(dlBtn);
+ card.appendChild(info);
+ repoContent.appendChild(card);
+ });
+ }
+
+ function refetchThemes() {
+ if (!repoContent) return;
+ repoContent.innerHTML = "Loading themes...";
+ currentThemeData = [];
+
+ fetch(THEMES_REGISTRY_URL)
+ .then(r => r.json())
+ .then(async registry => {
+ const sources = registry.sources || [];
+ const results = await Promise.allSettled(
+ sources.map(s => fetch(s.url).then(r => r.json()))
+ );
+ results.forEach(r => {
+ if (r.status === "fulfilled") {
+ currentThemeData.push(...(r.value.themes || []));
+ }
+ });
+ renderThemes(searchInput.value);
+ })
+ .catch(() => {
+ if (repoContent) repoContent.innerHTML = "Failed to fetch themes.";
+ });
+ }
+
+ function switchTab(tab, tabPluginsBtn, tabThemesBtn) {
+ activeTab = tab;
+ const isPlugins = tab === "plugins";
+
+ tabPluginsBtn.style.background = isPlugins ? "rgba(255,255,255,0.12)" : "transparent";
+ tabPluginsBtn.style.color = isPlugins ? "#fff" : "rgba(255,255,255,0.45)";
+ tabThemesBtn.style.background = !isPlugins ? "rgba(255,255,255,0.12)" : "transparent";
+ tabThemesBtn.style.color = !isPlugins ? "#fff" : "rgba(255,255,255,0.45)";
+
+ searchInput.placeholder = isPlugins
+ ? "Search plugins, authors, or descriptions"
+ : "Search themes or authors";
+ searchInput.value = "";
+
+ if (isPlugins) {
+ if (currentRepoData.length > 0) renderRepo({ plugins: currentRepoData });
+ else refetchPlugins();
+ } else {
+ if (currentThemeData.length > 0) renderThemes();
+ else refetchThemes();
+ }
+ }
+
+ function openWindow() {
+ let panel = document.getElementById("avia-official-repo-window");
+ if (panel) {
+ panel.style.display = panel.style.display === "none" ? "flex" : "none";
+ return;
+ }
+
+ panel = document.createElement("div");
+ panel.id = "avia-official-repo-window";
+ Object.assign(panel.style, {
+ position: "fixed",
+ bottom: "40px",
+ right: "40px",
+ width: "420px",
+ height: "520px",
+ background: "#1e1e1e",
+ color: "#fff",
+ borderRadius: "20px",
+ boxShadow: "0 12px 35px rgba(0,0,0,0.45)",
+ zIndex: 999999,
+ display: "flex",
+ flexDirection: "column",
+ overflow: "hidden",
+ border: "1px solid rgba(255,255,255,0.08)"
+ });
+
+ const header = document.createElement("div");
+ header.textContent = "Plugins & Themes Repo";
+ Object.assign(header.style, {
+ padding: "18px",
+ fontWeight: "600",
+ fontSize: "16px",
+ background: "rgba(255,255,255,0.04)",
+ borderBottom: "1px solid rgba(255,255,255,0.08)",
+ cursor: "move",
+ position: "relative",
+ textAlign: "center",
+ userSelect: "none"
+ });
+
+ let isDragging = false, offsetX = 0, offsetY = 0;
+ header.addEventListener("mousedown", (e) => {
+ isDragging = true;
+ const rect = panel.getBoundingClientRect();
+ offsetX = e.clientX - rect.left;
+ offsetY = e.clientY - rect.top;
+ panel.style.bottom = "auto";
+ panel.style.right = "auto";
+ panel.style.left = rect.left + "px";
+ panel.style.top = rect.top + "px";
+ document.body.style.userSelect = "none";
+ });
+ document.addEventListener("mousemove", (e) => {
+ if (!isDragging) return;
+ panel.style.left = e.clientX - offsetX + "px";
+ panel.style.top = e.clientY - offsetY + "px";
+ });
+ document.addEventListener("mouseup", () => {
+ isDragging = false;
+ document.body.style.userSelect = "";
+ });
+
+ const close = document.createElement("div");
+ close.textContent = "✕";
+ Object.assign(close.style, { position: "absolute", right: "18px", top: "16px", cursor: "pointer" });
+ close.onclick = () => panel.style.display = "none";
+ header.appendChild(close);
+
+ const tabs = document.createElement("div");
+ tabs.style.cssText = "display:flex;gap:6px;padding:10px 12px 0;background:rgba(255,255,255,0.02);border-bottom:1px solid rgba(255,255,255,0.08);";
+
+ const tabStyle = "padding:6px 16px;border-radius:8px 8px 0 0;border:none;cursor:pointer;font-size:13px;font-weight:500;transition:background 0.15s,color 0.15s;font-family:inherit;";
+
+ const tabPluginsBtn = document.createElement("button");
+ tabPluginsBtn.textContent = "Plugins";
+ tabPluginsBtn.style.cssText = tabStyle;
+
+ const tabThemesBtn = document.createElement("button");
+ tabThemesBtn.textContent = "Themes";
+ tabThemesBtn.style.cssText = tabStyle;
+
+ tabPluginsBtn.onclick = () => switchTab("plugins", tabPluginsBtn, tabThemesBtn);
+ tabThemesBtn.onclick = () => switchTab("themes", tabPluginsBtn, tabThemesBtn);
+
+ tabs.appendChild(tabPluginsBtn);
+ tabs.appendChild(tabThemesBtn);
+
+ searchInput = document.createElement("input");
+ searchInput.placeholder = "Search plugins, authors, or descriptions";
+ Object.assign(searchInput.style, {
+ margin: "12px",
+ padding: "8px",
+ borderRadius: "8px",
+ border: "none",
+ outline: "none",
+ background: "rgba(255,255,255,0.06)",
+ color: "#fff"
+ });
+ searchInput.addEventListener("input", () => {
+ if (activeTab === "plugins") renderRepo({ plugins: currentRepoData }, searchInput.value);
+ else renderThemes(searchInput.value);
+ });
+
+ repoContent = document.createElement("div");
+ Object.assign(repoContent.style, {
+ flex: "1",
+ overflowY: "auto",
+ overflowX: "hidden",
+ padding: "0 12px 12px"
+ });
+
+ const container = document.createElement("div");
+ Object.assign(container.style, { flex: "1", display: "flex", flexDirection: "column", overflow: "hidden" });
+ container.appendChild(searchInput);
+ container.appendChild(repoContent);
+
+ panel.appendChild(header);
+ panel.appendChild(tabs);
+ panel.appendChild(container);
+ document.body.appendChild(panel);
+
+ switchTab("plugins", tabPluginsBtn, tabThemesBtn);
+ refetchPlugins();
+ }
+
+ function injectSettingsButton() {
+ if (document.getElementById("avia-official-repo-btn-settings")) return;
+
+ const appearanceBtn = [...document.querySelectorAll("a")]
+ .find(a => a.textContent.trim() === "Appearance");
+ const referenceNode = document.getElementById("stoat-fake-quickcss");
+ if (!appearanceBtn || !referenceNode) return;
+
+ const clone = appearanceBtn.cloneNode(true);
+ clone.id = "avia-official-repo-btn-settings";
+
+ const label = [...clone.querySelectorAll("div")].find(d => d.children.length === 0);
+ if (label) label.textContent = "(Avia) Plugins/Themes Repo";
+
+ const iconSpan = clone.querySelector("span.material-symbols-outlined");
+ if (iconSpan) {
+ iconSpan.textContent = "extension";
+ iconSpan.style.fontVariationSettings = "'FILL' 0,'wght' 400,'GRAD' 0";
+ }
+
+ clone.onclick = openWindow;
+ referenceNode.parentElement.insertBefore(clone, referenceNode.nextSibling);
+ }
+
+ window.addEventListener("avia-plugin-list-changed", () => {
+ if (document.getElementById("avia-official-repo-window")) {
+ updateInstallStates();
+ }
+ });
+
+ new MutationObserver(() => injectSettingsButton())
+ .observe(document.body, { childList: true, subtree: true });
+
+ injectSettingsButton();
+
+})();