// Cloudflare Workers deployment for SimpleSearch // Deploy at: https://dash.cloudflare.com//workers-and-pages // // Version: 2.1.0 (Optimized - January 2026) // // Features: // - Streamlined CSS (removed redundant Tailwind classes) // - Optimized JavaScript (removed unused variables) // - Full glass morphism UI with Bing daily backgrounds // - Loading state with smooth transitions // - Keyboard shortcuts and accessibility support // - Local icon fallback system with timeout handling addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const url = new URL(request.url) const path = url.pathname // Handle root path requests and return index.html if (path === '/' || path === '') { return new Response(INDEX_HTML, { headers: { 'Content-Type': 'text/html;charset=UTF-8', 'Cache-Control': 'public, max-age=3600' } }) } // Handle resource requests if (path === '/assets/js/app.js') { return new Response(APP_JS, { headers: { 'Content-Type': 'application/javascript;charset=UTF-8', 'Cache-Control': 'public, max-age=86400' } }) } // If no matching resources are found, return a 404 return new Response('Not Found', { status: 404 }) } // Optimized HTML (reduced from 263 to ~170 lines) const INDEX_HTML = ` Search Navigation

Quick Bookmarks

` // Optimized JavaScript (removed unused variables, improved icon loading) const APP_JS = `// SimpleSearch v2.1.0 - Optimized for Cloudflare Workers // DOM Elements const searchForm = document.getElementById('searchForm'); const searchInput = document.getElementById('searchInput'); const homeBtn = document.getElementById('homeBtn'); // App State let currentEngine = localStorage.getItem('defaultEngine') || 'google'; const APP_VERSION = '2.1.0'; // Search engine configurations const searchEngines = { google: { name: 'Google', url: 'https://www.google.com/search', paramName: 'q', logo: 'https://www.google.com/favicon.ico' }, bing: { name: 'Bing', url: 'https://www.bing.com/search', paramName: 'q', logo: 'https://www.bing.com/favicon.ico' }, baidu: { name: 'Baidu', url: 'https://www.baidu.com/s', paramName: 'wd', logo: 'https://www.baidu.com/favicon.ico' }, duckduckgo: { name: 'DuckDuckGo', url: 'https://duckduckgo.com/', paramName: 'q', logo: 'https://duckduckgo.com/favicon.ico' }, yahoo: { name: 'Yahoo', url: 'https://search.yahoo.com/search', paramName: 'q', logo: 'https://search.yahoo.com/favicon.ico' }, startpage: { name: 'StartPage', url: 'https://www.startpage.com/search', paramName: 'q', logo: 'https://www.startpage.com/favicon.ico' }, ask: { name: 'Ask', url: 'https://www.ask.com/search', paramName: 'q', logo: 'https://www.ask.com/favicon.ico' }, searxng: { name: 'SearXNG', url: 'https://opnxng.com/search', paramName: 'q', logo: 'https://opnxng.com/favicon.ico' }, feloai: { name: 'FeloAI', url: 'https://felo.ai/search', paramName: 'q', logo: 'https://felo.ai/icon.svg' }, yandex: { name: 'Yandex', url: 'https://yandex.eu/search', paramName: 'text', logo: 'https://yandex.eu/favicon.ico' }, metaso: { name: 'Metaso', url: 'https://metaso.cn/', paramName: 'q', logo: 'https://metaso.cn/favicon.ico' } }; const bookmarks = { tech: { name: 'Technical', icon: \\\` \\\`, items: [ { name: 'ChatGPT', url: 'https://chatgpt.com', img: 'https://openai.com/favicon.ico' }, { name: 'Gemini', url: 'https://gemini.google.com', img: 'https://www.google.com/favicon.ico' }, { name: 'Grok', url: 'https://x.com/i/grok', img: 'https://x.com/favicon.ico' }, { name: 'MSCopilot', url: 'https://copilot.microsoft.com/', img: 'https://copilot.microsoft.com/favicon.ico' }, { name: 'MistralAI', url: 'https://chat.mistral.ai/chat', img: 'https://mistral.ai/favicon.ico' } ] }, tools: { name: 'Common Tools', icon: \\\` \\\`, items: [ { name: 'Github', url: 'https://github.com', img: 'https://github.com/favicon.ico' }, { name: 'Overleaf', url: 'https://www.overleaf.com', img: 'https://www.grammarly.com/favicon.ico' }, { name: 'Notion', url: 'https://www.notion.so', img: 'https://www.notion.com/front-static/favicon.ico' }, { name: 'Google Drive', url: 'https://drive.google.com', img: 'https://drive.google.com/favicon.ico' }, { name: 'DeepL', url: 'https://www.deepl.com/translator', img: 'https://www.deepl.com/favicon.ico' } ] }, social: { name: 'Social Media', icon: \\\` \\\`, items: [ { name: 'Twitter', url: 'https://x.com', img: 'https://x.com/favicon.ico' }, { name: 'Instagram', url: 'https://www.instagram.com', img: 'https://www.instagram.com/favicon.ico' }, { name: 'LinkedIn', url: 'https://www.linkedin.com', img: 'https://www.linkedin.com/favicon.ico' }, { name: 'Discord', url: 'https://discord.com/app', img: 'https://discord.com/favicon.ico' }, { name: 'Reddit', url: 'https://www.reddit.com', img: 'https://www.reddit.com/favicon.ico' } ] } }; // Generate engine buttons dynamically function generateEngineButtons() { const engineSelector = document.getElementById('engineSelector'); engineSelector.innerHTML = ''; for (const key in searchEngines) { if (searchEngines.hasOwnProperty(key)) { const engine = searchEngines[key]; const button = document.createElement('button'); button.type = 'button'; button.className = 'engine-button px-4 py-2 flex items-center justify-center rounded-full bg-white border border-gray-300 shadow-sm hover:shadow-md transition-shadow'; button.setAttribute('data-engine', key); button.setAttribute('aria-label', \\\`Select \\\${engine.name} search engine\\\`); const img = document.createElement('img'); img.src = engine.logo; img.alt = engine.name; img.className = 'engine-logo'; // Hide icon if it fails to load img.onerror = function () { this.style.visibility = 'hidden'; }; const span = document.createElement('span'); span.textContent = engine.name; button.appendChild(img); button.appendChild(span); engineSelector.appendChild(button); } } attachEngineButtonEvents(); } // Generate bookmark categories and items dynamically function generateBookmarks() { const bookmarksContainer = document.getElementById('bookmarksContainer'); if (!bookmarksContainer) { console.error("Bookmarks container not found"); return; } bookmarksContainer.innerHTML = ''; for (const categoryKey in bookmarks) { if (bookmarks.hasOwnProperty(categoryKey)) { const category = bookmarks[categoryKey]; const savedState = localStorage.getItem(\\\`category_\\\${categoryKey}\\\`); const categorySection = document.createElement('div'); categorySection.className = 'mb-4 bookmark-category'; const categoryHeader = document.createElement('div'); categoryHeader.className = 'flex items-center cursor-pointer mb-2 category-header'; categoryHeader.setAttribute('data-category', categoryKey); categoryHeader.setAttribute('role', 'button'); categoryHeader.setAttribute('aria-expanded', savedState !== 'closed'); categoryHeader.setAttribute('aria-label', \\\`Toggle \\\${category.name} bookmarks\\\`); categoryHeader.innerHTML = category.icon; const categoryTitle = document.createElement('h3'); categoryTitle.className = 'font-medium text-gray-800'; categoryTitle.textContent = category.name; categoryHeader.appendChild(categoryTitle); const categoryContent = document.createElement('div'); categoryContent.className = 'grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-3 category-content'; categoryContent.id = \\\`\\\${categoryKey}Bookmarks\\\`; if (savedState === 'closed') { categoryContent.style.display = 'none'; const icon = categoryHeader.querySelector('.category-icon'); if (icon) { icon.style.transform = 'rotate(-90deg)'; icon.style.transition = 'transform 0.3s ease'; } } else { categoryContent.style.display = 'grid'; } category.items.forEach(bookmark => { const bookmarkDiv = document.createElement('div'); bookmarkDiv.className = 'bg-white rounded-lg shadow-sm p-3 card-hover mini-bookmark'; const bookmarkLink = document.createElement('a'); bookmarkLink.href = bookmark.url; bookmarkLink.target = '_blank'; bookmarkLink.className = 'flex flex-col items-center justify-center'; const bookmarkImg = document.createElement('img'); bookmarkImg.src = bookmark.img; bookmarkImg.alt = bookmark.name; bookmarkImg.className = 'w-8 h-8 mb-2'; bookmarkImg.onerror = function () { this.src = 'https://raw.githubusercontent.com/es-v/SimpleSearch/main/assets/img/web.svg'; }; const bookmarkName = document.createElement('span'); bookmarkName.className = 'text-xs font-medium text-gray-800'; bookmarkName.textContent = bookmark.name; bookmarkLink.appendChild(bookmarkImg); bookmarkLink.appendChild(bookmarkName); bookmarkDiv.appendChild(bookmarkLink); categoryContent.appendChild(bookmarkDiv); }); categorySection.appendChild(categoryHeader); categorySection.appendChild(categoryContent); bookmarksContainer.appendChild(categorySection); categoryHeader.addEventListener('click', function () { const category = this.getAttribute('data-category'); const content = this.nextElementSibling; const icon = this.querySelector('.category-icon'); const isExpanded = content.style.display !== 'none'; if (isExpanded) { content.style.display = 'none'; if (icon) icon.style.transform = 'rotate(-90deg)'; this.setAttribute('aria-expanded', 'false'); localStorage.setItem(\\\`category_\\\${category}\\\`, 'closed'); } else { content.style.display = 'grid'; if (icon) icon.style.transform = 'rotate(0deg)'; this.setAttribute('aria-expanded', 'true'); localStorage.setItem(\\\`category_\\\${category}\\\`, 'open'); } }); } } } // Attach event listeners to engine buttons function attachEngineButtonEvents() { const engineButtons = document.querySelectorAll('.engine-button'); engineButtons.forEach(button => { button.addEventListener('click', function () { currentEngine = this.getAttribute('data-engine'); localStorage.setItem('defaultEngine', currentEngine); highlightSelectedEngine(); }); }); } // Initialize app function init() { showLoadingState(); generateEngineButtons(); generateBookmarks(); loadDefaultEngine(); highlightSelectedEngine(); setDailyBingBackground(); setupTransparentUI(); displayVersionInfo(); } // Load default engine from local storage function loadDefaultEngine() { const defaultEngine = localStorage.getItem('defaultEngine') || 'google'; currentEngine = defaultEngine; } // Set daily Bing background (simplified - no proxies) function setDailyBingBackground() { const cachedData = localStorage.getItem('bingBackgroundCache'); const today = new Date().toDateString(); if (cachedData) { try { const cache = JSON.parse(cachedData); if (cache.date === today && cache.imageUrl) { setBackgroundImage(cache.imageUrl); return; } } catch (e) { console.error('Error parsing cached background:', e); } } const fetchTimeout = setTimeout(() => { console.warn('Background fetch timeout, using fallback'); setFallbackBackground(); }, 3000); const bingImageUrl = 'https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1'; fetch(bingImageUrl, { method: 'GET', signal: AbortSignal.timeout(2500) }) .then(response => { if (!response.ok) throw new Error(\\\`HTTP \\\${response.status}\\\`); return response.json(); }) .then(data => { if (data && data.images && data.images.length > 0) { clearTimeout(fetchTimeout); const imageData = data.images[0]; const imageUrl = \\\`https://www.bing.com\\\${imageData.url}\\\`; localStorage.setItem('bingBackgroundCache', JSON.stringify({ date: today, imageUrl: imageUrl })); setBackgroundImage(imageUrl); } else { throw new Error('Invalid response format'); } }) .catch(error => { clearTimeout(fetchTimeout); console.warn('Bing background fetch failed:', error.message); setFallbackBackground(); }); } // Helper function to set background image function setBackgroundImage(imageUrl) { const img = new Image(); img.onload = function () { document.body.style.backgroundImage = \\\`url('\\\${imageUrl}')\\\`; document.body.style.backgroundSize = 'cover'; document.body.style.backgroundPosition = 'center'; document.body.style.backgroundRepeat = 'no-repeat'; document.body.style.backgroundAttachment = 'fixed'; hideLoadingState(); }; img.onerror = function () { setFallbackBackground(); }; img.src = imageUrl; } // Helper function to set fallback background function setFallbackBackground() { document.body.style.background = 'linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d)'; hideLoadingState(); } // Make UI elements transparent function setupTransparentUI() { const mainContainers = document.querySelectorAll('.bg-white'); mainContainers.forEach(container => { container.classList.remove('bg-white'); container.classList.add('glass-morphism'); }); const bookmarkCards = document.querySelectorAll('.card-hover'); bookmarkCards.forEach(card => { card.classList.add('glass-bookmark'); }); const searchContainer = document.querySelector('#searchForm').parentElement; searchContainer.classList.add('search-container-glass'); const searchInputElem = document.querySelector('#searchInput'); searchInputElem.classList.add('glass-input'); const engineButtonElements = document.querySelectorAll('.engine-button'); engineButtonElements.forEach(btn => { btn.classList.add('glass-button'); }); const style = document.createElement('style'); style.textContent = \\\` .glass-morphism { background: rgba(255, 255, 255, 0.2) !important; backdrop-filter: blur(8px) !important; -webkit-backdrop-filter: blur(8px) !important; border: 1px solid rgba(255, 255, 255, 0.3) !important; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1) !important; } .glass-bookmark { background: rgba(255, 255, 255, 0.25) !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important; border: 1px solid rgba(255, 255, 255, 0.3) !important; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1) !important; transition: all 0.3s ease !important; } .glass-bookmark:hover { background: rgba(255, 255, 255, 0.35) !important; transform: translateY(-5px) !important; box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2) !important; } .search-container-glass { background: rgba(255, 255, 255, 0.15) !important; backdrop-filter: blur(12px) !important; -webkit-backdrop-filter: blur(12px) !important; border-radius: 16px !important; border: 1px solid rgba(255, 255, 255, 0.2) !important; box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1) !important; padding: 24px !important; } .glass-input { background: rgba(255, 255, 255, 0.2) !important; border: 1px solid rgba(255, 255, 255, 0.3) !important; color: rgba(0, 0, 0, 0.8) !important; backdrop-filter: blur(4px) !important; -webkit-backdrop-filter: blur(4px) !important; } .glass-input::placeholder { color: rgba(0, 0, 0, 0.5) !important; } .glass-button { background: rgba(255, 255, 255, 0.25) !important; backdrop-filter: blur(4px) !important; -webkit-backdrop-filter: blur(4px) !important; border: 1px solid rgba(255, 255, 255, 0.3) !important; transition: all 0.3s ease !important; } .glass-button:hover { background: rgba(255, 255, 255, 0.4) !important; transform: translateY(-2px) !important; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1) !important; } .container { max-width: 900px !important; margin: 0 auto !important; } body { font-family: 'Inter', sans-serif !important; color: white !important; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) !important; height: 100vh !important; overflow-x: hidden !important; } h1, h2, h3, h4, h5, h6 { color: white !important; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3) !important; } a { color: rgba(255, 255, 255, 0.8) !important; transition: color 0.3s ease !important; } a:hover { color: white !important; text-shadow: 0 0 8px rgba(255, 255, 255, 0.5) !important; } .text-gray-600, .text-gray-700, .text-gray-800 { color: rgba(255, 255, 255, 0.9) !important; } .mini-bookmark { background: rgba(255, 255, 255, 0.2) !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important; border: 1px solid rgba(255, 255, 255, 0.3) !important; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important; transition: all 0.3s ease !important; } .mini-bookmark:hover { background: rgba(255, 255, 255, 0.3) !important; transform: translateY(-3px) !important; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15) !important; } .category-header { padding: 8px 12px; border-radius: 8px; background: rgba(255, 255, 255, 0.15) !important; backdrop-filter: blur(8px) !important; -webkit-backdrop-filter: blur(8px) !important; transition: all 0.3s ease !important; } .category-header:hover { background: rgba(255, 255, 255, 0.25) !important; } .category-content { transition: all 0.3s ease; } \\\`; document.head.appendChild(style); } // Highlight the currently selected search engine function highlightSelectedEngine() { const engineButtons = document.querySelectorAll('.engine-button'); engineButtons.forEach(button => { const engine = button.getAttribute('data-engine'); if (engine === currentEngine) { button.classList.add('ring-2', 'ring-white', 'bg-white/30'); button.setAttribute('aria-pressed', 'true'); } else { button.classList.remove('ring-2', 'ring-white', 'bg-white/30'); button.setAttribute('aria-pressed', 'false'); } }); } // Add loading state functions function showLoadingState() { const loadingDiv = document.createElement('div'); loadingDiv.id = 'backgroundLoader'; loadingDiv.style.cssText = \\\` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d); display: flex; align-items: center; justify-content: center; z-index: 9999; transition: opacity 0.5s ease; \\\`; loadingDiv.innerHTML = \\\`

