Start Page
This Extension allows you to create a Newtab page which will replace the default page that loads in a new tab in your Webfuse Sessions.
Directorystart-page-extension
- manifest.json
- new_tab.html
manifest.json
Section titled “manifest.json”{ "manifest_version": 3, "name": "Start page", "version": "1.0", "chrome_url_overrides": { "newtab": "new_tab.html" }}
new_tab.html
Section titled “new_tab.html”<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <title>Space Start Page</title> <link rel="stylesheet" href="styles.css" /></head><body> <div class="container"> <h1>Start a Session 🔎</h1> <div class="search-box"> <input id="query" type="text" placeholder="Enter your search..." />
<h3>Select a search engine</h3> <div class="dropdown" id="engineDropdown"> <div class="dropdown-selected" id="selectedEngine"> <img src="https://www.google.com/favicon.ico" alt="icon"> <span>Google</span </div> <div class="dropdown-list" id="engineList"> <div class="dropdown-item" data-url="https://www.google.com/search?q="> <img src="https://www.google.com/favicon.ico" alt="Google"> <span>Google</span> </div> <div class="dropdown-item" data-url="https://www.bing.com/search?q="> <img src="https://www.bing.com/sa/simg/favicon-2x.ico" alt="Bing"> <span>Bing</span> </div> <div class="dropdown-item" data-url="https://duckduckgo.com/?q="> <img src="https://duckduckgo.com/favicon.ico" alt="DuckDuckGo"> <span>DuckDuckGo</span> </div> </div> </div> </div> <button id="searchBtn">Start Session</button> </div>
<script> const dropdown = document.getElementById('engineDropdown'); const selected = document.getElementById('selectedEngine'); const list = document.getElementById('engineList'); let currentUrl = selected.datasetUrl || 'https://www.google.com/search?q=';
selected.addEventListener('click', () => { list.style.display = list.style.display === 'block' ? 'none' : 'block'; });
list.querySelectorAll('.dropdown-item').forEach(item => { item.addEventListener('click', () => { const img = item.querySelector('img').src; const name = item.querySelector('span').textContent; currentUrl = item.dataset.url; selected.innerHTML = `<img src="${img}" alt="${name}"><span>${name}</span>`; list.style.display = 'none'; }); });
let myIndex = null; let controlIndex = null; browser.webfuseSession.onMessage.addListener(message => { if (message?.event_type === 'host_changed') { myIndex = message.my_index; } else if (message?.event_type === 'tab_control') { if (message.controlIndex !== message.leaderIndex) { controlIndex = message.controlIndex; } } });
const start = () => { const query = document.getElementById('query').value.trim(); if (query) { const url = currentUrl + encodeURIComponent(query); if (myIndex === controlIndex) { browser.webfuseSession.apiRequest({ cmd: "relocate", url: url, newTab: false, }); } else { browser.runtime.sendMessage({ type: "navigate", url: url, clientIndex: controlIndex, }); } } }; document.getElementById('searchBtn').addEventListener('click', start); document.getElementById("query").addEventListener('keydown', e => { if (e.key === 'Enter') { e.preventDefault(); start(); } });
document.addEventListener('click', (e) => { if (!dropdown.contains(e.target)) { list.style.display = 'none'; } });
document.addEventListener('DOMContentLoaded', () => document.getElementById("query").focus()); </script></body></html>
styles.css
Section titled “styles.css”body { margin: 0; font-family: Arial, sans-serif; background: linear-gradient(135deg, #1b2735, #090a0f); color: white; display: flex; justify-content: center; align-items: center; height: 100vh;}
.container { text-align: center; background: rgba(255, 255, 255, 0.05); padding: 30px; border-radius: 16px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); max-width: 420px; width: 100%;}
h1 { margin-bottom: 20px; font-size: 26px;}
.search-box { display: flex; flex-direction: column; gap: 12px; position: relative;}
input { padding: 10px 12px; font-size: 16px; border-radius: 8px; border: none;}
h3 { margin: 0; padding: .3em;}
.dropdown { position: relative; cursor: pointer; padding-bottom: .5em;}
.dropdown-selected { display: flex; align-items: center; padding: 10px 12px; border-radius: 8px; background: #222;}
.dropdown-selected img { width: 20px; height: 20px; margin-right: 8px;}
.dropdown-list { position: absolute; top: 100%; left: 0; right: 0; background: #222; border-radius: 8px; margin-top: 4px; max-height: 200px; overflow-y: auto; display: none; z-index: 10;}
.dropdown-item { display: flex; align-items: center; padding: 8px 12px; cursor: pointer;}
.dropdown-item:hover { background: #3b82f6;}
.dropdown-item img { width: 20px; height: 20px; margin-right: 8px;}
button { padding: 10px 12px; font-size: 16px; border-radius: 8px; border: none; cursor: pointer; background: #3b82f6; color: white; transition: background 0.2s;}
button:hover { background: #2563eb;}
Key Points
Section titled “Key Points”- Using the
chrome_url_overrides
property to override the default new tab page:
"chrome_url_overrides": { "newtab": "new_tab.html"}
- Using Webfuse JS API to navigate to a new tab depending on the leader of the tab:
browser.webfuseSession.apiRequest({ cmd: "relocate", url: url, newTab: false,});// ORbrowser.runtime.sendMessage({ type: "navigate", url: url, clientIndex: controlIndex,});
- Listening for Webfuse Session Events to get the leader of the tab and current user index:
browser.webfuseSession.onMessage.addListener(message => { if (message?.event_type === 'host_changed') { myIndex = message.my_index; } else if (message?.event_type === 'tab_control') { controlIndex = message.controlIndex; }});
styles.css
is included as a regular style tag in thenew_tab.html
file:
<link rel="stylesheet" href="styles.css" />