# Read Frog Firefox Compatibility: Configuration Guide for Optimal Performance

> Optimize Read Frog compatibility in Firefox. Learn to adjust manifest permissions, configure CSP, add gecko metadata, and manage Web Speech API for peak performance.

- Repository: [MengXi/read-frog](https://github.com/mengxi-ream/read-frog)
- Tags: how-to-guide
- Published: 2026-03-07

---

**To ensure optimal compatibility and performance of Read Frog on Firefox, developers must adjust the extension manifest to omit unsupported permissions like `offscreen`, implement a custom Content Security Policy, add `browser_specific_settings.gecko` metadata, and gate Text-to-Speech features that rely on unsupported Web Speech APIs.**

Read Frog is an open-source browser extension built with the **WXT** framework that provides advanced reading capabilities across multiple browsers. When targeting **Firefox**, the codebase in `mengxi-ream/read-frog` requires specific conditional adjustments to handle Firefox's stricter Manifest V3 implementation and missing APIs. This guide details the exact configurations needed for seamless Firefox operation.

## Manifest Configuration Adjustments for Firefox

The [`wxt.config.ts`](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts) file generates the extension manifest dynamically based on the target browser. For Firefox compatibility, three critical modifications are required.

### Removing Offscreen Permission

Firefox does not support the `offscreen` API used in Chrome for DOM parsing in service workers. The configuration conditionally excludes this permission when building for Firefox:

```typescript
// wxt.config.ts – permission configuration
permissions: [
  "storage",
  "tabs",
  "alarms",
  "cookies",
  "contextMenus",
  "identity",
  "scripting",
  "webNavigation",
  ...(browser !== "firefox" ? ["offscreen"] : []),   // ← Firefox-specific exclusion
],

```

*Source:* [wxt.config.ts#L35-L36](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts#L35-L36)

### Custom Content Security Policy

Firefox Manifest V3 enables `upgrade-insecure-requests` by default, which can interfere with extension functionality. Read Frog overrides the CSP to remove this directive and explicitly allow WebAssembly execution:

```typescript
// wxt.config.ts – Firefox CSP override
...(browser === "firefox" && {
  content_security_policy: {
    extension_pages:
      "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';",
  },
}),

```

*Source:* [wxt.config.ts#L50-L55](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts#L50-L55)

### Gecko Browser Specific Settings

Firefox requires a `browser_specific_settings.gecko` block containing a stable extension ID and minimum version constraint:

```typescript
// wxt.config.ts – Gecko metadata
browser_specific_settings: {
  gecko: {
    id: "{bd311a81-4530-4fcc-9178-74006155461b}",
    strict_min_version: "109.0",
  },
},

```

*Source:* [wxt.config.ts#L56-L59](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts#L56-L59)

## Feature Gating for Firefox Limitations

Firefox lacks support for the Web Speech API used by Read Frog's Text-to-Speech (TTS) functionality. The codebase uses runtime environment checks to disable these features on Firefox.

### Disabling Text-to-Speech Components

The TTS page is conditionally removed from the navigation routes in the options sidebar:

```typescript
// src/entrypoints/options/app-sidebar/nav-items.ts
...(import.meta.env.BROWSER === "firefox" 
  ? [] 
  : [{ path: "/tts", component: TextToSpeechPage }]
),

```

*Source:* [nav-items.ts#L24-L25](https://github.com/mengxi-ream/read-frog/blob/main/src/entrypoints/options/app-sidebar/nav-items.ts#L24-L25)

### Hiding UI Elements Conditionally

The `SpeakButton` component is hidden in the selection toolbar when running on Firefox:

```tsx
// src/entrypoints/selection.content/selection-toolbar/index.tsx
const isFirefox = import.meta.env.BROWSER === "firefox";

return (
  <div>
    {/* Other toolbar buttons */}
    {!isFirefox && <SpeakButton />}
  </div>
);

```

*Source:* [selection-toolbar.tsx#L60-L53](https://github.com/mengxi-ream/read-frog/blob/main/src/entrypoints/selection.content/selection-toolbar/index.tsx#L60-L53)

The `IS_FIREFOX` constant is also defined in the command palette for consistent feature toggling across the extension:

```typescript
// src/entrypoints/options/command-palette/search-items.ts
const IS_FIREFOX = import.meta.env.BROWSER === "firefox";

```

*Source:* [search-items.ts#L9-L10](https://github.com/mengxi-ream/read-fream/read-frog/blob/main/src/entrypoints/options/command-palette/search-items.ts#L9-L10)

## Selection Handling Workarounds

Firefox exhibits unique behavior where text selection is cleared when focus moves to dropdown elements. Read Frog implements specific guards to maintain toolbar visibility during these interactions.

### Preventing Selection Loss on Dropdown Focus

The selection toolbar tracks dropdown state using a `dropdownOpenRef` to prevent premature hiding:

```typescript
// src/entrypoints/selection.content/selection-toolbar/index.tsx
const dropdownOpenRef = useRef(false);

const handleSelectionChange = () => {
  const selection = window.getSelection();
  if (!selection || selection.toString().trim().length === 0) {
    // Firefox clears selection on dropdown focus → keep toolbar if open
    if (!dropdownOpenRef.current) {
      setIsSelectionToolbarVisible(false);
    }
  }
};

```

*Source:* [selection-toolbar.tsx#L92-L100](https://github.com/mengxi-ream/read-frog/blob/main/src/entrypoints/selection.content/selection-toolbar/index.tsx#L92-L100)

## Build and Distribution Requirements

Security and packaging requirements differ for Firefox distribution, particularly regarding environment variable handling.

### Environment Variable Validation

The build process includes a Vite plugin that validates no API keys are accidentally bundled into the production code:

```typescript
// wxt.config.ts – build-time validation
if (apiKeyVars.length > 0) {
  throw new Error(
    `Found WXT_*_API_KEY environment variables that may be bundled...`
  );
}

```

*Source:* [wxt.config.ts#L77-L86](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts#L77-L86)

When creating distribution ZIP files for the Firefox Add-ons store, ensure the `WXT_GOOGLE_CLIENT_ID` environment variable is properly configured for OAuth functionality.

## Summary

- **Manifest adjustments** in [`wxt.config.ts`](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts) require omitting the `offscreen` permission, overriding the default CSP to remove `upgrade-insecure-requests`, and adding the `browser_specific_settings.gecko` block with a stable ID and minimum version.
- **Feature gating** uses `import.meta.env.BROWSER === "firefox"` checks to disable Text-to-Speech components in [`nav-items.ts`](https://github.com/mengxi-ream/read-frog/blob/main/nav-items.ts) and hide the `SpeakButton` in the selection toolbar.
- **Selection handling** implements `dropdownOpenRef` guards in [`selection-toolbar/index.tsx`](https://github.com/mengxi-ream/read-frog/blob/main/selection-toolbar/index.tsx) to prevent the toolbar from disappearing when Firefox clears text selection on dropdown focus.
- **Build security** relies on the `check-api-key-env` Vite plugin to prevent bundling sensitive credentials, which is critical for passing Firefox Add-ons store review.

## Frequently Asked Questions

### Why does Read Frog disable Text-to-Speech on Firefox?

Firefox does not currently support the Web Speech API's speech synthesis functionality that Read Frog uses for Text-to-Speech features. According to the source code in [`src/entrypoints/options/app-sidebar/nav-items.ts`](https://github.com/mengxi-ream/read-frog/blob/main/src/entrypoints/options/app-sidebar/nav-items.ts), the TTS page route is conditionally excluded when `import.meta.env.BROWSER === "firefox"` evaluates to true, preventing users from accessing unsupported functionality.

### What is the minimum Firefox version required for Read Frog?

Read Frog requires Firefox version **109.0** or higher. This constraint is defined in the `strict_min_version` field within the `browser_specific_settings.gecko` block in [`wxt.config.ts`](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts). This version requirement ensures compatibility with the Manifest V3 features that Read Frog relies upon.

### How does Read Frog handle the missing offscreen API in Firefox?

The extension conditionally omits the `offscreen` permission from the manifest when building for Firefox. In [`wxt.config.ts`](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts), the permissions array uses the spread operator with a ternary condition: `...(browser !== "firefox" ? ["offscreen"] : [])`. This ensures Firefox builds do not request unsupported permissions while Chrome builds retain the offscreen functionality needed for DOM parsing in service workers.

### Why is a custom Content Security Policy needed for Firefox compatibility?

Firefox's Manifest V3 implementation enables `upgrade-insecure-requests` by default in the Content Security Policy, which can interfere with extension functionality. Read Frog overrides this in [`wxt.config.ts`](https://github.com/mengxi-ream/read-frog/blob/main/wxt.config.ts) by specifying a custom `content_security_policy` that removes the upgrade directive and explicitly allows WebAssembly execution via `'wasm-unsafe-eval'`. This ensures consistent behavior across browsers while maintaining security boundaries.