Back to Blog

Build a Chrome Extension with React and TypeScript

Learn how to build a Chrome extension using React and TypeScript in 2026. Covers project setup, Manifest V3, popup UI, content scripts, and publishing.

MM

Michael McGarvey

April 1, 2026·4 min read
Building a Chrome extension with React and TypeScript

Most Chrome extensions are still built with plain HTML, CSS, and vanilla JavaScript. That approach works for simple tools, but the moment your extension grows beyond a single popup button you start running into problems. State management becomes messy. Refactoring breaks things silently. The UI code gets tangled in ways that slow you down every time you want to add a feature. React and TypeScript solve these problems by giving you components that are easy to reuse and a type system that catches mistakes before your users ever see them. If you are building a Chrome extension in 2026, this combination is the fastest way to ship something polished and maintainable. For a broader look at getting started from scratch, see how to create a Chrome extension from the ground up.

1.

2.

3.

4.

5.

6.

7.

8.

Why React and TypeScript for Chrome Extensions

React lets you break your extension UI into small, self-contained components. A popup with a settings panel, a list of saved items, and a status indicator becomes three clean components instead of one sprawling HTML file. When you need to update the settings panel, you change one component without worrying about breaking the rest.

TypeScript adds a layer of safety on top of that. Chrome extensions rely heavily on message passing between the popup, background service worker, and content scripts. Without types, it is easy to send a message with the wrong shape and spend an hour debugging why nothing happens. TypeScript catches those mismatches at build time so they never reach your users.

Together they also unlock the broader React ecosystem. You can pull in UI libraries, state management tools, and styling solutions like Tailwind CSS that would be awkward or impossible to use in a vanilla JavaScript extension. For more on why Tailwind is a strong fit for extension styling, read why Tailwind CSS is the best choice for modern extension UI development.

Understanding the Chrome Extension Architecture

Before you start writing React components, it helps to understand where they actually run inside an extension. A Chrome extension built on Manifest V3 has four main parts.

The manifest file is a JSON configuration that tells Chrome everything about your extension: its name, permissions, which files to load, and where the popup and background scripts live. The popup is the small window that appears when a user clicks your extension icon. The background service worker handles events and long-running logic without a visible UI. Content scripts are injected into web pages and can read or modify the page the user is viewing.

React fits naturally into the popup and options pages because those are standard HTML pages where you can mount a React app. The background service worker does not have a DOM, so it stays as plain TypeScript. Content scripts can use React if you render into a Shadow DOM, but for most extensions keeping content scripts lightweight and vanilla is the simpler path.

Setting Up Your Project

The modern setup for a React and TypeScript Chrome extension uses Vite as the build tool. Vite handles bundling, hot module replacement during development, and produces optimized output for production. Start by scaffolding a new Vite project with the React and TypeScript template, then adjust the configuration to output files in the structure Chrome expects.

Your project folder should have a manifest JSON file at the root of the output directory, a popup folder containing your React entry point, a background folder for the service worker, and an optional content scripts folder. The key is configuring Vite to produce multiple entry points rather than a single bundled application. Each entry point maps to a different part of the extension architecture.

Install the Chrome types package so TypeScript understands the Chrome extension APIs. This gives you autocomplete and type checking for every API call, from storage and messaging to tabs and alarms. The type definitions alone save hours of consulting documentation.

ExtensionFast

Ship Your Chrome Extension This Weekend

ExtensionFast gives you auth, payments, and a landing page out of the box — so you can focus on your unique features, not the boilerplate.

Chrome extension built fast with ExtensionFast
Wand iconGet ExtensionFast

Building the Popup UI with React

The popup is where most of your React code lives. It is a standard React application rendered inside a small browser window, typically around 400 by 600 pixels. Design your components with this constraint in mind. Avoid complex layouts that require scrolling and focus on showing the user exactly what they need at a glance.

Start with a single root component that mounts when the popup opens. Break the interface into smaller components as the UI grows. A typical popup might have a header component, a main content area that displays data or controls, and a footer with action buttons. Each component manages its own state or pulls from a shared context if multiple components need the same data.

Keep your bundle size small. The popup loads fresh every time the user clicks the extension icon, so a bloated bundle means a visible delay. Avoid importing large libraries when a lighter alternative exists. Tree shaking in Vite helps, but being intentional about your dependencies matters more.

Adding Type Safety with TypeScript

The biggest win TypeScript gives you in extension development is typed message passing. Extensions communicate between the popup, background service worker, and content scripts using Chrome's messaging API. Without types, these messages are just objects with no contract. You might send a message with an action field in the popup and check for a type field in the background, and the extension silently fails.

Define a set of message types as a TypeScript union. Each message type has a specific shape with required fields. When you send a message from the popup, TypeScript enforces that you include all required fields. When you receive a message in the background, TypeScript narrows the type based on the discriminant field so you can handle each message safely.

TypeScript also helps with the Chrome storage API. Define interfaces for the data you store and retrieve so you always know the shape of your persisted state. This eliminates an entire class of bugs where stored data drifts out of sync with the code that reads it.

Testing and Debugging Your Extension

Load your extension in Chrome by navigating to the extensions page and enabling developer mode. Click the load unpacked button and select your build output directory. Chrome will pick up your manifest and register the extension immediately.

Debugging a React extension involves multiple DevTools windows. Right-click your popup and select inspect to open DevTools for the popup context. The background service worker has its own DevTools link on the extensions management page. Content scripts are debugged through the DevTools of the page they are injected into. Each context runs independently, so console logs and breakpoints are scoped to their own window.

The most common gotcha is the service worker shutting down unexpectedly. Manifest V3 service workers are not persistent. They start when an event fires and stop when idle. If you store state in memory variables, that state disappears when the service worker restarts. Use the Chrome storage API instead of global variables for anything that needs to persist.

Publishing to the Chrome Web Store

Once your extension works locally and you have tested it across a few different websites, you are ready to publish. The Chrome Web Store review process has become stricter in recent years, so make sure your manifest only requests the permissions your extension actually uses. Overly broad permissions are the most common reason for rejection.

Write a clear and compelling store listing. Your title, description, and screenshots directly impact whether users click install. For a detailed walkthrough of the review process, read how to pass the Chrome Web Store review on your first try. To make sure your listing ranks well and converts visitors into users, see how to optimize your Chrome Web Store listing for maximum installs.

Start Building Faster

React and TypeScript give you the tools to build Chrome extensions that are maintainable, type-safe, and fast to iterate on. The initial setup takes a bit more effort than a vanilla JavaScript extension, but that investment pays off the moment you need to add a second feature or debug a message passing issue. If you want to skip the configuration entirely and start with a production-ready React and TypeScript extension template, ExtensionFast gives you the full stack out of the box so you can focus on building your product instead of wiring up build tools.