How Read Frog's Site Control Mechanages Extension Behavior with Whitelisting and Blacklisting
Read Frog's site control mechanism uses a configuration object with mode and patterns fields to determine whether content scripts run on specific websites, supporting both universal activation ("all" mode) and domain-specific whitelisting.
Read Frog implements a granular site control system that governs where its browser extension activates. The mechanism, defined in the repository's configuration schema and utility modules, allows users to either enable the extension globally or restrict it to specific domains through pattern matching.
Core Components of the Site Control System
Configuration Schema and Data Structure
The site control configuration is defined in src/types/config/config.ts (lines 76-80). The siteControl object contains two critical fields:
mode: Accepts either"all"or"whitelist". When set to"all", the extension activates on every website. When set to"whitelist", activation depends on pattern matching.patterns: An array of domain strings (e.g.,example.com,sub.example.com) that define permitted domains when operating in whitelist mode.
The Site Enablement Logic
The core decision logic resides in src/utils/site-control.ts (lines 4-15). The isSiteEnabled function evaluates whether a given URL should trigger extension behavior:
export function isSiteEnabled(url: string, config: Config | null): boolean {
if (!config) return true;
const { mode, patterns } = config.siteControl;
if (mode === "all") return true;
// whitelist mode – enable only if a pattern matches
return patterns.some(pattern => matchDomainPattern(url, pattern));
}
Content scripts throughout the extension import this utility and abort initialization if the site fails the check:
import { isSiteEnabled } from "@/utils/site-control";
import { getLocalConfig } from "@/utils/config/storage";
import { DEFAULT_CONFIG } from "@/utils/constants/config";
const config = await getLocalConfig() ?? DEFAULT_CONFIG;
if (!isSiteEnabled(window.location.href, config)) {
// Extension will stay dormant on this page
return;
}
// …continue initializing UI…
Domain Pattern Matching Implementation
The pattern matching algorithm is implemented in src/utils/url.ts (lines 3-20). The matchDomainPattern function normalizes both the URL and pattern, then checks for either an exact hostname match or a subdomain relationship:
// matchDomainPattern handles cases like:
// pattern: "example.com" matches "example.com" and "sub.example.com"
// but does not match "badexample.com"
This implementation allows users to specify broad domain coverage (e.g., github.com covers both github.com and gist.github.com) without requiring explicit subdomains in the pattern list.
User Interface and State Management
Popup Atoms for Whitelist Control
The popup interface manages whitelist state using Jotai atoms defined in src/entrypoints/popup/atoms/site-control.ts. Two primary atoms track the current configuration:
isWhitelistModeAtom: Boolean indicating whethermode === "whitelist"isCurrentSiteInWhitelistAtom: Boolean indicating whether the active tab's URL matches any pattern in the current whitelist
The initSiteControlAtomsAtom initializes these values by reading the stored configuration when the popup loads (lines 25-32).
Toggling Site Inclusion
The toggleCurrentSiteInWhitelistAtom handles adding or removing the current site's hostname from the siteControl.patterns array (lines 35-75). When a user enables the extension for the current site:
import { toggleCurrentSiteInWhitelistAtom } from "@/entrypoints/popup/atoms/site-control";
import { useSetAtom } from "jotai/react";
const toggle = useSetAtom(toggleCurrentSiteInWhitelistAtom);
// When a user checks the "Enable on this site" switch:
await toggle(true); // adds hostname to config.siteControl.patterns
After updating the configuration, the atom triggers a page reload of the active tab. This ensures content scripts re-evaluate isSiteEnabled with the updated pattern list, immediately activating the extension on the newly whitelisted domain.
Persistence and Storage
The site control configuration persists across browser sessions using extension storage helpers in src/utils/config/storage.ts. The getLocalConfig function retrieves the stored configuration on startup, while updates write back to Chrome or Firefox extension storage.
When users modify the whitelist through the popup, the Jotai atoms update both the in-memory state and the persistent storage, ensuring that content scripts loading on subsequent page visits respect the latest site control settings.
Implementation in Content Scripts
Every content script entry point (such as the side panel in src/entrypoints/side.content/index.tsx) implements the site control check before rendering any UI components. This pattern prevents the extension from injecting elements into pages where the user has not authorized activity, or conversely, ensures activation on permitted domains when whitelist mode is active.
The check occurs early in the script lifecycle to minimize performance impact on non-target pages.
Summary
- Read Frog's site control mechanism relies on a
siteControlconfiguration object withmodeandpatternsfields defined insrc/types/config/config.ts. - The
isSiteEnabledfunction insrc/utils/site-control.tsimplements the core logic, returningtruefor all sites whenmodeis"all", or checking domain patterns whenmodeis"whitelist". - Domain matching uses the
matchDomainPatternhelper insrc/utils/url.ts, supporting exact matches and subdomain wildcards. - The popup UI manages whitelist state through Jotai atoms in
src/entrypoints/popup/atoms/site-control.ts, allowing users to toggle the current site and trigger page reloads. - Configuration persists via extension storage helpers in
src/utils/config/storage.ts, ensuring site control settings survive browser restarts. - Content scripts check
isSiteEnabledbefore initialization to respect user preferences.
Frequently Asked Questions
How does Read Frog determine if a website is whitelisted?
Read Frog uses the isSiteEnabled function in src/utils/site-control.ts to evaluate the current URL against the stored configuration. When siteControl.mode is set to "whitelist", the function iterates through the patterns array and uses matchDomainPattern from src/utils/url.ts to check if the hostname matches any pattern exactly or as a subdomain.
Can Read Frog block specific sites while allowing all others?
The current implementation does not include a dedicated blacklist mode. To achieve blacklist-like behavior, users must set siteControl.mode to "whitelist" and include all desired domains in the patterns array while omitting the sites they wish to block. The extension will then remain inactive on any domain not explicitly listed.
Where is the site control configuration stored?
The configuration persists in the browser's extension storage using helpers defined in src/utils/config/storage.ts. The getLocalConfig function retrieves settings on startup, and the Jotai atoms in src/entrypoints/popup/atoms/site-control.ts write updates back to storage whenever users modify the whitelist through the popup interface.
How does the extension update when I change the whitelist?
When you toggle a site's inclusion via the popup, the toggleCurrentSiteInWhitelistAtom updates the configuration and triggers a reload of the active tab. This reload causes content scripts to re-execute, calling isSiteEnabled with the updated siteControl.patterns array, which immediately activates or deactivates the extension for that site.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →