Webext Packages Overview — Chrome Extension Development

12 min read

Webext Packages Overview

A comprehensive comparison of the 8 core @theluckystrike/webext-* packages for building Chrome extensions. Each package provides typed, Promise-based wrappers for Chrome’s extension APIs.

Quick Comparison Table

Package Use When… Install
webext-storage You need typed Chrome storage with schema validation npm i @theluckystrike/webext-storage
webext-messaging You need type-safe message passing between contexts npm i @theluckystrike/webext-messaging
webext-tabs You work with browser tabs frequently npm i @theluckystrike/webext-tabs
webext-permissions You need runtime permission management npm i @theluckystrike/webext-permissions
webext-action You need to control the extension toolbar icon npm i @theluckystrike/webext-action
webext-alarms You need scheduled/periodic tasks npm i @theluckystrike/webext-alarms
webext-badge You need to show notification badges npm i @theluckystrike/webext-badge
webext-notifications You need rich browser notifications npm i @theluckystrike/webext-notifications

webext-storage

Best for: Persisting extension settings, user preferences, and cached data with full TypeScript support.

npm install @theluckystrike/webext-storage

When to Use

Key Features

Basic Usage

import { defineSchema, createStorage } from '@theluckystrike/webext-storage';

const schema = defineSchema({
  settings: {
    theme: 'light' as string,
    notifications: true as boolean,
  },
  user: {
    name: '' as string,
    lastLogin: 0 as number,
  }
});

const storage = createStorage(schema);

await storage.get('settings'); // { theme: 'light', notifications: true }
await storage.set('settings', { theme: 'dark' });

storage.watch('settings', (changes) => {
  console.log('Settings changed:', changes);
});

webext-messaging

Best for: Type-safe communication between background scripts, content scripts, and popups.

npm install @theluckystrike/webext-messaging

When to Use

Key Features

Basic Usage

import { createMessenger } from '@theluckystrike/webext-messaging';

type Messages = {
  getUser: { request: void; response: { id: string; name: string } };
  updateUser: { request: { name: string }; response: { success: boolean } };
  ping: { request: void; response: 'pong' };
};

// In background script
const backgroundMessenger = createMessenger<Messages>('background');

backgroundMessenger.on('getUser', async () => {
  return { id: '123', name: 'Alice' };
});

backgroundMessenger.on('updateUser', async ({ name }) => {
  await saveUser(name);
  return { success: true };
});

// In content script
const contentMessenger = createMessenger<Messages>('content');
const user = await contentMessenger.send('getUser');

webext-tabs

Best for: Querying, managing, and manipulating browser tabs in your extension.

npm install @theluckystrike/webext-tabs

When to Use

Key Features

Basic Usage

import { 
  getActiveTab, 
  getTabsByUrl, 
  closeTabs,
  createTab 
} from '@theluckystrike/webext-tabs';

// Get the currently active tab
const activeTab = await getActiveTab();

// Find all tabs matching a URL pattern
const youtubeTabs = await getTabsByUrl('*://*.youtube.com/*');

// Create a new tab
const newTab = await createTab('https://example.com');

// Close multiple tabs
await closeTabs([tab1.id, tab2.id]);

// Listen for tab events
import { onTabCreated, onTabUpdated, onTabClosed } from '@theluckystrike/webext-tabs';

onTabCreated((tab) => {
  console.log('New tab created:', tab.url);
});

webext-permissions

Best for: Managing runtime permissions — checking, requesting, and removing permissions dynamically.

npm install @theluckystrike/webext-permissions

When to Use

Key Features

Basic Usage

import { 
  hasPermission, 
  requestPermission, 
  getPermissionDescription 
} from '@theluckystrike/webext-permissions';

// Check if permission is already granted
const hasAccess = await hasPermission('tabs');

// Get human-readable description
console.log(getPermissionDescription('activeTab'));
// → "Access the tabs when you click the extension"

// Request a permission
const granted = await requestPermission('tabs');
if (granted) {
  console.log('Permission granted!');
}

// Check multiple permissions
const needed = ['storage', 'activeTab', 'scripting'];
const hasAll = await Promise.all(needed.map(hasPermission));

webext-action

Best for: Controlling the extension’s toolbar icon (action) — setting badge, popup, icon, and title.

npm install @theluckystrike/webext-action

When to Use

Key Features

Basic Usage

import { 
  setIcon, 
  setBadge, 
  setTitle, 
  setPopup,
  openPopup,
  onActionClicked 
} from '@theluckystrike/webext-action';

// Set icon
await setIcon({ path: 'icons/icon-48.png' });

// Set badge (shows on toolbar)
await setBadge({ text: '5', color: '#FF0000' });

// Set tooltip title
await setTitle({ title: 'My Extension - 5 unread' });

// Open popup programmatically
await openPopup();

// Handle icon click (when no popup is set)
onActionClicked.addListener((tab) => {
  console.log('Icon clicked on tab:', tab.id);
});

webext-alarms

Best for: Scheduling periodic tasks in your extension background service worker.

npm install @theluckystrike/webext-alarms

When to Use

Key Features

Basic Usage

import { 
  createAlarm, 
  getAlarm, 
  getAllAlarms, 
  clearAlarm,
  onAlarmFired 
} from '@theluckystrike/webext-alarms';

// Create a periodic alarm (minimum 1 minute in Chrome)
await createAlarm({
  name: 'data-sync',
  delayInMinutes: 15,  // Or use periodInMinutes for repeating
  periodInMinutes: 15
});

// Get specific alarm
const alarm = await getAlarm('data-sync');

// Listen for alarm
onAlarmFired.addListener((alarm) => {
  if (alarm.name === 'data-sync') {
    syncData();
  }
});

// Clear when done
await clearAlarm('data-sync');

webext-badge

Best for: Showing small text overlays on the extension icon — notification counts, status indicators.

npm install @theluckystrike/webext-badge

When to Use

Key Features

Basic Usage

import { 
  setBadge, 
  getBadge, 
  clearBadge,
  setBadgeColor 
} from '@theluckystrike/webext-badge';

// Set badge with count
await setBadge({ text: '12' });

// Set badge with color
await setBadge({ text: '3', color: '#FF5733' });

// Per-tab badge
await setBadge({ text: '5', tabId: 123 });

// Clear badge
await clearBadge();

// Get current badge
const current = await getBadge();

webext-notifications

Best for: Rich browser notifications with interactive buttons, icons, and click handlers.

npm install @theluckystrike/webext-notifications

When to Use

Key Features

Basic Usage

import { 
  createNotification, 
  updateNotification,
  clearNotification,
  onNotificationClicked,
  onNotificationButtonClicked
} from '@theluckystrike/webext-notifications';

// Create basic notification
await createNotification({
  type: 'basic',
  iconUrl: 'icons/notification.png',
  title: 'New Message',
  message: 'You have 3 new messages',
  priority: 1
});

// Create with action buttons
await createNotification({
  type: 'basic',
  title: 'Download Complete',
  message: 'file.zip has been downloaded',
  buttons: [
    { title: 'Open File' },
    { title: 'Show in Folder' }
  ]
});

// Handle clicks
onNotificationClicked.addListener((notificationId) => {
  console.log('Notification clicked:', notificationId);
});

onNotificationButtonClicked.addListener((notificationId, buttonIndex) => {
  if (buttonIndex === 0) {
    openFile();
  }
});

Which Package Should You Use?

Scenario Recommended Package
Store user settings webext-storage
Store app state webext-storage + webext-reactive-store
Background ↔ Content communication webext-messaging
Popup ↔ Background communication webext-messaging
Work with browser tabs webext-tabs
Request permissions on demand webext-permissions
Toolbar icon control webext-action
Show notification count webext-badge
Schedule background tasks webext-alarms
Rich user notifications webext-notifications

Bundle All Eight

If you need all eight packages, consider the meta-package:

npm install @theluckystrike/chrome-extension-toolkit

This installs all core webext packages plus additional utilities in one command.


No previous article
No next article