Grabbit is a powerful Chrome Extension (Manifest V3) that enables users to select multiple links on a webpage using a customizable drag-select interface. Users can perform various actions on selected links, such as opening them in new tabs/windows or copying their URLs to the clipboard.
Available on the Chrome Web Store
This project is tested with BrowserStack
- Drag-Select: Intuitive visual selection box.
- Custom Actions: Configurable mouse/keyboard combinations including A-Z keys (e.g., G + Right Click to Copy).
- Adaptive Smart Selection: Intelligent pattern-based filtering that automatically detects and selects consistent groups of links (e.g., repeating video titles, grid items) while ignoring clutter.
- Linkify: Automatically converts plain text URLs on web pages into clickable links. Includes an Aggressive Mode for domain-only recognition (e.g.,
google.com) and support for links inside code blocks. - Exclusion Filters: Global keyword and Regular Expression (Regex) filtering to automatically skip unwanted links during drag-selection. Manageable via a dynamic tag-based UI.
- Disabled Domains: Blocklist feature to completely disable Grabbit (Selection, Linkify, Visited tracking) on specific domains. Includes a visual "OFF" badge and a popup overlay with an "Enable" button.
- Options Page: Extensive customization for colors, behavior, and granular filtering rules.
- Enhanced Copy Formatting: Expanded "Copy URLs with Titles" action with support for Markdown, JSON, and customizable separators (Comma, Dot, Tab, etc.).
- Create Bookmarks: Select multiple links and instantly save them as bookmarks in a folder named after the current page title.
- Advanced Options: Dedicated section for power-user features. Now includes animated toggle switches, a dynamic UI that adapts to selected features, and a robust filter/domain management system.
- Configurable "Mark as Visited": (New) Per-action setting in Advanced Options to visually mark links as visited (purple) in the browser.
- Dynamic Link Detection: (New) Automatically detects and allows selection of new links that appear during a drag (e.g., from infinite scroll or lazy loading).
- Duplicate Link Highlighter: (New) Visually identifies links with the same URL on a page using unique colored underlines. Helps in finding repetitive content and managing navigation.
- AI Product Comparison: (New) Select multiple product tabs and generate a comprehensive AI-powered comparison table with a clear winner, pros/cons, and feature breakdown.
- AI Article Summarization: (New) Summarize articles and blog posts with AI-generated key takeaways, topic tags, and bottom line analysis.
- AI YouTube Video Summarization: (New) Summarize YouTube videos with chapter-by-chapter breakdowns, key points, and detailed summaries for each section. Automatically extracts transcripts and creates intelligent chapter markers.
- Modern Architecture: Refactored into a modular structure for better maintainability and performance.
The project is built using standard web technologies and the Chrome WebExtensions API. It does not require a build step (no Webpack/Rollup) and runs directly as an unpacked extension.
Frontend (Chrome Extension)
├── Content Scripts (injected into webpages)
│ ├── Event handling (drag selection, mouse/keyboard)
│ ├── UI rendering (selection box, counter label)
│ ├── Business logic (collision detection, link processing)
│ └── Special features (linkify, visited tracking, smart selection)
├── Background Service Worker (privileged operations)
│ ├── Tab/window management
│ ├── Bookmark creation
│ ├── Clipboard operations
│ ├── Payment integration (ExtPay)
│ └── AI features coordination (comparison, summarization)
├── Options Page (settings UI)
│ ├── Action management (create/edit/delete actions)
│ ├── Advanced options (filters, disabled domains, linkify)
│ ├── Popup customization (button order, visibility)
│ └── Format preview (copy formatting)
├── Popup (quick actions)
│ ├── Tab management (copy/open URLs)
│ └── AI feature triggers (compare, summarize)
└── AI Features Pages
├── Product Comparison (AI Features/compare/)
└── Article Summarization (AI Features/summarize/)
└── YouTube Video Summarization (AI Features/youtube-summary/)
Backend (Supabase Infrastructure)
├── Secure Edge Functions (OpenRouter API)
├── Stripe integration (payment validation)
├── Rate limiting (monthly quotas with automatic reset)
└── User management (subscribers, usage tracking, RLS policies)
- User Action: Content scripts detect mouse/keyboard input on webpages
- Event Processing:
grabbit.jsorchestrates event handling through modular components - Action Execution: For privileged operations (tabs, bookmarks), messages sent to
background.js - AI Features: Comparison data sent through Supabase Edge Functions (API keys never exposed to client)
- Result Display: UI components render feedback (selection box, success messages, comparison tables)
- Settings Management: Options pages use modular components (sidebar, footer) with auto-initialization
- Popup Actions: Popup loads configuration from storage, renders buttons based on user preferences
- Premium Features: ExtPay validates subscription, backend enforces rate limiting
- JavaScript (Vanilla): Core logic, utilizing ES6+ features.
- HTML/CSS: UI for Popup and Options pages. Leveraging CSS Variables for a centralized design system.
- Chrome APIs:
storage,tabs,windows,clipboard,scripting,bookmarks. - Manifest V3: Adheres to the latest Chrome extension security and background service worker requirements.
- Backend (Supabase): Secure server-side infrastructure for database persistence, user authentication, and Edge Functions handling AI requests and Stripe integration.
- AI: OpenRouter API for product comparison, article summarization, and YouTube video summarization.
- Payments: ExtPay (Chrome extension payment platform), Stripe API.
manifest.json: The entry point. Defines permissions, background scripts, and the order of content script injection.css/: Global styles and design tokens.variables.css: Single Source of Truth for design tokens (colors, gradients, fonts, shadows, transitions).options.css: Main layout and component styles for the settings page.sidebar.css: Styles for the navigation sidebar.
popup/: The small window that appears when clicking the extension icon.popup.html: Structure of the popup, featuring a Modern Glassmorphism design.popup.js: Logic for quick actions (e.g., "Copy all tabs"). Handles dynamic success states for nested button elements.popup.css: Complete Redesign featuring animated background orbs, dark glassmorphism cards, and gradient icon boxes. Standardized using global variables.
options.html/js/options/: The full settings page for configuring actions and appearance, now refactored into ES modules.- Advanced Options: Dedicated sub-page for power-user settings.
advancedOptions.html: Layout for experimental features including Linkify, Exclusion Filters, and Disabled Domains.advancedOptions.js: Logic for saving/loading advanced settings, managing the exclusion filter list, and the domain blocklist.advancedOptions.css: Specific styling for advanced controls (toggle switches, filter tags).
AI Features/compare/: (New) Standalone page for AI-powered product comparisons.compare.html: Comparison page structure.compare.js: Logic for comparison workflow and UI.compare.css: Premium Glassmorphism styling.
AI Features/summarize/: (New) Standalone page for AI-powered article summarization.summarize.html: Summary page structure.summarize.js: Logic for summarization workflow and UI.summarize.css: Premium Glassmorphism styling.
AI Features/youtube-summary/: (New) Standalone page for AI-powered YouTube video summarization.youtube-summary.html: YouTube summary page structure with loading states and chapter-by-chapter result views.youtube-summary.js: Logic for YouTube summarization workflow, handles transcript extraction via InnerTube API, and renders chapter summaries.youtube-summary.css: Premium Glassmorphism styling specific to the YouTube summary interface.
wordpress-plugin/: Server-side backend code.grabbit-backend.php: Secure proxy and user management plugin.README.md: Backend setup guide.
js/linkify.js: (New) Scans the page for plain text URLs and converts them to clickable<a>tags if enabled.js/visited.js: (New) Handles persistent tracking and visual marking of visited links to bypass browser redirect limitations.
The options page has been refactored from a single monolithic file into multiple ES modules, improving code reuse and testing:
main.js: Orchestrates initialization.env.js: Environment constants (OS detection, Extension context).storage.js: Handles saving/loading actions tochrome.storage.sync.utils.js: Helpers for colors, key labels, and tooltips.preview.js: Live format preview for "Copy URLs & Titles".card.js: Component for managing action cards.modal.js: Manages the "Add/Edit Action" modal lifecycle.popup-config.js: Popup button management and drag-and-drop reordering.
The order in manifest.json → content_scripts → js is critical. Scripts share a global scope:
js/state.js- MUST LOAD FIRST - DefinesGrabbitStateglobal object andCONSTANTSjs/utils.js- Helper functions used by other modulesjs/ui.js- DOM manipulation functionsjs/visited.js- Visited link trackingjs/smart-select.js- Adaptive pattern-based selectionjs/logic.js- Core business logicjs/linkify.js- Text-to-link conversionjs/duplicate-highlighter.js- Duplicate link highlightingjs/grabbit.js- MUST LOAD LAST - Main entry point and event orchestrator
Never reorder these scripts without understanding dependencies. Many modules reference GrabbitState or functions from earlier-loaded scripts.
The project uses a "No Build Step" CSS architecture that leverages modern browser features to maintain a clean and scalable codebase.
All design tokens are defined in the :root pseudo-class within variables.css. This file acts as the single source of truth for:
- Color Palette: Integrated primary/secondary colors and status colors (success, warning, error).
- Gradients: Standardized linear gradients for buttons, backgrounds, and the sidebar.
- Typography: A unified font stack across all extension pages.
- Shadows & Transitions: Consistent depth and motion tokens.
To maintain separation of concerns and benefit from caching, styles have been extracted from popup.html into popup.css. The popup has been completely redesigned with a premium aesthetic:
- Glassmorphism: Using
backdrop-filterand semi-transparent backgrounds for a modern "frosted glass" look. - Animated Components: Decorative floating background orbs and pulsing logo glows for a living UI.
- Visual Hierarchy: Buttons now feature distinct icon boxes with custom gradients, primary titles, and descriptive subtitles.
- Dynamic States: Success states are handled gracefully with color transitions and content updates via JavaScript.
Styles are organized by component area (Options, Sidebar, Popup), each inheriting variables from the global pool. This allows for rapid UI adjustments without global "find and replace" operations.
js/grabbit.js - Main Entry Point & Event Orchestrator
- Initializes by loading saved actions from
chrome.storage.sync - Core event listeners:
mousedown(start tracking),mousemove(check 5px drag threshold),mouseup(finalize selection),keydown(modifiers/ESC),window.blur(cleanup) - Delegates specific logic to specialized modules
- Activates selection UI only after 5px drag threshold (prevents accidental selections)
js/state.js - State Management
GrabbitState: Global state object (mouse position, selection status, cached links, active modifiers, filters)CONSTANTS: Drag threshold (5px), scroll speed, link refresh interval (500ms for infinite scroll), debounce delays
js/logic.js - Core Business Logic
updateSelectionBox(): Calculates geometry relative to documenthandleScroll(mouseY): LinkClump-style auto-scrolling near viewport edgesisLinkExcluded(url): Checks URLs against keyword/regex filtersupdateSelectedLinks(): Collision detection, Smart Select orchestration, exclusion filteringprocessSelectedLinks(matchedAction): Executes actions (open/copy/bookmark) with deduplication and formatting
js/ui.js - DOM & Visuals
createSelectionBox(): Absolute-positioned selection overlaycreateCounterLabel(): Floating status label with action textupdateVisualStyles(): Syncs box colors, border styles, counter textcleanupSelection(): Removes UI, resets state, clears intervals
js/utils.js - Helper Functions
getOS(): Cross-platform OS detectioncheckKeyCombination(e, mouseButton): Matches input against saved actionsgetMouseButton(e): Normalizes mouse button codesisElementSticky(element): Collision detection helper for sticky headersisDomainDisabled(disabledDomains): Checks current domain against blocklistdebounce(func, wait): Performance wrapper for high-frequency eventsgetAllLinks(root): Deep link discovery including Shadow DOM traversal
js/smart-select.js - Adaptive Pattern-Based Selection
apply(linksInBox): Analyzes links in selection, builds frequency map of signaturesgetLinkSignature(link, style): Generates unique signature based on structure, tag name, font weight/sizeisLinkImportant(link, style): Heuristic engine for semantically/visually important links (headings, bold)- Filters selection to repeating patterns (count >= 2), prioritizing "important" links
js/visited.js - Persistent Visited State Management
- Bypasses privacy restrictions (e.g., Google Search redirects) using
chrome.storage.local injectGrabbitVisitedStyles(): Injects CSS for.grabbit-visitedclassapplyGrabbitVisitedStyling(): Restores visited styling on page loadmarkLinksAsGrabbitVisited(urls, anchorElements): Persists and updates UI
js/linkify.js - Text-to-Link Conversion
- Regex engine for
http,https,ftp,wwwURLs - Aggressive Mode: Prefix-less domain recognition (e.g.,
github.com/user/repo) - DOM traversal: Recursive walk, skipping
<a>,<script>,<style>,<textarea> - Code block support: Includes
<code>and<pre>tags - Shadow DOM support: Handles URLs inside Shadow Roots
- Linkified elements get
.grabbit-linkifiedclass
js/duplicate-highlighter.js - Duplicate Link Highlighting
- Automatically highlights links that share the same URL on a page.
- Uses vibrant, unique colors for each group of duplicate links.
- Uses
MutationObserverto handle dynamic content (infinite scroll). - Supports Shadow DOM for deep link discovery.
- Respects domain blocklist and user settings.
js/background.js - Privileged API Bridge
chrome.runtime.onInstalled: Sets defaults on first runchrome.runtime.onMessage: Bridges content script requests to privileged APIstabs.create: Opens links in new tabswindows.create: Opens links in new windowsbookmarks.create: Creates bookmarks- Clipboard operations via
chrome.clipboard
updateIconState(tabId, url): Manages "OFF" badge for disabled domainscreateBookmarksInFolder(parentId): Recursive helper for batch bookmark creation- Coordinates AI comparison workflow with backend
js/options/main.js - Orchestrator
initialize(): Main entry pointsetupExtensionButtons(): Pin and Rate button logic
js/options/modal.js - Add/Edit Dialog
openModal()/closeModal(): Lifecycle managementhandleSaveAction(): Form validation and persistencesetupFormValidation(): Real-time UI feedbackupdateFormatOptionVisibility(): Dynamic UI toggling
js/options/card.js - Action Cards
createActionCard(action): Visual representation of saved actionsopenEditModal(action, card): Pre-populates modal for editing
js/options/preview.js - Format Preview
updateFormatPreview(): Live terminal-style preview for copy formattingsetupPreviewListeners(): Attaches change events
js/options/storage.js - Persistence
saveActionsToStorage(actions): Syncs tochrome.storage.syncloadActionsFromStorage(): Retrieves settings on load
js/options/env.js - Environment Detection
isExtension: Checks if running in Chrome extension contextcurrentOS: Cross-platform OS detection for UI customization
js/options/utils.js - Options Page Utilities
generateUniqueColor(): Assigns colors to action cards from predefined paletteupdateKeyLabels(): Updates modifier key labels based on OS (e.g., Command ⌘ on Mac)initializeTooltips(): Sets up fixed positioning for tooltipsisDuplicateCombination(): Validates for duplicate key+mouse combinations
js/options/popup-config.js - Popup Button Management
POPUP_BUTTONS: Registry of all popup buttons with metadataloadPopupConfig()/savePopupConfig(): Persist button order and enabled stateinitializePopupConfig(): Renders drag-and-drop button list- Drag-and-drop reordering with
setupDragAndDrop() - Toggle switches for enabling/disabling buttons
getButtonIcon(): Returns SVG HTML for button icons
AI Features/compare/compare.js - Comparison Workflow & UI
- Checks for pending comparison data from
chrome.storage.local runComparison(): Orchestrates 3-step process (Extract → Analyze → Build)- Communicates with
background.jsto trigger AI analysis - Handles error states (premium required, monthly limit reached)
renderResults(data): Builds Winner Banner, Products Grid, Features TableupdateStep(stepNumber): Progress tracker visualization
AI Features/summarize/summarize.js - Summarization Workflow & UI
- Checks for pending summary data from
chrome.storage.local runSummary(): Orchestrates summarization process (Extract → Summarize → Render)- Communicates with
background.jsto trigger AI analysis - Handles error states (premium required, monthly limit reached)
renderResults(data): Builds Summary Banner, Key Takeaways, Topics, Bottom Line
AI Features/youtube-summary/youtube-summary.js - YouTube Summary Workflow & UI
- Checks for pending YouTube summary data from
chrome.storage.local runSummary(): Orchestrates YouTube summarization process (Extract Transcript → Summarize → Render Chapters)- Communicates with
background.jsto trigger transcript extraction via YouTube InnerTube API - Handles error states (premium required, monthly limit reached, no transcript available)
renderResults(data): Builds Summary Banner, Key Points, Chapter-by-Chapter Breakdown with detailed summaries- Each chapter includes timestamp, short summary (2 sentences), and detailed summary (8-10 sentences)
popup/popup.js - Main Popup Script
- Loads popup configuration from
popup-config.js - Renders enabled buttons in configured order
- Copy Selected Tabs: Copies URLs of currently selected tabs
- Copy All Tabs: Copies all open tab URLs in current window
- Open Copied Links: Opens links from clipboard (one per line)
- Compare Products: Triggers AI product comparison workflow
- Summarize Page: Triggers AI article summarization workflow
- Premium badge display and ExtPay integration
- Glassmorphism UI with animated backgrounds
popup/popup.html - Popup Interface
- Glassmorphism design with animated background orbs
- Dynamic button rendering based on configuration
- Premium features with PRO badges
- Responsive layout for various screen sizes
popup/popup.css - Popup Styling
- Glassmorphism effects with backdrop-filter
- Animated gradient backgrounds and orbs
- Button hover effects and transitions
- Premium badge styling
- Inherits all design tokens from
css/variables.css
js/components/sidebar.js - Navigation Sidebar Component
GrabbitSidebarclass: Auto-initializing component- Renders navigation menu with links to Main Options, Popup Options, Advanced Options
- Handles active section highlighting and hash-based navigation
- Internal page section switching without page reload
js/components/footer.js - Footer Component
GrabbitFooterclass: Auto-initializing component- Renders footer with support links (PayPal, Revolut)
- Displays contributor list with GitHub links
- "Contribute on GitHub" callout button
- Handles rate and pin extension button functionality
js/premium.js - ExtPay Payment Manager
Premium.init(): Initializes ExtPay background servicePremium.getUser(): Returns payment status, email, trial statusPremium.openPaymentPage(): Opens ExtPay payment flowPremium.openLoginPage(): Opens ExtPay login for existing usersPremium.validateWithBackend(email): Validates license with Supabase backend- Syncs with ExtPay dashboard (extension ID:
grabbit-premium)
js/ExtPay.js - Third-Party Payment Library
- External ExtPay library for Chrome extension payments
- Handles subscription management, trial periods, payment processing
- Injected as content script on
extensionpay.comdomain - DO NOT MODIFY - External dependency
handleYouTubeSummary() - YouTube Video Summarization Orchestrator
- Verifies premium status and fetches API token
- Extracts YouTube video data via
extractYouTubeDataFromPage()using InnerTube API - Sends transcript and metadata to Supabase Edge Function
/youtube-summaryendpoint - Handles monthly quota limits and error states (no captions, subscription inactive)
- Returns structured chapter-by-chapter summary with timestamps and detailed summaries
extractYouTubeDataFromPage() - YouTube Data Extraction (Injected Function)
- Executed in MAIN world to access YouTube's
window.ytcfgobject - Extracts:
- Video title from
h1.ytd-video-primary-info-renderer - Channel name from channel element
- Chapters from video player or description (timestamp pattern matching)
- InnerTube API key for authenticated requests
- Video title from
- InnerTube Player API Call:
- Uses ANDROID client (bypasses restrictions)
- Fetches caption tracks in JSON3 format
- Prefers English captions, falls back to first available
- Transcript Processing:
- Inserts timestamp markers every 30 seconds for AI chapter accuracy
- Formats timestamps as
[MM:SS]or[HH:MM:SS] - Limits to 60,000 characters for long videos
- Stores video duration for validation
- Error Handling: Returns structured error object if transcript unavailable
handleArticleSummary() - Article Summarization Orchestrator
- Verifies premium status and fetches API token
- Extracts article content via
extractArticleDataFromPage() - Sends to Supabase Edge Function
/summarizeendpoint - Handles monthly quota limits and subscription validation
- Returns structured summary with key takeaways and topics
handleProductComparison() - Product Comparison Orchestrator
- Verifies premium status and fetches API token
- Extracts product data from multiple tabs via
extractProductDataFromPage() - Sends to Supabase Edge Function
/compareendpoint - Handles monthly quota limits and subscription validation
- Returns structured comparison with winner, pros/cons, and feature tables
getApiToken() - API Token Management
- Caches API token in
chrome.storage.localto reduce backend requests - Fetches token from
/get-tokenendpoint with email authentication - Throws descriptive errors with status codes and details
- Used by all AI feature handlers for authenticated requests
js/content-extractor.js - Product Content Extractor
extractProductData(): Intelligently extracts product information for AI comparison- Title Extraction: H1, product-title selectors, OG meta tags, document.title fallback
- Price Extraction: Multiple selector strategies (Amazon
.a-price-whole,.pdp-price, etc.) - Description Extraction: Product descriptions, meta descriptions, feature bullets (Amazon)
- Specs Extraction: Tables, definition lists, spec containers (limited to 5 blocks)
- Returns structured object with title, price, description, specs, URL, site name
- Used via
scripting.executeScriptin background.js for AI features
advancedOptions/advancedOptions.js - Advanced Settings Management
- Linkify Settings: Toggle linkify on/off, aggressive mode toggle
- Exclusion Filters: Add/remove keyword/regex patterns to filter out links
- Disabled Domains: Blocklist for domains where Grabbit should not activate
- Real-time validation, duplicate checking, status messages
- Persists all settings to
chrome.storage.sync
advancedOptions/advancedOptions.html - Advanced Options UI
- Separate page from main options.html
- Linkify controls (enable/disable, aggressive mode)
- Exclusion filter management with tag-based UI
- Disabled domains blocklist management
- Loaded via sidebar navigation
advancedOptions/advancedOptions.css - Advanced Options Styling
- Form controls, toggle switches, input fields
- Tag-based filter list styling
- Status message animations
- Inherits from
css/variables.css
popup/popupOptions/popupOptions.js - Popup Button Customization
- Allows users to reorder and enable/disable popup buttons
- Drag-and-drop interface for button reordering
- Toggle switches for button visibility
- Persists configuration to
chrome.storage.sync
popup/popupOptions/popupOptions.html - Popup Options UI
- Separate settings page for popup customization
- Lists all popup buttons with icons, titles, subtitles
- Drag handles for reordering
- Reset to defaults button
popup/popupOptions/popupOptions.css - Popup Options Styling
- Drag-and-drop visual feedback
- Toggle switch styling
- Button preview cards
- PRO badge styling for premium features
Since there is no build process, you can work directly on the source files.
-
Load Unpacked:
- Open Chrome and go to
chrome://extensions/. - Enable Developer Mode (top right).
- Click Load unpacked.
- Select the root directory of this project (where
manifest.jsonis located).
- Open Chrome and go to
-
Reloading Changes:
- After modifying any file (especially
manifest.jsonor background scripts), go tochrome://extensions/and click the Reload (circular arrow) icon on the Grabbit card. - Crucial: You must also refresh any web pages where you are testing the content script for the changes to take effect.
- After modifying any file (especially
GrabbitStateinjs/state.jsis the single source of truth for:- Mouse positions (startX, startY, currentX, currentY)
- Selection status (isSelecting, selectionBox, counterLabel)
- Matched action and modifiers
- Cached links and refresh interval
- Active exclusion filters and disabled domains
mousedowningrabbit.js: Stores start position, doesn't activate UImousemove: Checks 5px drag threshold, then callsactivateSelection()activateSelection(): Creates UI elements, starts link refresh timerupdateSelectedLinks(): Collision detection, Smart Select, filteringmouseup: CallsprocessSelectedLinks()with matched actioncleanupSelection(): Removes UI, resets state, clears intervals
- Actions stored in
chrome.storage.syncwith structure:{ mouseButton: 0|1|2, // 0=left, 1=middle, 2=right modifierKey: "ctrl"|"shift"|"alt"|"meta"|"A"-"Z"|"", actionType: "open"|"copy"|"bookmark", settings: { /* action-specific config */ } }
checkKeyCombination()inutils.jsmatches input against saved actions- Modifiers include Ctrl, Shift, Alt, Meta, and letter keys A-Z
- Build frequency map of link signatures in selection box
- Signature = structure + tag name + font weight + font size
- If patterns repeat (count >= 2), filter to match those patterns
- Prioritize "important" links (headings, bold text)
- Reduces selection clutter on complex pages
refreshCachedLinks()called every 500ms during selection- Scans DOM for new links that appeared since selection started
- Handles lazy loading and infinite scroll scenarios
- Updates link cache without interrupting drag operation
- Update action type enum in
js/options/modal.js - Add UI configuration in modal form
- Add handling in
processSelectedLinks()injs/logic.js - Add background message handler in
js/background.js(if privileged API needed) - Test on various websites
- Check if token exists in
css/variables.css - If not, add new token to
:root - Reference token in component CSS
- Test across different pages to ensure no conflicts
- Create file in
js/directory - Add to
manifest.json→content_scripts→jsarray - Critical: Place in correct dependency order (state → utils → feature modules → grabbit.js)
- If using
GrabbitState, ensure it loads afterstate.js - Test by reloading extension and refreshing test pages
Sidebar Component:
- Add
<div id="sidebar-placeholder"></div>to any settings page HTML - Include
<script src="js/components/sidebar.js"></script>before closing body tag - Component auto-initializes on DOMContentLoaded
- Set active section with
data-active-sectionattribute:<div id="sidebar-placeholder" data-active-section="popup-options"></div>
Footer Component:
- Add
<div id="footer-placeholder"></div>to any settings page HTML - Include
<script src="js/components/footer.js"></script>before closing body tag - Component auto-initializes and renders footer with support links and contributors
- Handles rate and pin button functionality automatically
Both components use class-based architecture with render() and initLogic() methods for easy customization.
- Navigate to Options page → Popup Options
- Drag buttons to reorder (changes reflect immediately in popup)
- Use toggle switches to enable/disable buttons
- Configuration persists to
chrome.storage.syncviapopup-config.js - Popup reads configuration on load and renders buttons accordingly
- To add new button types:
- Add to
POPUP_BUTTONSregistry injs/options/popup-config.js - Implement handler in
popup/popup.js - Add icon SVG to
getButtonIcon()function
- Add to
- Open Chrome DevTools on test webpage
- Check Console for errors
- Inspect
GrabbitStatein Console:console.log(GrabbitState) - Use
debugger;statements in content script files - Remember to reload extension and refresh page after code changes
- Go to
chrome://extensions/ - Click "Service worker" link under Grabbit
- Opens DevTools for background worker
- Check Console for errors
- Inspect messages received/sent
Recommended Test Sites:
- Hacker News (news.ycombinator.com) - Clean link lists
- Reddit - Complex nested links
- Amazon/e-commerce sites - Product links for AI comparison
- Google Search - Test visited link tracking and redirects
Testing Edge Cases:
- Sticky headers that overlap content
- Infinite scroll (Twitter, Facebook feeds)
- Shadow DOM (web components)
- Links within iframes
- Very long pages (test auto-scrolling)
- Click the extension icon to access quick actions
- Visit the options page to configure custom actions
- On any webpage:
- Hold configured mouse button (and key if set)
- Drag to select multiple links
- Release to perform the configured action
Access the options page to:
- Create new actions with custom key combinations
- Set different colors for selection boxes
- Configure smart selection options
- Manage existing actions
- Set default behaviors
- Windows 10
- Windows 11, Chrome Latest Version (28 Jan 2026)
- MacOS Tahoe, Chrome Latest Version (28 Jan 2026)
- Linux, Chrome Latest Version (28 Jan 2026)
- 🔴 ESC key conflicts with Windows shortcuts when used with Ctrl/Shift/Alt
- 🔴 Letter keys (A-Z) as modifiers may not work with some laptop trackpads (palm rejection)
- 🔴 Not compatible with Netsuite
- 🟢 Add two actions. Action 1: Ctrl + Right Mouse for copy link. Action 2: Right mouse for open links - Copy links with CTRL + Right Mouse, release the CTRL, it does not change to open links while the opposite works.
- 🟢 Add two actions. Action 1: Ctrl + Right Mouse for copy link. Action 2: Ctrl + Left mouse for open links. Only action with right mouse works
- 🟢 Lifting keyboard key and no action is found for mouse only actions, is still selecting
- 🟢 Removed unused context menu permission
- 🟢 Fix naming of buttons in Mac
⚠️ Limited to Chrome (Manifest V3)⚠️ No automated test suite (manual testing only)⚠️ ExtPay.js is a third-party dependency - updates may require testing payment flow⚠️ AI features require active internet connection and valid subscription
- 🟢 Open Links/tabs in reverse order
- 🟢 Copy links with titles
- 🟢 Provide different color on add new action
- 🟢 Added A-Z keys as modifier options for actions
- 🟢 Duplicate Link Highlighter
- 🔴 Append Urls to clipboard. Clipboard = selected links + clipboard
- 🟢 Add rating button
- 🟢 Open tabs next to active tab
- 🟢 Recognize tags that are not visible
- 🟢 Include Compatibility with Youtube Subscriptions links
- 🟢 Add delay when opening tabs
- 🟢 Include option when copying URLs ("Title tab Url, instead of Title \n Url")
- 🟢 Create Bookmarks
- 🔴 Fix compatibility with Netsuite
- 🔴 Improve trackpad compatibility for letter key modifiers
- Frontend: Vanilla JavaScript (ES6+), HTML, CSS
- Chrome APIs: storage, tabs, windows, clipboard, scripting, bookmarks
- Backend: Supabase Edge Functions
- AI: OpenRouter API
- Payments: Stripe API, checkout flow
- Database: Supabase PostgreSQL database
- Content Extraction: Custom DOM parsing for e-commerce sites
- Component Architecture: Class-based reusable components with auto-initialization
- Design System: CSS Variables, Glassmorphism design, component-based styling
- Testing: Manual testing on BrowserStack across multiple platforms
Please refer to the changelog for detailed changes in each version.
- @TheTacoScott - https://github.com/TheTacoScott
- @oaustegard - https://github.com/oaustegard
- @digirat - https://github.com/digirat
- Subtiltee - https://subtiltee.com/all-extensions
This project is licensed under the MIT License - see the LICENSE file for details.
- This is a Linkclump replacement/alternative
- This is a Copy All Urls replacement/alternative