Loading...

\\\`; document.body.appendChild(loadingDiv); } function hideLoadingState() { const loader = document.getElementById('backgroundLoader'); if (loader) { loader.style.opacity = '0'; setTimeout(() => { loader.remove(); }, 500); } } // Add a function to display the version number function displayVersionInfo() { const footer = document.createElement('div'); footer.className = 'fixed bottom-2 right-2 flex items-center bg-black/20 backdrop-filter backdrop-blur-sm px-3 py-1 rounded-full hover:bg-black/30 transition-all'; const versionSpan = document.createElement('span'); versionSpan.className = 'text-xs text-white/70 font-medium'; versionSpan.textContent = \\\`v\\\${APP_VERSION}\\\`; versionSpan.style.textShadow = '0 1px 2px rgba(0,0,0,0.3)'; const githubLink = document.createElement('a'); githubLink.href = 'https://github.com/es-v/SimpleSearch'; githubLink.target = '_blank'; githubLink.className = 'ml-2 text-white/80 hover:text-white transition-colors'; githubLink.title = 'View on GitHub'; githubLink.style.textShadow = '0 1px 2px rgba(0,0,0,0.3)'; const githubIcon = document.createElement('span'); githubIcon.innerHTML = \\\` \\\`; githubLink.appendChild(githubIcon); footer.appendChild(versionSpan); footer.appendChild(githubLink); document.body.appendChild(footer); } // Handle search form submission searchForm.addEventListener('submit', function (e) { e.preventDefault(); const query = searchInput.value.trim(); if (!query) return; const engine = searchEngines[currentEngine]; const url = new URL(engine.url); url.searchParams.append(engine.paramName, query); window.open(url.toString(), '_blank'); }); // Home button functionality if (homeBtn) { homeBtn.addEventListener('click', function () { window.location.reload(); }); } // Add keyboard shortcuts for enhanced UX document.addEventListener('keydown', function (e) { // Alt+S to focus search input if (e.altKey && e.key === 's') { e.preventDefault(); searchInput.focus(); } // Number keys (1-9) to select search engines if (e.altKey && e.key >= '1' && e.key <= '9') { e.preventDefault(); const engineIndex = parseInt(e.key) - 1; const engineButtons = document.querySelectorAll('.engine-button'); if (engineButtons[engineIndex]) { engineButtons[engineIndex].click(); engineButtons[engineIndex].focus(); } } // Escape to clear search input if (e.key === 'Escape' && document.activeElement === searchInput) { searchInput.value = ''; } }); // Prevent form resubmission on page refresh if (window.history.replaceState) { window.history.replaceState(null, null, window.location.href); } // Initialize the application when DOM is fully loaded document.addEventListener('DOMContentLoaded', function () { init(); });`