AI‑powered Chrome extension that auto‑detects your projects, groups related tabs into workspaces, and suspends idle tabs to keep your browser fast and organized.
-
Automatic workspace detection
- Classifies new/updated tabs into workspaces (for example: “Robotics Store”, “Social / Browsing”, “AI Tools”).
- Uses rules (GitHub, Vercel, Notion, Jira, etc.) plus optional Groq AI for smarter grouping.
-
Chrome tab groups integration
- Each workspace maps to a Chrome tab group (color + emoji + name).
- Tabs are moved into the correct group as you browse.
- Switching workspaces focuses the relevant group and its tabs.
-
Workspace lifecycle
- Save workspace: snapshot of current tabs (including pinned, titles, favicons).
- Switch workspace: saves current, optionally suspends it, and restores the target workspace’s tabs.
- Archive idle/empty workspaces after a period of inactivity.
-
Automatic tab suspension
- Suspends background tabs into a lightweight
suspended.htmlpage. - Keeps the original favicon and a “Restore Tab” button.
- Resumes the original URL when you interact with the tab.
- Suspends background tabs into a lightweight
-
Side panel & popup UI
- Popup: quick list of workspaces and actions.
- Side panel: richer management (rename, move tabs, etc.).
- Options page: configure AI, sync, theme, and behavior.
-
Keyboard shortcuts (configurable in Chrome)
Alt + .– Next workspaceAlt + ,– Previous workspaceAlt + S– Save current workspace
-
Platform
- Chrome Extension Manifest V3
- Background service worker:
background/service-worker.js - Content script:
content/page-analyzer.js - Popup, sidepanel, options pages built with React/Vite into
dist/
-
Build tools
vite(with@crxjs/vite-plugin)- React 18 (
react,react-dom)
-
Runtime APIs & libraries
- Chrome APIs:
tabs,tabGroups,storage,alarms,sidePanel,notifications,idle,scripting - Optional Groq API for AI classification:
- Model:
llama-3.3-70b-versatile - Endpoint:
https://api.groq.com/openai/v1/chat/completions
- Model:
- Optional sync via Supabase (controlled by settings)
- Chrome APIs:
Workspaces are stored in chrome.storage via helpers in utils/storage.js. A workspace looks like:
{
id: string;
name: string;
color: string; // hex color
emoji: string; // e.g. "🚀"
createdAt: number;
lastActive: number;
chromeGroupId: number | null;
status: "active" | "suspended" | "archived";
tabs: Array<{
url: string;
title: string;
favicon: string;
pinned: boolean;
index: number;
lastVisited: number;
}>;
classificationRules: string[]; // user regex patterns
}utils/constants.js defines:
WORKSPACE_COLORS,CHROME_GROUP_COLORS,WORKSPACE_EMOJISDEFAULT_SETTINGS(autoClassify, suspendOnSwitch, suspendAfterMinutes, etc.)MESSAGE_TYPES,ALARM_NAMES, Groq model constants
-
AI pass (optional)
- If no rule matches and a Groq API key is set:
- Gathers
tabSignalsfromextractTabSignals(tab)and optional content-script page signals. - Sends them plus sample existing workspaces to Groq.
- Expects JSON:
{ "workspace": string, "confidence": number, "isNew": boolean }.
- Gathers
- Results are cached (
getCachedClassification,setCachedClassification) to avoid repeated calls.
- If no rule matches and a Groq API key is set:
-
Matching to existing workspace
findMatchingWorkspace(workspaces, classificationName):- Exact name match.
- Fuzzy contains match.
- ID match (slugified).
File: background/service-worker.js.
-
Startup / install
- On install:
- Optionally auto‑classifies all current tabs once (
autoClassifyAll()). - Creates alarms:
idle-suspend-checkevery 5 minutesauto-archive-checkevery hoursync-workspacesevery 15 minutes
- Optionally auto‑classifies all current tabs once (
- On startup:
- Re-creates alarms.
- Runs
syncTabGroupTitles()to ensure tab group names are consistent with workspaces.
- On install:
-
Tab listeners
-
chrome.tabs.onCreatedandonUpdated:- When a tab has a URL, is not incognito, and not ignored, call
handleClassifyTab(tab).
- When a tab has a URL, is not incognito, and not ignored, call
-
handleClassifyTab(tab):- Gets user settings, exits if
autoClassifyis off. - Runs classifier.
- If existing workspace found:
- Adds tab to
workspace.tabs(if new). - Uses
ensureTabGroup(workspace)to create/attach a Chrome group. - Adds the tab to that group via
addTabToGroup. - Saves workspace.
- Adds tab to
- If classification is new and
confidence >= 0.6:- Creates a new workspace with random color + emoji.
- Groups the tab into a new Chrome tab group and stores
chromeGroupId.
- Gets user settings, exits if
-
chrome.tabs.onActivated:- Updates
lastActiveand active workspace ID when you switch tabs within a group.
- Updates
-
chrome.tabGroups.onUpdated:- Syncs manual group renames/colors back to the workspace.
- If a group title is empty, fills it with
"<emoji> <name>".
-
-
Workspace switching
cycleWorkspace(direction)(keyboard shortcuts).switchWorkspace(fromId, toId):- For the current workspace:
- Snapshots open tabs via
snapshotWorkspaceTabs(fromWs). - Optionally suspends them via
suspendWorkspaceTabs(fromWs)and marks statussuspended. - Saves workspace.
- Snapshots open tabs via
- For the target workspace:
- Restores tabs via
restoreWorkspaceTabs(toWs)(reopen or unsuspend). - Updates
chromeGroupId, setsstatus = "active",lastActive = now. - Sets active workspace ID.
- Focuses the first tab in that workspace.
- Restores tabs via
- Optionally shows a notification about the switch.
- For the current workspace:
-
Messages (popup/sidepanel/options)
- Via
chrome.runtime.onMessageandMESSAGE_TYPES:GET_STATE– return full state (getFullState()).SWITCH_WORKSPACE,SAVE_WORKSPACE,CREATE_WORKSPACE,DELETE_WORKSPACE,ARCHIVE_WORKSPACE,RENAME_WORKSPACE,MOVE_TAB.UPDATE_SETTINGS– save user settings.CLASSIFY_TAB,CLASSIFY_ALL.OPEN_SIDEPANEL– opens side panel for the current tab.PAGE_SIGNALS– stores signals from content script intochrome.storage.session.
- Via
All in utils/tabUtils.js.
-
Group helpers
ensureTabGroup(workspace):- If
workspace.chromeGroupIdis valid, returns it. - Else:
- Finds tabs that belong to the workspace (by URL).
- Groups them with
chrome.tabs.group. - Sets title to
"<emoji> <workspace.name>"(fallback to💻 Workspace). - Sets color based on workspace color.
- Collapses if workspace is suspended.
- If
addTabToGroup(tabId, groupId):- Safely adds a tab to a given group.
-
Suspension
suspendTab(tabId):- Skips active / ignored / already suspended tabs.
- Navigates the tab to:
chrome.runtime.getURL("assets/suspended.html") + ?url=<originalUrl>&title=<title>&favicon=<faviconUrl>
restoreTab(tabId):- Extracts
urlfrom the suspended page query param and navigates back to it.
- Extracts
suspendWorkspaceTabs(workspace):- Finds tabs belonging to the workspace (prefers
groupId). - Collapses the tab group.
- Calls
suspendTabon each.
- Finds tabs belonging to the workspace (prefers
restoreWorkspaceTabs(workspace):- For each stored tab:
- If already open, restores if suspended.
- Else, reuses a suspended instance if present.
- Else, opens a new tab with correct
urland pinned state.
- Groups all opened tabs into a tab group with proper title and color.
- For each stored tab:
-
Suspended page
-
Files:
assets/suspended.htmlassets/suspended.js
-
suspended.html:<!doctype html> <html> <head> <meta charset="utf-8" /> <title>Tab Suspended</title> </head> <body> <div class="icon">💤</div> <h2>This tab has been suspended</h2> <p>Click below or interact with this tab to restore it.</p> <button id="restore-button">Restore Tab</button> <script src="suspended.js" defer></script> </body> </html>
-
suspended.js:- Reads
url,title,faviconfrom the query string. - Sets page title to
"<original title> (suspended)". - Dynamically creates/updates
<link rel="icon">to show the original favicon. - Wires the button and visibility events to call
restore().
- Reads
-
- Open:
github.com/localhost:3000(your dev server)vercel.com/you/
- With auto‑classify ON, the extension:
- Detects
namefrom GitHub/Vercel URLs. - Groups these tabs into a “Name” workspace.
- Creates a yellow tab group with an emoji, for example
🛒 Name.
- Detects
- Press
Alt + S:- A snapshot is saved with all those URLs and pinned states.
- Switch to another workspace via keyboard or popup:
- Current tabs are optionally suspended.
- Tabs for the target workspace are restored and grouped.
- Open many social sites: Twitter/X, YouTube, Reddit, Instagram.
- The classifier maps them to a workspace named “Social / Browsing”.
- When you switch to a “Work” workspace:
- Social tabs are suspended in the background.
- Only a small group remains, easily collapsible.
- Coming back:
- Switch to “Social / Browsing” workspace.
- Tabs restore from the suspended page back to their original URLs.
- In the side panel:
- Create a workspace: AI Research with emoji
🧠.
- Create a workspace: AI Research with emoji
- Drag or “Move tab to workspace” from the UI:
- Selected tabs are added to AI Research.
- The extension groups those tabs into a
🧠 AI ResearchChrome tab group.
- When closing the browser and reopening:
- On startup, the extension restores group titles and keeps your workspace metadata.
- Run a build:
cd GridMind
npm install
npm run build- In Chrome/Brave:
- Go to
chrome://extensions(orbrave://extensions). - Enable Developer mode.
- Click “Load unpacked” and select the
dist/folder.
- Go to
npm run dev- Vite watches source files and rebuilds into
dist/. - After changes, click Reload on the extension in the extensions page.
Open the Options page (right‑click the extension icon → Options or chrome://extensions → Details → Extension options):
- Groq API key – enable AI classification.
- Auto classify – on/off.
- Suspend on switch – whether to suspend tabs when leaving a workspace.
- Suspend after minutes – idle time before auto‑suspend via alarm.
- Show notifications – toasts for save/switch events.
- Sync settings – Supabase URL/key if you want cross‑device sync (optional).
- Theme – dark/light.