Add-Ons for Web Browsers With React

Sometimes we would like to increase our productivity when working with our favorite web browser. It usually helps to use a proper browser add-on, but not always. Sometimes there’s no add-on to solve a specific problem you have. In that case, you can create your own add-on, and React can help you with that.

Creating a web browser add-on may seem to be a niche, but there are already plenty of them available in many web browsers like Chrome, Firefox, Opera that individual developers or users create. There are also many guides, tutorials, and instructions available - they all describe the process of creating such add-ons step by step.

The basic structure of every web browser add-on

Before diving into details on how to set up and use React in web browser add-ons development, let’s have some fundamentals covered.

Every web browser add-on is created using JavaScript or TypeScript. It contains three major parts:

  1. Manifest:
    This file contains important information regarding the add-on, such as its version number, required permissions, icons, and scripts it uses. Its structure will vary between versions 2 and 3, which are currently supported by major web browsers.
    ‍
  2. Scripts:
    These act as the engine of your web add-on. Background scripts are registered during the add-on launch and can run in the background, performing tasks like manipulating the browser, its windows, tabs, etc. Content scripts are the ones that are launched for the context of a single web page and are able to manipulate its content.
    ‍
  3. UI implementation:
    In its most basic form, this is where the HTML code of your add-on is. Using the script tag, you can always use JavaScript to launch a script in your view. In other words, a web browser add-on is like a simple web page (yes, let’s keep our add-ons simple) with its backend - background scripts and actual server if you use one, and frontend as the client of the said scripts or server.

And this is where React comes in - with React you can easily implement the most complex UI solution you can imagine providing users of your add-on with the top-notch layout, look and feel.

<p-bg-col>What’s important to note is that not all of these parts are required. The truth is that only the manifest is required for your add-on to be fully working in the browser, but the rest is up to you and your needs regarding what your add-on is about to do.<p-bg-col>

Examples

Let’s say you work on the ad blocker add-on which launches all the logic behind the scenes each time you visit a website. Such an add-on will only have the Background and/or Content scripts implemented, as there’s no need to show any popup to the user (of course, you can still implement it to provide your user with statistics on how many ads were blocked by now, but it’s up to you).

Another example would be the extension which would present to the user a weather update that can be fetched from the internet. This update would be displayed in the popup or via a modal or alert. There’s no need to implement any Background and/or Content scripts.

Creating the project and setup

Every web browser on the market has a guide or tutorial focused on creating the basic setup and on starting development. So the first step I recommend is to search for a tutorial regarding your favorite web browser (such a tutorial is to be found on the official websites of the web browser) or the web browser you want to support in your extension and get familiar with the steps listed there regarding:

  • What the project structure should look like
  • How to build and pack the extension
  • How to manually test it locally before publishing
  • How to eventually publish it to the market

The two first points listed above are common for every browser there is, but the last two will vary across every browser. And because the first two are common the repository of your add-on should always contain the package.json file in the root of your project, next to the setup files (all other configs for tools you use or those described further), and next to the add-on application implementation directory.

So once we have the initial structure, let’s start installing all the basic tools we will need to use React for developing the add-on.

Depending on your package manager tool, let’s install the following: 

  • React
  • react-dom
  • webpack

as the basic setup for working with React in add-ons development.

Remember that you will also need a tool to transpile your code so you can follow Babel’s guide on how to set it up depending on your needs.

If you plan to write tests for your add-on (which I totally and strongly recommend, and will cover in future articles), you can also install Jest and react-test-renderer.

Of course, for the sake of your own development experience, you can supply your repository with additional code-quality tools, like ESLint and TypeScript.

So you now have the setup ready. Following the guide of the browser you selected to support, you also should have the directory now with the add-ons implementation itself. This directory can be called whatever you want, but it should contain the already described manifest file with the required source code files:

  1. The Background scripts and/or the Content scripts (if you plan to use them)
  2. The view of your popup implemented in a single HTML code

Those parts are also already described above, so let’s jump into our main point of interest: the popup view.

Popup view 

A popup is something that appears each time the user clicks the icon of your add-on and is something that the user will interact with when using your add-on. However, currently, this view is just the most basic HTML page there can be, so let’s quickly and easily set it up with React.

Developing the popup with React

To do that we should start with the entry point or our add-on’s view. The manifest of your add-on contains the browser_action or action part, depending on the manifest version, where the default_popup field should already exist. If it does not, let’s create it and add there the HTML code of our popup’s view we want to be the entry of our add-on. So for version 2 of manifest it will be:

"browser_action": {
"default_popup": "src/popup/Popup.html"
}
view raw snippet1.js hosted with ❤ by GitHub

or for version 3 of manifest:

"action": {
"default_popup": "src/popup/Popup.html"
}
view raw snippet2.js hosted with ❤ by GitHub

The HTML code implemented in src/popup/Popup.html should contain the script tag and the div with the selected id (most probably root). All in its body.

For the script, let’s create the first JS or TS file in which we will instantiate the first React component as the root of our DOM. The implementation may vary of course, but below is just the basic example of how this entry component may look like:

import React, { useEffect } from "react";
import ReactDOM from "react-dom";
export const Popup = (): JSX.Element => {
useEffect(() => {
document.addEventListener("click", (event) => {
event.preventDefault();
});
}, [document]);
return <div className="popup-view"></div>;
};
ReactDOM.render(<Popup />, document.getElementById("root"));
view raw snippet3.js hosted with ❤ by GitHub

On a final note

What this implementation does may be clear for you, but there are some things worth mentioning. Anything given as children of the div will be rendered just like it is when developing any other web page with React. There is really no difference, and that is really awesome!

It means that you can work with React in creating your web browser add-on just like you would work with it on any other day during web development.

‍

Insights

Learn more about Developer Experience

cover

May 5Article

Codex Ambassador: Q1 Recap Across 5 Cities

A short recap of Codex events in Berlin, Wroclaw, Warsaw, Sopot, and Miami, plus what we learned from each format and where we want to go next.

cover

Feb 5Live Stream

Storybook Explained: From Basics to Advanced Workflows

Core Storybook concepts, stories and args, interaction testing, and how Storybook works in React Native projects.

cover

Jan 29Article

Announcing AI SDK Profiler for React Native

Announcing the AI SDK Profiler plugin for Rozenite DevTools. Capture OpenTelemetry spans from the Vercel AI SDK and inspect AI requests across on-device and cloud providers.

cover

Nov 28Talk

How I Hacked React Native DevTools (And Built a Plugin Framework)

Learn how React Native DevTools work under the hood, and how to inject custom plugins with clean hooks and no forks.

cover

Sep 16Talk

How I Hacked React Native DevTools (And Built a Plugin Framework)

Learn how React Native DevTools work under the hood, and how to inject custom plugins with clean hooks and no forks.

cover

Jul 28Article

Introducing Rozenite: A Plugin Framework for React Native DevTools

Build custom debugging panels inside React Native DevTools with Rozenite: a modular, TypeScript-ready plugin framework with full device-scoped support.

cover

Feb 12Article

How to Easily Create Native Libraries With Nitro and Turbo Modules

Learn how to optimize React Native performance with Turbo and Nitro Modules. Ditch the legacy bridge and master modern native module development.

cover

Dec 4Podcast

Radon IDE: Better Developer Experience for React Native Teams

Find out how Radon IDE can help increase team velocity and rid you of the common React Native app development pain points.

cover

Sep 19Podcast

Exploring Bun: Jarred Sumner on Hyperfast JavaScript Toolkit

Is Bun the future of React Native package management? Join us as we talk with Jarred Sumner, the creator of this lightning-fast JavaScript toolkit.

cover

Sep 11Podcast

Vim: from Zero to Hero

Discover the power of Vim, the legendary text editor, as we explore its origins, standout features, and practical tips to boost your coding efficiency.

cover

Jan 27Article

Why Is It Worth to Automate Your Dependency Management with `Autolinking`?

When you automate your dependency management, you can fully focus on developing your app. Find out how you can do it with autolinking.

cover

Oct 11Article

Setting up React Native Monorepo With Yarn Workspaces

Why you should create a React Native monorepo and how to do it.

cover

Mar 19Tutorial

The Hard Way vs. The React Native AI SDK Way: Stop Writing Custom Modules for Every Model

Learn how React Native AI uses a unified provider model to switch between cloud and on-device LLMs without rewriting application logic, enabling reliable AI experiences online and offline.

cover

Mar 12Tutorial

Build Smarter Apps: Tool Calling & AI Orchestration Explained

Learn how on-device models in React Native can call tools, interact with external APIs, and return structured outputs you can use directly in application logic.

cover

Mar 5Tutorial

MLC LLM + React Native: On-Device AI Without the Pain

Learn how to run third-party on-device LLMs in React Native using MLC LLM. Choose your models, run them efficiently across platforms, and keep a unified JavaScript API with React Native AI.

cover

Feb 24Tutorial

Intelligent Fallbacks with Apple Intelligence in React Native

Learn how to use Apple’s built-in Foundation Models in React Native apps, reduce memory usage, and enable fast, fully on-device AI with React Native AI Apple.

cover

Feb 10Tutorial

What Is the React Native AI SDK? A Complete Intro & Quickstart

Learn why on-device AI matters for React Native apps, how local LLMs behave offline, and what problems React Native AI is designed to solve from day one.

cover

Jan 29Tutorial

Implementing an Android TurboModule with Kotlin

Learn how to implement a React Native TurboModule on Android, from the TypeScript spec and Codegen to the Kotlin implementation and package registration.

cover

Jan 19Tutorial

Working with Different Threads in Swift TurboModules

Learn how JavaScript, native module, background, and main threads interact in React Native TurboModules, and how to use GCD queues to run async work safely in Swift.

cover

Jan 9Tutorial

How to Add Type-Safe Constants to Swift TurboModules

Learn how to expose typed, immutable constants from a Swift TurboModule using Codegen, and get full end-to-end type safety between native and JavaScript.

cover

Dec 30Tutorial

Adding Event Emitters to Your TurboModule in Swift

Learn how to emit native events from a Swift TurboModule and subscribe to them in JavaScript, including proper memory management and Codegen integration.

cover

Dec 22Tutorial

Writing Your First TurboModule in Swift

Learn how to build a fully working TurboModule in Swift, integrate it with Codegen, and bridge it through Objective‑C inside an Expo app.