5 Lessons I Learned Building a Firefox New Tab Extension from Scratch
Source: Dev.to
The manifest_version: 3 Transition Is Mostly Smooth, But Watch for Service Worker Gotchas
Firefox now supports Manifest V3, and I decided to go all‑in. Most things just work — declarative content scripts, the new permissions model, cleaner background handling.
But service workers have a critical limitation: they go inactive after 30 seconds. For a new‑tab extension that needs to refresh weather data periodically, this matters.
Solution: fetch weather data on each new‑tab open, not on a persistent background schedule. Cache the result in localStorage and refresh only if the cached data is older than 10 minutes.
async function getWeather() {
const cached = JSON.parse(localStorage.getItem('weatherCache') || '{}');
const now = Date.now();
if (cached.data && (now - cached.timestamp) fetchWeatherByCoords(pos.coords),
(err) => {
// err.code === 1: User denied
// err.code === 2: Position unavailable
// err.code === 3: Timeout
showManualCityInput(
err.code === 1
? 'Location blocked — enter your city manually'
: 'Could not detect location'
);
},
{ timeout: 5000, maximumAge: 3600000 }
);
Dark Mode Detection in Extensions Is Actually Elegant
Implementing dark/light mode switching is straightforward in extensions. You get prefers-color-scheme support out of the box, plus the option to persist a user preference.
// Auto-detect system preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
// Apply theme
function applyTheme(dark) {
document.documentElement.setAttribute('data-theme', dark ? 'dark' : 'light');
localStorage.setItem('theme', dark ? 'dark' : 'light');
}
// Listen for system changes
prefersDark.addEventListener('change', (e) => applyTheme(e.matches));
// On load: check user preference first, then system
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
applyTheme(savedTheme === 'dark');
} else {
applyTheme(prefersDark.matches);
}
Users get a “just works” experience (matches their OS setting) with the option to override.
AMO Review Is Actually Quite Fast (and Human)
I expected a multi‑week wait for the Firefox Add‑On (AMO) review process. My experience was surprisingly good:
- Initial review: ~3 days
- Reviewer feedback: Specific and actionable (they flagged one
eval()call I hadn’t noticed) - Follow‑up review: ~1 day
The reviewer pointed out that I was using innerHTML to set a clock time value (unnecessary DOM risk even though the data was internal) and asked me to switch to textContent. Fair point.
Tips to speed up review:
- Write clean, readable code
- Minimize permissions to exactly what you need
- Avoid remote code execution
- No obfuscation
- Include source maps if you minify
The Result
After all this, I shipped Weather & Clock Dashboard — it’s open source (MIT), requires no account, and is genuinely useful.
If you’re building a Firefox extension, the developer experience is actually solid. The API documentation has improved dramatically in recent years, and the Mozilla developer community is helpful.
Built with: Pure HTML/CSS/JS · No build step · MIT Licensed