Browser extensions - Popup extension


Creating our very first extension that has a popup action

17 Aug, 2022 · 5 min read

We have already had quite the exposure to browser extensions so far and looked at the following items:

This article will look at how we can set up a popup extension. This extension pops up when you click on the icon in your toolbar.

The result for today will be this popup extension showing our React app in the dropdown.

Browser pop up extension

Setting up the popup extension

First, create the new project and navigate to it.

mkdir popup-extension && cd popup-extension

Then let’s initialize a new node project.

npm init -y

Now we can start adding the packages we need.

npm i react react-dom tailwindcss vite

And the dev dependencies we’ll use.

npm i -D @vitejs/plugin-react postcss-cli

Let’s start by initializing the Taiwlidn config.

npx tailwind init

This will create a tailwind.config.js file, where you can place the following config.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['src/*.jsx'],
  theme: {
    extend: {},
  variants: {
    extend: {},
  plugins: [],

Let’s also add a .postcssrc.json file to our project’s root.

  "plugins": {
    "tailwindcss": {}

The Tailwind config’s last step is to add a css folder with a style.css file inside.

@tailwind base;
@tailwind components;
@tailwind utilities;

Then we also want a Vite config file called vite.config.js.

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],

Also, open up your package.json and add the following scripts.

"scripts": {
	"dev": "vite",
	"build": "vite build",
	"preview": "vite preview"

Creating the public assets and manifest

Extensions work based on the manifest file to run it in our build. We can create a public folder.

Create another folder called icons and put your extension icons there. (or use mine from the GitHub project). Also, put a file called manifest.json inside.

  "manifest_version": 3,
  "version": "1.0",
  "name": "Popup Extension",
  "description": "A demo popup experience",
  "action": {
    "default_icon": "icons/icon-48.png",
    "default_popup": "index.html"
  "icons": {
    "48": "icons/icon-48.png"

Now, if we create this index.html file at the root of our project, we should be ready to try it out.

<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>DDT Popup</title>
    <link rel="stylesheet" type="text/css" href="./css/style.css" />
    Hello world 👋

If you now build and install the plugin, following these directions, you should be able to add it to your browser.

Pop up extension first version

As you can see in the screenshot above, it looks relatively small and unstyled. It also has no interactivity. Let’s change that by adding some Tailwind and React.

Adding Tailwind and React, a popup extension

We already loaded all the needed configurations, so let’s start by converting our plain HTML into a React app.

In your index.html, replace the body with the following contents.

  <div id="app"></div>
  <script type="module" src="src/index.jsx"></script>

Now we’ll have to create an src directory, which will be the main entry point for our React application.

Inside this directory, start by adding an index.jsx file.

import ReactDOM from 'react-dom';
import { App } from './App';

const app = document.getElementById('app');
ReactDOM.render(<App />, app);

This is our basic React init and injects React into our app. Let’s create this App component by adding an App.jsx file.

import Counter from './Counter';

export function App() {
  return (
    <div className='flex flex-col items-center justify-center w-screen h-screen bg-indigo-400 text-6xl font-bold text-white'>
      <p>Welcome 👋</p>
      <br />
      <Counter />

As you can see, this also renders a Counter component responsible for some interactions. Let’s create that one as well: Counter.jsx.

import { useState } from 'react';

export default function Counter() {
  const [counter, setCounter] = useState(0);
  const increase = () => setCounter((count) => count + 1);
  const decrease = () => setCounter((count) => count - 1);
  return (
      <button onClick={decrease}>-</button>
      <span className='px-4'>{counter}</span>
      <button onClick={increase}>+</button>

As you can see, throughout these components, we also introduced some Tailwind classes that should take care of the styling.

Let’s build our app again and try it out in the browser.

React and styled component

It looks to be there, but our app is super narrow, and we can’t see much! Let’s fix that by making our main popup a fixed size. Open up the style.css file and add the following line.

#app {
  width: 350px;

Now build the app again and try it out.

Browser pop up extension

You can find the complete code on GitHub.

Thank you for reading, and let’s connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Spread the knowledge with fellow developers on Twitter
Tweet this tip
Powered by Webmentions - Learn more

Read next 📖

Browser extensions - recap and status

1 Sep, 2022 · 2 min read

Browser extensions - recap and status

Browser extensions - DevTools extension

31 Aug, 2022 · 2 min read

Browser extensions -  DevTools extension

Join 2098 devs and subscribe to my newsletter