A powerful, customizable Chrome new tab page extension with a pluggable widget system, third-party API integrations, SQL query workbench, and a data transformation pipeline.
- Drag-and-drop grid layout with configurable columns, row height, and compaction
- 25 widget types spanning static displays, data visualizations, and interactive tools
- Per-widget settings panel with 5 tabs: data sources, transform pipeline, display options, styling, and info
- Per-widget content scaling via style settings
- Copy/paste and duplicate widgets across pages
- Multi-page dashboard with tab navigation
- Page-level security with PIN lock, TOTP (2FA), and recovery codes
| Type | Category | Description |
|---|---|---|
| Clock | Static | Large time display with date, 12/24h format |
| Greeting | Static | Time-aware greeting with optional name |
| Quick Links | Static | Shortcut grid to frequently visited sites |
| Search | Static | Quick web search bar |
| Timer | Interactive | Countdown timer |
| Stopwatch | Interactive | Elapsed time stopwatch |
| Claude Chat | Interactive | Conversational AI with model selection (Haiku/Sonnet/Opus), web search, persistent chat history |
| Notes | Interactive | Rich text editor (Tiptap) with slash commands, task lists, date smart chips, formatting toolbar |
| Card Benefits | Interactive | Editable credit card perks and benefits tracker |
| Number Card | Data | Single KPI value with color thresholds and sparkline trends |
| Table | Data | Sortable, filterable data table with column visibility and resize |
| List | Data | Compact title/subtitle list view |
| Bar Chart | Chart | Grouped or stacked bar chart, multi-series, dual Y axis |
| Line Chart | Chart | Multi-series line/area chart with stacking and dual Y axis |
| Pie Chart | Chart | Donut chart with legend and data labels |
| Heatmap | Chart | Color-intensity grid for two-dimensional data |
| Calendar View | Data | Week view with event indicators |
| Timeline | Data | Grouped chronological event list |
| Markdown | Data | Rendered markdown content from data |
| Credit Cards | Financial | Visual credit card display with balance and available credit |
| Accounts | Financial | Bank account summary with net worth, credit utilization, and asset tracking (categories: Cash, Investments, Assets, Credit, Loans) |
| Weather | Specialized | Current conditions + 6-day forecast via Open-Meteo with WMO weather codes |
| Stock Ticker | Specialized | Price sparklines with trend indicators, supports any data source or Alpha Vantage self-fetch |
| Air Quality | Specialized | AQI gauge display via AirNow |
| Oura Ring | Specialized | Health metrics with auto-detection of sleep, activity, readiness, and heart rate data |
Each connector is a self-contained plugin that fetches, normalizes, and caches data from an external service.
| Connector | Auth | What it provides |
|---|---|---|
| Gmail | Google OAuth2 | Unread emails, message metadata |
| Google Calendar | Google OAuth2 | Upcoming events across calendars |
| Google Tasks | Google OAuth2 | Task lists and items |
| Claude AI | API Key | AI-generated responses, chat with web search |
| Notion | API Key | Database entries with dynamic schema |
| Plaid | Proxy + Token | Bank account balances and transactions |
| Plaid Cost | Proxy + Token | API cost tracking |
| SimpleFIN | Bridge URL | Bank accounts and transactions |
| Alpha Vantage | API Key | Stock price history and quotes |
| Open-Meteo | None | Weather forecasts and current conditions |
| AirNow | API Key | Air quality index by location |
| Oura | API Key | Sleep, activity, readiness, and heart rate data |
| Frankfurter | None | Currency exchange rates |
| Seats.aero | API Key | Flight and travel data |
| Custom REST API | API Key / None | Any JSON endpoint with field mapping |
A Honeycomb-inspired query workbench for exploring and transforming data:
- Visual query builder -- WHERE filters, GROUP BY, VISUALIZE (aggregations), ORDER BY, LIMIT, HAVING
- SQL editor -- write raw SQL with syntax highlighting and schema sidebar
- Bi-directional sync -- visual query and SQL stay in sync as you edit either side
- SQL engine -- parses SQL via node-sql-parser, supports SELECT, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, UNION ALL, column aliases, string/number literals
- Save as widget -- turn query results into a dashboard widget
- Save as derived dataset -- create virtual datasets from queries for use by other widgets
- Query history -- browse and replay past queries
- Export -- download results as CSV or JSON
- Manual datasets -- create custom data tables directly in the browser with typed columns
- Derived datasets -- define virtual datasets via pipeline transforms or SQL queries over any combination of connectors, manual datasets, and other derived datasets
- Derived datasets resolve lazily with cycle detection
A JSON-serializable transform pipeline sits between data and display:
- filter -- field conditions with and/or logic, date macros (
{{now}},{{now+7d}}) - sort -- multi-field ascending/descending
- group_by -- group rows and aggregate per group
- aggregate -- sum, avg, min, max, count, count_distinct, first, last, median, p50, p95, p99
- computed_field -- safe JavaScript expressions evaluated per-row
- select_fields / rename_field -- column projection and renaming
- limit -- offset + count pagination
- time_series_bucket -- bucket by hour/day/week/month/quarter/year with gap-filling and timezone support
- merge -- union or join (inner/left/right/full) multiple data sources
- custom_expression -- row-level or table-level JS with a sandboxed evaluator
- window_function -- row_number, rank, running_total, moving_avg, lag, lead, percent_of_total with partition-by and order-by
- having -- post-aggregation filtering
- 9 built-in color themes (Midnight, Slate, Emerald, Rose, Amber, Nord, Dracula, Solarized, Monokai)
- Dark / Light / System mode
- Custom accent color, font family, background image with opacity control
- Global text scale + per-widget content scale
- OKLCh color space for perceptually uniform palettes
External APIs
|
v
Connectors (service worker, chrome.alarms)
|
v
chrome.storage.local (cached NormalizedDataSet)
|
v
useWidgetData hook (TanStack Query + pipeline)
|
v
Display Components (React)
Manual Datasets ──┐
├──> Query Workbench / Derived Datasets
Connector Data ───┘
Data flows one direction. The service worker fetches on a schedule and writes to storage. The new tab page reads reactively. Connectors and widgets never reference each other -- all data passes through the NormalizedDataSet / DataTable interfaces.
Manual and derived datasets feed into the same pipeline, allowing widgets to consume data from any source uniformly.
| Layer | Technology |
|---|---|
| Framework | React 19, TypeScript 5 |
| Bundler | Vite 6, @crxjs/vite-plugin |
| Styling | Tailwind CSS v4 (OKLCh tokens) |
| Grid | react-grid-layout v2 |
| Charts | Recharts |
| Rich Text | Tiptap v3 (ProseMirror) |
| SQL | node-sql-parser |
| State | Zustand (global, persisted to chrome.storage) |
| Data Fetching | TanStack Query |
| Forms | react-hook-form, Zod |
| Animation | Framer Motion |
| Icons | lucide-react |
| Package Manager | Bun |
- Bun >= 1.0
- Node.js >= 20
- Google Chrome or Chromium-based browser
bun installbun run devThen load the extension in Chrome:
- Navigate to
chrome://extensions - Enable Developer mode
- Click Load unpacked
- Select the
dist/directory
The dev server supports HMR -- changes to React components will hot-reload in the new tab page.
bun run buildOutputs a ready-to-load extension in dist/.
npx tsc --noEmitsrc/
manifest.ts # Chrome MV3 manifest (typed)
index.css # Tailwind entry + custom theme tokens
newtab/ # New tab page
App.tsx # Shell: grid + floating toolbar + page tabs
background/
service-worker.ts # Alarm-based fetch scheduling
core/
types/ # TypeScript interfaces (common, connector, widget, transform, grid)
pipeline/ # Transform engine + SQL engine + sandbox + date macros
registry/ # Connector and display type registries
storage/ # Zustand persistence adapter for chrome.storage
auth/ # OAuth2 flows, API key store, token cache
themes/ # 9 OKLCh color theme presets
messaging/ # Typed NTP <-> service worker message passing
docs/ # Widget documentation registry
connectors/
gmail/ # Gmail API
google-calendar/ # Calendar API
google-tasks/ # Tasks API
claude/ # Anthropic Messages API + chat
notion/ # Notion database query
plaid/ # Plaid via proxy (accounts + cost tracking)
simplefin/ # SimpleFIN bridge
alpha-vantage/ # Stock price data
open-meteo/ # Weather forecasts
airnow/ # Air quality index
oura/ # Oura Ring health data
frankfurter/ # Currency exchange rates
seats-aero/ # Flight data
custom-api/ # Generic REST endpoint
widgets/
base/
WidgetShell.tsx # Frame, drag handle, controls, content scaling
useWidgetData.ts # TanStack Query hook for connector data
displays/ # Data-driven renderers (charts, tables, cards, weather, stocks)
interactive/ # Stateful widgets (Chat, Notes, CardBenefits, Timer, Stopwatch)
notes-editor/ # Tiptap rich editor with slash commands and date chips
settings-panel/ # 5-tab config modal + visual query builder
grid/
GridContainer.tsx # react-grid-layout wrapper
GridConfigPanel.tsx # Grid configuration controls
stores/ # Zustand stores (widget, connector, theme, layout, page, manual/derived datasets)
components/
query-workbench/ # SQL/visual query builder, results panel, export, history
WidgetPicker.tsx # Widget type browser
ConnectorManager.tsx # Data source configuration
ManualDatasetEditor.tsx # Manual dataset CRUD + derived dataset management
PageTabs.tsx # Multi-page tab bar
GlobalSettings.tsx # App-wide settings
WidgetDocsModal.tsx # Widget documentation viewer
Requires a Google Cloud project with the appropriate APIs enabled and an OAuth2 client ID configured for Chrome extensions. Set the client ID in src/manifest.ts under the oauth2 key.
- Get an API key from console.anthropic.com
- Add a Claude Chat widget
- Enter your API key when prompted (or update it via the key icon in the chat toolbar)
- Select your preferred model (Haiku 4.5, Sonnet 4.6, or Opus 4.6)
- Create an internal integration
- Share your database with the integration
- Add a Notion connector with the integration token and database ID
Plaid requires a server-side proxy to hold your client_id and secret. Configure the proxy URL in the Plaid connector settings.
- Get a setup token from SimpleFIN
- Add a SimpleFIN connector and enter the token
- The extension will exchange it for an access URL automatically
Connect to any JSON endpoint. Configure URL, method, headers, response path (dot notation), and field mappings.
- Create
src/connectors/your-service/your-connector.ts - Extend
BaseConnectorand implementmanifestandfetch() - Register in
src/connectors/index.ts - The connector will automatically appear in the Data Sources panel
- Create a component in
src/widgets/displays/orsrc/widgets/interactive/ - Add to
staticWidgetsordataWidgetsmap insrc/widgets/base/WidgetShell.tsx - Add a template entry in
src/components/WidgetPicker.tsx
MIT License - see LICENSE for details.