Build a Tab Grouper Chrome Extension with Plasmo: A Step-by-Step Guide

Introduction

Chrome extensions are lightweight tools that enhance your browsing experience—from managing passwords to organizing tabs. While building one from scratch can involve complex setup, the Plasmo framework simplifies the process, letting you focus on core functionality. In this guide, you'll create a Tab Grouper extension that automatically groups tabs by domain using TypeScript, React, and Plasmo. No prior extension experience needed—just basic React and TypeScript knowledge.

Build a Tab Grouper Chrome Extension with Plasmo: A Step-by-Step Guide
Source: www.freecodecamp.org

What You Need

Step-by-Step Instructions

Step 1: Scaffold the Project

Open your terminal and run:

plasmo init tab-grouper
cd tab-grouper

This creates a new directory with TypeScript, React, and a basic manifest.json already configured. Plasmo reads your package.json and generates the manifest automatically—you never edit it directly. The project includes a popup.tsx file and a background folder where you'll add scripts.

Step 2: Understand the Extension Structure

Chrome extensions consist of:

For the Tab Grouper, you'll use the background script to handle tab creation and grouping, and the popup to trigger the action.

Step 3: Build the Background Script

Inside src/background, create a file index.ts. This script listens for messages from the popup and performs the grouping logic. Add:

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'groupTabs') {
    groupTabsByDomain();
  }
});

async function groupTabsByDomain() {
  const tabs = await chrome.tabs.query({ currentWindow: true });
  const domainMap: Record = {};

  for (const tab of tabs) {
    if (!tab.url || !tab.id) continue;
    const url = new URL(tab.url);
    const domain = url.hostname;
    if (!domainMap[domain]) domainMap[domain] = [];
    domainMap[domain].push(tab.id);
  }

  for (const [domain, tabIds] of Object.entries(domainMap)) {
    if (tabIds.length > 1) {
      await chrome.tabs.group({ tabIds });
      await chrome.tabGroups.update((await chrome.tabs.group({ tabIds })).groupId, {
        title: domain,
        color: 'blue'
      });
    }
  }
}

This script queries all tabs in the current window, groups tabs sharing the same domain, and assigns a color. Note: in a real implementation you'd handle errors and color cycling.

Step 4: Create the Popup UI

Open src/popup.tsx and replace the default content with a simple button:

import { sendToBackground } from '@plasmohq/messaging';

export default function Popup() {
  const handleGroup = async () => {
    await sendToBackground({ name: 'groupTabs' });
  };

  return (
    

Tab Grouper

); }

Plasmo's sendToBackground utility sends a message to the background script. Make sure the message name matches the listener in the background script.

Build a Tab Grouper Chrome Extension with Plasmo: A Step-by-Step Guide
Source: www.freecodecamp.org

Step 5: Test the Extension Locally

In your terminal, run:

plasmo dev

This starts a development server that rebuilds on changes. Open Chrome and go to chrome://extensions. Enable Developer mode, click Load unpacked, and select the build/chrome-mv3-dev folder (or whatever path Plasmo outputs). The extension should appear in your toolbar. Open several tabs from different sites, click the extension icon, then click Group Tabs – your tabs will be grouped by domain.

Step 6: Add Polish and Error Handling

To make the extension robust, consider:

For example, to cycle colors, define an array ['red','orange','yellow','green','blue','purple'] and increment an index per domain.

Step 7: Prepare for Publishing

When you're ready to publish:

Tips for Success

With these steps, you've built a fully functional Chrome extension using Plasmo. Now you can extend it with additional features or create entirely new extensions!

Recommended

Discover More

Building Financial Products That Last: Moving from MVP to BedrockBreaking: Ubuntu 26.04 LTS Streamlines Pro Activation by Moving Settings to Security Center10 Critical Facts About the FakeWallet Crypto Stealer Infiltrating Apple's App StoreMalicious Ruby Gems and Go Modules Target CI/CD Pipelines in Sophisticated Supply Chain AttackCompare AI Models Instantly: ChatPlayground AI Q&A