Skip to content

About

Organize your tabs effortlessly with Tabs Pin! Quickly pin favorite sites, prevent duplicates, create personalized workspaces, and boost your productivity with a sleek, customizable, and privacy-focused pinned tab manager.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Tabs Pin: Pinned Tabs Manager for Firefox & Chrome

Tabs Pin logo

Install for Firefox Chrome Web Store CI Latest release License: GPL-3.0

Save the sites you always keep pinned, sort them into categories, and reopen them all in one click, pinned and without duplicates. Manifest V3, 100% local storage, no account, no tracking.

Contents

Features

  • One-click launch: open every saved site as a pinned tab, or only one category.
  • No duplicates: a site already open is left alone; open but unpinned, it is pinned instead of reopened. Matching ignores tracking parameters, parameter order, http/https and www. (so a tab still matches after the site redirected it), but keeps what identifies a page (?v= on YouTube, ?q=, ?id=, single-page-app routes like #/inbox…). The same address cannot be saved twice.
  • Pin the current tab from the popup, into the category of your choice.
  • Categories: rename them and pick an emoji icon; close all pinned tabs of a category at once (with confirmation). Tabs of a removed category move to the first one.
  • Reorder tabs by drag and drop, or with the ↑ / ↓ buttons (keyboard friendly).
  • Import / export your configuration as JSON.
  • 14 languages: Arabic, Chinese, Dutch, English, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Portuguese, Russian, Spanish.
  • Accessible: full keyboard use, focus kept in place after actions, screen-reader labels and announced messages, right-to-left layout for Arabic, dark mode, high-contrast and reduced-motion preferences respected.

Installation

Browser Store Minimum version
Firefox addons.mozilla.org 115 (ESR)
Chrome / Chromium Chrome Web Store 104

Each GitHub release also provides the Firefox and Chrome packages as .zip files.

Usage

  1. Click the Tabs Pin icon in the toolbar.
  2. Pin current tab saves the page you are on (you choose its category), or open Options to add, edit and reorder sites.
  3. Open N tabs opens everything; click a category to open only its sites.
  4. The Close button of a category closes, after confirmation, the pinned tabs of the current window whose site (domain) matches one of the category's saved sites.

Privacy & permissions

Permission Why
tabs Read the addresses of open tabs, to avoid duplicates and pin / close them
storage Keep your sites, categories and settings in the browser's local storage
activeTab Read the current tab when you pin it
  • 100% local storage: your sites, categories and settings are stored only in your browser (storage.local) and never sent anywhere: no account, no sync server, no analytics.
  • Site icons (display only, nothing is stored remotely): to show the favicon of a saved site, the popup and options page request it from Google's and DuckDuckGo's favicon services, then from the site itself. These requests contain the site's domain name (not the full address).

Backup format

Options → Export downloads a JSON file:

{
  "tabs": [
    { "id": "tab_…", "url": "https://example.com/", "title": "Example",
      "category": "work", "enabled": true, "order": 0, "dateAdded": "2026-01-01T00:00:00.000Z" }
  ],
  "categories": [{ "id": "work", "name": "Work", "icon": "💼" }],
  "settings": { "lastOpened": "2026-01-01T00:00:00.000Z", "categoriesLocalized": true },
  "exportDate": "…",
  "version": "1.4.2"
}

On import, the file replaces the current tabs and categories. It is validated first: entries without an http(s) address and unnamed categories are dropped, a missing icon becomes 📁, tabs of an unknown category go to the first one, duplicate IDs are fixed, only a valid past lastOpened date is kept from the settings, and the number of skipped tabs is reported.

Development

Requirements: Node.js ≥ 20.11 (see .nvmrc), Firefox and/or Chromium.

git clone https://github.com/alexandre-leng/Tabs-Pin-Manager-Extension.git
cd Tabs-Pin-Manager-Extension
npm ci
Command What it does
npm run dev:firefox Runs Firefox with the extension, reloaded on every change
npm run dev:chrome Stages build/chrome/: load it as an unpacked extension (run again after changes)
npm run build Builds both packages into web-ext-artifacts/ (build:firefox / build:chrome for one)
npm test Unit tests (Jest)
npm run test:e2e Interface tests (Playwright): loads the real extension in Chromium, drives the popup and options page, runs an axe-core accessibility audit. Run npx playwright install chromium once first
npm run lint web-ext lint (Firefox add-on rules)
npm run lint:js / npm run lint:css ESLint / Stylelint

manifest.json is shared and never modified: every command copies the extension into build/<browser>/ with the browser-specific manifest (scripts/prepare-manifest.js). CI runs all the checks above on every push and pull request.

Architecture

Native ES modules, no bundler: each context has one entry module and every dependency is an explicit import.

Context Entry Modules
Background (Firefox event page / Chrome service worker) background/background.js controller.js (events, messages), data-store.js (saved data, one change at a time), tab-actions.js (open / pin / close tabs), import-sanitizer.js, log.js
Popup popup/main.js popup.js (PopupManager), category-list.js, category-order.js, category-selection.js, tab-actions.js
Options page options/main.js options.js (OptionsManager), tab-cards.js, tab-editor.js, tab-ordering.js, category-editor.js, icon-picker.js, import-export.js
Shared lib/ browser-api.js, storage-manager.js, url-utils.js, tab-utils.js, domain-utils.js, punycode.js (display of international domains), time-format.js, ui-utils.js, i18n-helper.js, default-categories.js, mixins.js
  • The background script owns the data: pages change it only through messages (openAllTabs, openCategoryTabs, countCategoryPinnedTabs, closeCategoryTabs, saveTab, deleteTab, reorderTabs, saveCategories, importAllData) and read it with getTabsData (the popup reads storage directly only if the background does not answer). The background broadcasts a dataChanged message after each change.
  • On install, default categories are created in the browser language; on update, migrate() translates them once (settings.categoriesLocalized), fills missing tab fields and moves tabs of unknown categories to the first one.
  • Page features are plain objects of methods composed into the page class with mixin(), which throws if two features define the same method.
  • tests/module-graph.test.js checks that every import resolves and no module is unused; tests/locales.test.js checks that every translation key used exists in every language.

Releasing

  1. Bump the version in package.json and manifest.json (a test checks they match).
  2. Move the Unreleased notes of CHANGELOG.md under ## [x.y.z] - date.
  3. Push to main, then run the Release workflow (Actions → Release → Run workflow): it tests, builds both packages and publishes the GitHub release with the changelog section as notes.

Support

License

GPL-3.0. Developed by Alexandre.

About

Organize your tabs effortlessly with Tabs Pin! Quickly pin favorite sites, prevent duplicates, create personalized workspaces, and boost your productivity with a sleek, customizable, and privacy-focused pinned tab manager.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages