This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Umbreon is a Chrome dark mode extension (MV3) that applies dark themes to any website. No build step required - uses vanilla JavaScript with ES modules.
Load as unpacked extension:
- Open
chrome://extensions - Enable Developer mode
- Click "Load unpacked" and select this project folder
Reload the extension after code changes via the refresh icon on the extensions page.
All communication uses chrome.runtime.sendMessage with message types defined in src/shared/messaging.js. The service worker acts as a central hub, handling messages from popup, options, and content scripts.
Service Worker (src/background/service_worker.js)
- Computes effective state per tab by combining: nightlight setting, auto-activate rules, disable lists, and tab overrides
- Tab overrides (user toggles) are stored in session storage and cleared on tab close
- Injects content script on demand via
chrome.scripting.executeScript
Content Script (src/content/content.js)
- MUST remain as classic (non-module) script because
chrome.scripting.executeScriptinjects as classic - Uses IIFE with guard key to prevent duplicate execution when re-injected
- Inlines
MessageType.APPLYconstant since ESM imports aren't available - Themes are hardcoded CSS variable definitions (not fetched) for MV3 compatibility
- Patches
Element.prototype.attachShadowto inject styles into dynamically created shadow roots - Uses MutationObserver to fix contrast on newly added DOM elements
Storage Layer (src/shared/storage.js)
chrome.storage.syncfor persistent settings (synced across devices)chrome.storage.sessionfor ephemeral tab overrides
When determining if dark mode is enabled for a tab:
- Check if URL is restricted (chrome://, edge://, about:, webstore)
- Check tab override (explicit user toggle for this session)
- Check disable rules (per-origin or per-page)
- Check nightlight or auto-activate rules (requires
<all_urls>permission)
Extension starts with minimal permissions (activeTab, scripting, storage). The optional <all_urls> permission is requested only when enabling Nightlight or adding auto-activate rules.