In this guide
- First launch and initial setup
- Appearance — themes, widget styles, and typography
- Dashboards — multiple workspaces
- Widget builder — build your own
- Widget Store — community and official widgets
- Built-in widgets — clock, weather, pomodoro, and more
- Backgrounds — nine source types
- The command palette (⌘K)
- Snippets and URL aliases
- Built-in plugins
- Custom plugins — fetch, relay, and scrape mode
- Automations — trigger and action rules
- Script commands — run JS from the palette
- User scripts — inject JS into any page
- AI profiles and BYOK setup
- Workspace presets
- Todos, habits, and focus mode
- Dock — favicon icons, preset packs, and overflow stacks
- Projects and Tags — organise your research
- Smart palette — context bubbles and recently used
- Page actions — highlight, screenshot, reader mode
- Pro sync — highlights and todos across devices
1. First launch and initial setup
After installing from the Chrome Web Store, open a new tab. The first-run overlay asks for three things: your name (shown in the greeting), your home city for the weather widget, and whether you want analytics. All three are optional and all three can be changed later in Settings.
Settings are in the gear icon on the top-right of the new tab. Everything persists in chrome.storage.sync — your settings follow you across Chrome profiles automatically.
2. Appearance — themes, widget styles, and typography
Open Settings → Appearance to personalise how Pinodock looks. All options apply instantly — no refresh needed.
Theme presets
Eight named colour themes replace the old dark / light toggle. Pick one from the visual grid; each shows a swatch and name.
| Preset | Character | Best for |
|---|---|---|
| Warm Dark | Charcoal background, terracotta accent | Default — comfortable for long sessions |
| Light | Off-white background, same terracotta accent | Bright offices, print-friendly screenshots |
| Midnight | Near-black, GitHub-blue accent | Developers, dark-room environments |
| Forest | Dark green, fresh-green accent | Nature lovers, low-fatigue reading |
| Ocean | Deep teal, sky-blue accent | Writers, calm focus environments |
| Rose | Dark burgundy, pink accent | Creative work, evening sessions |
| Slate | Cool grey light, indigo accent | Presentations, light-mode alternative |
| Sand | Warm beige light, bronze accent | Warm light-mode, analog feel |
The accent colour picker below the theme grid lets you override the preset accent with any hex value. The first dot in the accent picker resets the accent to the preset default.
Widget style
Four widget surface styles control how plugin widgets look on your dashboard:
| Style | Appearance | Use it when |
|---|---|---|
| Card | Surface background, subtle border, soft shadow | Default — works with all themes |
| Flat | Transparent — no border or shadow | Clean, minimal look; works well on solid colour backgrounds |
| Bordered | Semi-transparent fill with a 1 px border, no shadow | Structured look that still shows the background through |
| Glass | Frosted-glass blur, translucent fill, soft border | Photo or gradient backgrounds; high-contrast photos work best |
Font family
Choose the typeface used across the entire dashboard. The setting writes a --font-family CSS variable that all components inherit.
| Option | What loads |
|---|---|
| System | OS default — San Francisco on Mac, Segoe UI on Windows. Zero load time. |
| Inter | Inter variable — the most legible screen font for dense data dashboards. |
| Mono | JetBrains Mono (or Fira Code / Cascadia Code as fallbacks). Best for Dev dashboards. |
| Serif | Georgia. Warmer and more editorial — pairs well with the Sand or Light theme. |
4. Widget builder — build your own widget
The widget builder is a three-step wizard that lets you turn any JSON API, relay function, or open browser tab into a live dashboard widget — no code required.
Open it from Dashboard → Customize → Build widget.
Step 1: Choose a widget type
Pick the visual layout that matches your data. Twelve types are available:
| Type | Best for |
|---|---|
| Metric card | A single number — revenue, error rate, build time. Colour-codes at warn/danger thresholds. |
| Status card | A coloured badge showing an operational state (OK / Warn / Error). |
| List | An ordered list of items from an API array — HN stories, open PRs, recent deploys. |
| Table | Two-column label / value pairs — ideal for weather, system stats, or key-value configs. |
| Sparkline | Mini line chart from a numeric array — price history, request counts, memory usage. |
| Progress ring | Circular progress from a current / max ratio — storage used, sprint completion, quota. |
| Countdown | Time remaining until a date you set — launch day, sprint deadline, subscription renewal. |
| Agenda | Timeline of upcoming events from an API array — calendar events, release milestones. |
| Image card | Static image with title and caption — team photo, architecture diagram, marketing asset. |
| Quote | Static or API-sourced text block — team motto, rotating tip, daily affirmation. |
| Calendar strip | 7-day rolling mini calendar with optional event dots from Google Calendar. |
| Text block | Free-form text note stored locally — pinned reminder, on-call notes. |
Step 2: Name, icon, and data source
Give the widget a name, emoji icon, and accent colour. Then choose where data comes from:
- Static — no fetch; you type the content directly (used for Quote, Text block, Countdown, Image).
- API fetch — GET any CORS-enabled JSON endpoint from your browser.
- Relay — POST to your own serverless function; credentials stay server-side.
- Scrape tab — read text from an open browser tab via a CSS selector (internal tools, Retool, legacy dashboards).
Step 3: Map fields
For API fetch and relay modes, map JSON response fields to the widget's display slots. Each field needs a label, a dot-notation path (e.g. bitcoin.usd or [0].title), and an optional transform:
| Transform | Effect |
|---|---|
number | Formats with locale thousands separators |
currency | Prepends $ and 2 decimal places |
percent | Appends % and 1 decimal place |
date | Converts ISO/Unix timestamp to locale date string |
truncate | Clips text to 60 characters |
uppercase / lowercase | Case transforms |
For metric cards, you can also set warn and danger thresholds per field — the value text colour turns amber or red when crossed.
5. Widget Store — community and official widgets
The Widget Store is a curated registry of ready-made widgets you can install in one click. Open it from Dashboard → Customize → Widget Store.
Official widgets from PencilCard are bundled in the extension and available offline. The live registry at pencilcard.com/pinodock-widgets.json is fetched in the background; if you're offline the bundled set is used automatically.
Official starter widgets
| Widget | Type | Data source |
|---|---|---|
| Bitcoin Price | Metric card | CoinGecko API (free, no key) |
| Hacker News Top 5 | List | HN Firebase API (free, no key) |
| GitHub Open PRs | Metric card | GitHub REST API (needs token) |
| PagerDuty Incidents | Status card | Your relay function (credentials server-side) |
| Stripe MRR | Metric card | Your relay function (credentials server-side) |
| OpenWeatherMap | Table | OpenWeatherMap API (free key) |
| Launch Countdown | Countdown | Static — edit the target date after installing |
Clicking Install saves the widget definition locally and adds it to the current dashboard. If the widget requires a URL, API key, or relay endpoint, the widget card will prompt you to fill those in after install.
Publishing a widget
Any widget you build in the widget builder can be exported as a JSON definition. Submit it to pencilcard.com/pinodock-widgets and — after review — it will appear in the store for everyone to install. No code review required; the format is the same JSON Pinodock already uses internally.
6. Dashboards — your multiple workspaces
A dashboard is a named configuration of widgets and plugins. You can have as many as you want. Each one stores independently: which plugins are on, which widgets are visible, and which layout template is active.
Pinodock ships with four preset dashboards to get you started:
| Dashboard | Default plugins | Layout |
|---|---|---|
| Work 💼 | Google Calendar, Gmail, GitHub, Todoist | Two-col |
| Creator 🎬 | YouTube Studio, Spotify, Reddit | Masonry-left |
| Dev ⌨️ | GitHub, Hacker News, AWS, Crypto | Three-col |
| Personal 🌿 | Spotify, Crypto, Reddit | Hero-top |
To create a custom dashboard: open the Dashboard panel (bottom of the settings sidebar), click + New Dashboard, give it a name and an emoji. You'll get a blank canvas. Add plugins from the Plugins tab, choose a layout, and toggle which widgets appear on that dashboard.
Layout templates
Eight layout options control how plugins are distributed across the grid:
- Single — one full-width column
- Two-col — equal side-by-side columns
- Three-col — three equal columns
- Hero-top — first plugin spans full width, rest split below
- Wide-left / Wide-right — 2:1 split favouring one side
- Tall-left / Tall-right — one plugin spans two rows on the dominant side
7. Built-in widgets
Widgets are the static components that appear alongside your plugin data. Each widget can be shown or hidden per-dashboard, and the order is fully draggable in Settings → Widgets.
| Widget | What it does | Config |
|---|---|---|
| Clock | Always visible in the header | 12h/24h, seconds on/off, digital/analog style |
| Quote | Daily motivational quote | Show/hide |
| Quick Links | Pinned URLs as clickable chips | Add/remove/reorder links |
| Scratch Pad | Ephemeral text note, persists in storage | Show/hide |
| Pomodoro | 25/5 focus timer | Work and break durations, session log |
| Ambient Sound | Background audio while working | Off / Rain / Focus |
| Weather | Current conditions for your city | City name, show/hide |
8. Backgrounds — nine source types
Open Settings → Appearance → Background to choose your source. All nine modes are free:
| Mode | How it works | Config needed |
|---|---|---|
| Curated | Pinodock's built-in photo library. Click the refresh button on the new tab to cycle to the next one. | None |
| Daily | A new random photo each day. Same image across all tabs until midnight. | None |
| Unsplash | Random photo from Unsplash by topic, refreshed on each new tab open. | Your Unsplash API key + topic |
| Giphy | Animated GIF background matched to a tag. | Your Giphy API key + tag |
| Gradient | CSS gradient between two colors at a custom angle. | Start color, end color, angle |
| Solid color | Flat background color. | Hex color |
| Custom URL | Any HTTPS image URL. | The URL |
| Local file | Upload an image from your device, stored locally in the extension. | File upload |
| Folder | Rotate through a set of local images. Click refresh to advance to the next one. | Multiple file uploads |
9. The command palette (⌘K)
Press ⌘K (Mac) or Ctrl K (Windows/Linux) anywhere on your new tab to open the command palette. It searches across:
- Open browser tabs (purple badge)
- Bookmarks (blue badge)
- Recent history (grey badge)
- Your snippets (teal badge)
- Your URL aliases (orange badge)
- Script commands triggered with
!prefix (yellow badge) - Built-in actions: new tab, close tab, go back, go forward, zoom controls
The palette also runs on active tabs. Press ⌘⇧K on any page to open the Quick Palette overlay — you get the full command set without navigating back to your new tab.
ghp will surface a bookmark titled "GitHub Pull Requests". You don't need to type the full title.
7. Snippets and URL aliases
Text snippets FREE
Go to Settings → Snippets → Add Snippet. Each snippet has a title (what you search for) and content (what gets copied to your clipboard when you pick it). Selecting a snippet in the palette instantly copies the content — press ⌘V to paste it wherever you need it.
Practical snippet setups:
// Snippet: "meet-zoom" → content:
https://zoom.us/j/YOUR_MEETING_ID?pwd=YOUR_PASSWORD
// Snippet: "sig-email" → content:
Best regards,
Sarah Chen
Senior Engineer · Acme Corp
sarah@acme.com · +1 (555) 000-1234
// Snippet: "pr-template" → content:
## What this PR does
## Test plan
- [ ] Unit tests pass
- [ ] Tested on staging
- [ ] No breaking changes to public API
## Related issues
Closes #
// Snippet: "sql-explain" → content:
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT * FROM
URL aliases FREE
Go to Settings → Aliases → Add Alias. Set a short prefix and the full URL. Type the prefix in ⌘K and press Enter to navigate directly.
// Developer shortcuts
gh → https://github.com/YOUR_ORG
prs → https://github.com/YOUR_ORG/YOUR_REPO/pulls
li → https://linear.app/YOUR_WORKSPACE
fig → https://www.figma.com/files/YOUR_TEAM
// Environments
prd → https://app.yourproduct.com
stg → https://staging.yourproduct.com
log → https://us-east1.console.cloud.google.com/logs
// Daily tools
cal → https://calendar.google.com
mail → https://mail.google.com
doc → https://www.notion.so/YOUR_WORKSPACE
8. Built-in plugins FREE
Enable plugins per-dashboard from the Plugins tab in Settings. Built-in plugins fall into two categories: public (no auth needed) and connected (reads data from an open browser tab).
| Plugin | Type | What it shows |
|---|---|---|
| Hacker News | Public | Top 5 stories from the HN front page |
| Crypto Prices | Public | BTC, ETH, SOL price + 7-day sparkline |
| Reddit Feed | Public | Top posts from any subreddit (configurable) |
| GitHub | Connected (github.com tab) | Open notification count + username |
| Gmail | Connected (mail.google.com tab) | Unread count + latest 5 subjects |
| Google Calendar | Connected (calendar.google.com tab) | Today's upcoming events |
| Spotify | Connected (open.spotify.com tab) | Now playing track, artist, play state |
| YouTube Studio | Connected (studio.youtube.com tab) | Recent video views and subscriber count |
| AWS Console | Connected (console.aws.amazon.com tab) | Current month cost + active region |
| Todoist | Connected (app.todoist.com tab) | Today's task list |
Connected plugins require the target site to be open in a tab. When Pinodock finds it, it injects a small read-only script to extract the data. No credentials are stored — Pinodock reads from the session your browser already has.
9. Custom plugins PRO
Go to Settings → Plugins → Custom → Add Plugin. Three fetch modes cover virtually any data source.
Fetch mode — public JSON APIs
Makes a direct GET request from your browser. Works with any API that supports CORS. Here are three complete plugin configs you can enter directly into the settings form:
// ── Plugin: GitHub open PRs ───────────────────────────────
Name: Open PRs
Icon: 🐙 Color: #24292e
Mode: fetch
URL: https://api.github.com/repos/YOUR_ORG/YOUR_REPO/pulls?state=open&per_page=100
Headers: {"Authorization": "Bearer ghp_YOUR_TOKEN", "X-GitHub-Api-Version": "2022-11-28"}
Template: stat
Fields:
• Label: "Open PRs" Path: "length" Transform: number
Threshold: warnAbove=5 dangerAbove=10
// ── Plugin: Bitcoin price ─────────────────────────────────
Name: Bitcoin
Icon: ₿ Color: #f7931a
Mode: fetch
URL: https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd&include_24hr_change=true
Template: stat
Fields:
• Label: "Price" Path: "bitcoin.usd" Transform: currency
• Label: "24h change" Path: "bitcoin.usd_24h_change" Transform: percent
// ── Plugin: OpenWeatherMap temperature ───────────────────
Name: Weather — Sydney
Icon: 🌤 Color: #0ea5e9
Mode: fetch
URL: https://api.openweathermap.org/data/2.5/weather?q=Sydney&appid=YOUR_KEY&units=metric
Template: table
Fields:
• Label: "Temp" Path: "main.temp" Transform: number
• Label: "Feels like" Path: "main.feels_like" Transform: number
• Label: "Humidity" Path: "main.humidity" Transform: percent
• Label: "Wind km/h" Path: "wind.speed" Transform: number
Relay mode — private APIs where credentials stay server-side
Some APIs block CORS or shouldn't have their keys in browser storage. Relay mode POSTs to a small function you control; the function calls the real API and returns just the data you need.
Here's a complete relay function for Vercel (also works as a Cloudflare Worker or AWS Lambda):
// vercel/functions/pinodock-relay.js
export default async function handler(req, res) {
const { key, params } = req.body
// Optional: verify the shared secret from Pinodock settings
const secret = process.env.PINODOCK_RELAY_SECRET
if (secret && req.headers['x-pinodock-secret'] !== secret) {
return res.status(401).json({ error: 'Unauthorized' })
}
switch (key) {
case 'stripe-mrr': {
const stripe = await fetch(
'https://api.stripe.com/v1/charges?limit=100&created[gte]=' +
Math.floor(Date.now() / 1000) - 2592000,
{ headers: { Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}` } }
).then(r => r.json())
const mrr = stripe.data.reduce((s, c) => s + c.amount, 0) / 100
return res.json({ mrr, currency: 'usd' })
}
case 'pagerduty-incidents': {
const pd = await fetch(
'https://api.pagerduty.com/incidents?statuses[]=triggered&statuses[]=acknowledged',
{ headers: {
Authorization: `Token token=${process.env.PAGERDUTY_TOKEN}`,
Accept: 'application/vnd.pagerduty+json;version=2'
}}
).then(r => r.json())
return res.json({ count: pd.total, incidents: pd.incidents.slice(0, 5) })
}
default:
return res.status(400).json({ error: 'Unknown plugin key' })
}
}
In Pinodock settings, configure the relay plugin:
// ── Plugin: Stripe MRR (relay) ─────────────────────────
Name: MRR
Icon: 💳 Color: #635bff
Mode: relay
URL: https://your-vercel-app.vercel.app/api/pinodock-relay
Relay key: stripe-mrr
Secret: YOUR_SHARED_SECRET
Refresh: 60 (minutes)
Template: stat
Fields:
• Label: "Monthly Revenue" Path: "mrr" Transform: currency
Scrape mode — data from any open tab
Point at a URL and a CSS selector. Pinodock reads the matching element's text from your open tab. No API needed — ideal for internal dashboards, Retool apps, and legacy tools.
// ── Plugin: Retool metric ─────────────────────────────
Name: Active Users
Icon: 📊 Color: #f59e0b
Mode: scrape
URL: https://your-company.retool.com/apps/your-dashboard
Selector: [data-testid="active-user-count"] .value
Template: stat
10. Automations PRO
Automations are trigger → action rules that run in the background. Go to Settings → Automations → Add Automation.
| Trigger type | Format | Example |
|---|---|---|
| Time | HH:MM — fires daily at that time | 09:00 |
| Query | Typed prefix in the palette | standup |
| Action type | What it does |
|---|---|
| open_url | Opens a URL in a new tab |
| open_alias | Navigates to one of your saved URL aliases |
| copy | Copies a text string to your clipboard |
Automation examples:
// ── Automation 1: Open your standup tools at 9 AM ────────
Name: Morning Standup
Trigger: time → 09:00
Action: open_url → https://meet.google.com/your-standup-link
// ── Automation 2: "deploy" in palette → open your CI run ─
Name: Open Latest Deploy
Trigger: query → deploy
Action: open_url → https://github.com/YOUR_ORG/YOUR_REPO/actions
// ── Automation 3: "eod" → copy end-of-day template ──────
Name: EOD Template
Trigger: query → eod
Action: copy → Done today:
-
-
Tomorrow:
-
Blockers: none
Enable Auto-run automations in settings to have time-based automations fire automatically without any user action. Leave it off to keep them as manual triggers only.
11. Script commands PRO
Script commands are JavaScript functions triggered by typing !trigger in the command palette. Go to Settings → Scripts → Add Script Command.
Each command receives the rest of your typed input as input: string and can do anything JavaScript can do in a Chrome extension background context — fetch requests, clipboard writes, tab operations, and more.
// ── Script: "!ip" — fetch and copy your public IP ────────
Name: Get Public IP
Trigger: ip
Code:
const res = await fetch('https://api.ipify.org?format=json')
const data = await res.json()
await navigator.clipboard.writeText(data.ip)
return `Copied: ${data.ip}`
// ── Script: "!time London" — world clock ─────────────────
Name: World Clock
Trigger: time
// input = the timezone name (e.g. "London", "Tokyo", "New_York")
Code:
const zone = input.trim() || 'UTC'
const fmt = new Intl.DateTimeFormat('en-GB', {
timeZone: zone, hour: '2-digit', minute: '2-digit', second: '2-digit'
})
const result = `${zone}: ${fmt.format(new Date())}`
await navigator.clipboard.writeText(result)
return result
// ── Script: "!uuid" — generate and copy a UUID ───────────
Name: New UUID
Trigger: uuid
Code:
const id = crypto.randomUUID()
await navigator.clipboard.writeText(id)
return id
// ── Script: "!b64 Hello world" — base64 encode ───────────
Name: Base64 Encode
Trigger: b64
Code:
const encoded = btoa(unescape(encodeURIComponent(input)))
await navigator.clipboard.writeText(encoded)
return encoded
// ── Script: "!tab github" — switch to a matching tab ─────
Name: Jump to Tab
Trigger: tab
Code:
const tabs = await chrome.tabs.query({})
const match = tabs.find(t =>
t.url?.toLowerCase().includes(input.toLowerCase()) ||
t.title?.toLowerCase().includes(input.toLowerCase())
)
if (match) {
chrome.tabs.update(match.id, { active: true })
chrome.windows.update(match.windowId, { focused: true })
return `Switched to: ${match.title}`
}
return 'No matching tab found'
12. User scripts PRO
User scripts are JavaScript that runs automatically when you visit a URL matching a pattern you define. They use Chrome's userScripts API and require Developer Mode to be enabled in chrome://extensions.
Go to Settings → User Scripts → Add Script. Each script has URL match patterns, a JS code body, a world context (USER_SCRIPT for isolation or MAIN for full page access), and a run-at timing.
Three recipe scripts are built-in and available free:
- GitHub TODO Highlighter — wraps
TODO,FIXME,HACKcomments in yellow - Cookie Banner Remover — hides OneTrust, Cookiebot, and similar on any site
- Linear Focus Mode — collapses the sidebar on Linear
With Pro you can write your own. Here are four complete examples:
// ── Script 1: Auto-dark-mode on any page ─────────────────
Name: Force Dark Mode
Matches: ["https://*/*"]
World: USER_SCRIPT
RunAt: document_start
Code:
const style = document.createElement('style')
style.textContent = `
html { filter: invert(1) hue-rotate(180deg) !important; }
img, video, canvas, svg, iframe { filter: invert(1) hue-rotate(180deg) !important; }
`
document.documentElement.appendChild(style)
// ── Script 2: GitHub — show PR age in the PR list ────────
Name: GitHub PR Age
Matches: ["https://github.com/*/pulls*"]
World: MAIN
RunAt: document_idle
Code:
document.querySelectorAll('[aria-label*="opened"] relative-time').forEach(el => {
const opened = new Date(el.getAttribute('datetime'))
const days = Math.floor((Date.now() - opened) / 86400000)
const badge = document.createElement('span')
badge.textContent = `${days}d`
badge.style.cssText = `
background: ${days > 7 ? '#dc2626' : days > 3 ? '#d97706' : '#16a34a'};
color: white; font-size: 10px; font-weight: 700; border-radius: 4px;
padding: 1px 5px; margin-left: 6px; vertical-align: middle;
`
el.parentNode?.appendChild(badge)
})
// ── Script 3: Notion — hide the left sidebar ─────────────
Name: Notion Focus Mode
Matches: ["https://www.notion.so/*"]
World: USER_SCRIPT
RunAt: document_idle
Code:
const hide = () => {
const sidebar = document.querySelector('.notion-sidebar-container, [class*="sidebar"]')
if (sidebar) sidebar.style.display = 'none'
}
hide()
new MutationObserver(hide).observe(document.body, { childList: true, subtree: true })
// ── Script 4: Any page — floating word count for writers ──
Name: Word Count HUD
Matches: ["https://docs.google.com/document/*", "https://www.notion.so/*"]
World: MAIN
RunAt: document_idle
Code:
const hud = document.createElement('div')
hud.style.cssText = `
position: fixed; bottom: 16px; right: 16px; z-index: 99999;
background: rgba(15,23,42,0.85); color: #e2e8f0;
font: 600 11px/1 monospace; padding: 6px 10px; border-radius: 6px;
pointer-events: none; backdrop-filter: blur(4px);
`
document.body.appendChild(hud)
function update() {
const text = document.body.innerText || ''
const words = text.trim().split(/\s+/).filter(Boolean).length
hud.textContent = `${words.toLocaleString()} words`
}
update()
new MutationObserver(update).observe(document.body, { subtree: true, characterData: true })
To export all your scripts as a JSON backup, open Settings → User Scripts → Export. To share or import a set of scripts, use the Import button and paste a JSON array in the same format.
13. AI profiles and BYOK setup PRO
Pinodock supports multiple AI profiles. Each profile points to a different provider or model. Go to Settings → AI → Add Profile.
| Provider | Key prefix | Default model |
|---|---|---|
| OpenAI (ChatGPT) | sk-… | gpt-4o-mini |
| Anthropic (Claude) | sk-ant-… | claude-haiku-4-5 |
| Google Gemini | AIza… | gemini-2.0-flash |
| DeepSeek | sk-… | deepseek-chat |
| Perplexity | pplx-… | llama-3.1-sonar-small-128k-online |
| Local (OpenAI-compatible) | Optional | Any Ollama model (e.g. gemma3, llama3.2) |
For Local mode, set the base URL to your Ollama or LM Studio endpoint (default: http://127.0.0.1:11434/v1). Pinodock will call /models to verify the connection and list available models. Everything stays on your device — no API key required.
// Local Ollama profile setup
Provider: Local (OpenAI API)
Base URL: http://127.0.0.1:11434/v1
Model: gemma3:4b ← or llama3.2, phi4-mini, etc.
Max tokens: 512
API key: (leave blank)
// LM Studio profile setup
Provider: Local (OpenAI API)
Base URL: http://127.0.0.1:1234/v1
Model: lmstudio-community/gemma-3-4b-it-GGUF
API key: lm-studio ← LM Studio requires any non-empty string
Switch between profiles at any time from the AI panel. The active profile is used for all AI actions: the command palette AI query, document summarisation, and in-page context answers.
14. Workspace presets FREE
A workspace preset is a named group of URLs. Activating a preset opens all URLs as new tabs in one click. Create them in Settings → Workspaces → Add Preset.
// Preset: Morning routine
Name: Morning Icon: ☀️
URLs:
https://mail.google.com
https://calendar.google.com
https://linear.app/YOUR_WORKSPACE/my-issues
https://github.com/notifications
// Preset: Deep work (no distractions)
Name: Deep Work Icon: 🎯
URLs:
https://www.notion.so/YOUR_WORKSPACE
https://docs.google.com
// Preset: Code review
Name: Review PRs Icon: 🔍
URLs:
https://github.com/YOUR_ORG/YOUR_REPO/pulls?q=is:open+review-requested:@me
https://github.com/YOUR_ORG/YOUR_REPO/actions
// Preset: Weekly planning
Name: Weekly Plan Icon: 📅
URLs:
https://calendar.google.com
https://linear.app/YOUR_WORKSPACE/projects
https://docs.google.com/spreadsheets/d/YOUR_OKR_SHEET
15. Todos, habits, and focus mode FREE
Todos are accessible from the command palette (⌘K → "todo" → press enter on "Open Todos") or from the Todo widget on your dashboard. Each task has a title, status (Todo / In Progress / Done), priority (Low / Medium / High), and an optional due date.
Recurring todos — tasks that reset daily, weekly, or monthly — are created from the recurring toggle inside any todo item. They re-open automatically on their cadence without any action from you.
Habits live on the Habits panel. Each habit shows a streak counter and a weekly completion heatmap. The number of days shown in the heatmap is configurable. A habit reminder notification can be scheduled from Settings → Reminders.
Focus mode is a toggle in Settings or accessible via the command palette. When on, it hides all non-essential dashboard elements and dims background content, leaving only your active timer and current task visible. Toggle off anytime.
18. Dock — favicon icons, preset packs, and overflow stacks
The dock at the bottom of the new tab now shows two sections separated by a thin divider: your built-in navigation shortcuts on the left, and your custom site icons on the right. Every site you add appears as a real favicon — not an emoji.
Click the + button at the right end of the dock to open the dock customizer. Six preset packs let you add an entire category of sites at once:
| Pack | Sites |
|---|---|
| 🎬 Streaming | Netflix, YouTube, Spotify, Twitch, Disney+, Prime Video, Apple TV+, Max |
| 🌐 Social | X/Twitter, Instagram, Facebook, TikTok, Reddit, LinkedIn, Pinterest |
| 💬 Messaging | WhatsApp Web, Telegram, Discord, Slack, Messenger, Gmail, Outlook |
| 💻 Dev | GitHub, Stack Overflow, MDN, npm, CodePen, Vercel |
| ⚡ Productivity | Notion, Figma, Linear, Calendar, Drive, Trello |
| 📰 News | Hacker News, BBC, The Guardian, Reuters |
The dock has a visible limit per size setting (small: 7, medium: 9, large: 6). Any sites beyond the limit collapse into an overflow stack button — a 2×2 favicon grid. Click it to open a popover showing all overflow sites.
Moving your cursor over the dock activates macOS-style magnification — icons scale continuously based on cursor proximity, growing in the direction away from the dock edge (upward for a bottom dock).
Dock settings (Settings → Dashboard): position (bottom/left/right), size (small/medium/large), and auto-hide (slides off-screen, reappears when the cursor nears the edge).
→ Full guide: customizing the Pinodock dock
19. Projects and Tags — organise your research
Every piece of content in Pinodock — highlights, reading list items, snippets, and todos — can now be assigned to a Project. A Project is a named container with an emoji and a color. It groups items across content types so you can see everything related to a client, subject, or side project in one view.
Open the Projects tab (📁 in the sidebar) to create and manage projects. The overview shows a card grid; click any card to open the project's detail view: all four content types together, filtered to that project.
To assign an item to a project, open the Highlights, Snippets, Reading, or Todos panel, find the item, and click ▼ tag / project to expand its assignment controls. Select a project from the picker dropdown.
Tags are secondary free-form labels added to individual items. Type in the tag input and press Enter. Tags appear as colored pills and can be filtered within the project detail view. Use tags for sub-context within a project: status (urgent, done), category (frontend, citation), or person (alice).
→ Full guide: Projects and Tags in Pinodock
20. Smart palette — context bubbles and recently used
When you open the new tab launcher (⌘K) without typing anything, two things appear below the input:
Context bubbles — five one-click navigation shortcuts: Todos, Reading, Snippets, Highlights, Clipboard. Click any to jump to that panel instantly.
Recently used — the last five commands or items you activated, sorted by recency. Click to re-run. Useful for commands with arguments you want to repeat with a slight variation.
Search results are ranked by a three-factor formula: fuzzy match quality (55%), usage frequency (30%), and recency (15%). Items you use often float to the top of results automatically — no configuration needed.
→ Full guide: the smart context-aware palette
21. Page actions — highlight, screenshot, reader mode
The on-page command palette (⌘Shift+P on any website) now includes two new actions in its quick-action grid:
🖊 Highlight — if text is selected on the page when you open the palette, clicking Highlight saves that text as a Pinodock highlight: the selected text, surrounding context, page URL, title, and timestamp. It appears immediately in your Highlights panel and can be assigned to a project.
📸 Screenshot — captures the visible tab as a PNG using Chrome's captureVisibleTab API and opens the result in a new tab for saving or copying.
These join the existing page actions: Copy URL, Copy Markdown, Reader Mode, QR Code, UTM Builder, Pick Color, and Encode URL. All nine actions are available by keyboard number (1–9) when the palette is open and the input is empty.
22. Pro sync — highlights and todos across devices
Pinodock Pro users can enable cross-device sync via Firestore (Settings → Account → Enable sync). The following data syncs when you're signed in on multiple Chrome profiles:
| Synced | Not synced (privacy) |
|---|---|
| Highlights (text, color, URL, tags, project) | Clipboard history |
| Reading List (title, URL, tags, project) | AI chat sessions |
| Snippets (title, content, tags, project) | Command frequency data |
| Todos (text, status, priority, tags, project) | Browser history |
| QuickLinks / Dock sites | |
| Project definitions |
Settings sync automatically via chrome.storage.sync (Chrome handles this natively without sign-in). The Pro Firestore sync layer handles content, not settings.