IO Platform Documentation
Project IO · Chrome Extension · Documentation

IO Marketing OS
Chrome Extension

Capture any webpage, analyze it through the IO Marketing OS framework, and build a live intelligence library — all from your browser toolbar.


Installation · Features · Workflows · Troubleshooting
3Minutes to install
4Core features
100Pages saved locally
4Analysis modes

The IO Chrome Extension sits in your browser toolbar and turns any webpage into an IO Marketing OS intelligence input. One click extracts the page's full structure — title, headings, word count, body text — and prepares it for analysis through the IO Platform's URL Intelligence Engine.

It does not require an account, does not send data to any server without your action, and stores your capture library locally in Chrome's storage. The analysis happens on demand through the IO Platform, where you control what gets sent and when.

Start Here
Installation Guide
Four files, five steps, three minutes. How to install the extension in Chrome without the Web Store.
Getting Started
Your First Analysis
Walk through analyzing a competitor page from first click to IO framework insight.
Feature
Analyze This Page
The primary action — extracts page structure and prepares it for IO Platform analysis.
Feature
Save to Library
Quick-save any page for later analysis. Builds your competitive intelligence archive.
Feature
Right-Click Context Menu
Right-click any page, link, or selected text — "Analyze with IO Marketing OS" appears in the context menu.
Workflow
Full Analysis Workflow
Extension → IO Platform → four analysis modes → actionable IO framework recommendations.
Help
Common Errors & Fixes
The ten most common issues and their solutions — from CORS errors to permission blocks.
Help
FAQ
Does it work on paywalled sites? Where is my data stored? Fifteen common questions answered.
Getting Started · 01

Installation Guide

The extension installs directly in Chrome without requiring the Chrome Web Store — a process called "unpacked installation." It takes three minutes and four files.


Developer Mode · Load Unpacked · Four Files · Three Minutes

Because the IO Chrome Extension is not listed in the Chrome Web Store, it is installed as a developer extension. This is completely normal for internal tools, enterprise extensions, and extensions in active development. The process is supported natively by Chrome and takes no technical knowledge beyond following the steps below.

Before you start: You need four files — manifest.json, popup.html, popup.js, and background.js. All four are available in the IO Platform under the Chrome Extension tab, with copy buttons. You do not need an icon file; Chrome will use a default icon.
1
Create the extension folder
Create a new folder on your computer named io-extension. Place it somewhere permanent — your Desktop, Documents, or a dedicated dev folder. Do not move this folder after installation, or Chrome will lose the extension.
mkdir ~/Documents/io-extension
2
Copy the four files
Go to the IO Platform → Chrome Extension tab. Copy each of the four files using the Copy button and save them as text files in your io-extension folder with the exact filenames shown.
manifest.json
popup.html
popup.js
background.js
3
Open Chrome Extensions
In Chrome, navigate to the Extensions management page. You can do this three ways:
  • Type chrome://extensions in the address bar and press Enter
  • Menu (⋮) → Extensions → Manage Extensions
  • Keyboard: +Shift+E (Mac) or Ctrl+Shift+E (Windows)
4
Enable Developer Mode
In the top-right corner of the Extensions page, find the "Developer mode" toggle and switch it ON. The page will expand to show additional developer options — this is expected. Developer mode allows Chrome to load unpacked extensions from local folders.
5
Load the extension
Click the "Load unpacked" button that appeared after enabling Developer mode. A file picker will open. Navigate to and select your io-extension folder — select the folder itself, not any file inside it. Click Open (or Select Folder on Windows). The IO Chrome Extension will appear in your extensions list.
Pin it to your toolbar: After installation, click the puzzle-piece icon in the Chrome toolbar to see all extensions. Find "IO Marketing OS" and click the pin icon to keep it visible in the toolbar at all times.

Verifying installation

After installation, you should see the IO Marketing OS extension card in your Extensions list. Navigate to any webpage, click the IO icon in the toolbar — the popup should appear with the current page's URL displayed. If it opens but shows an error, see the .

Updating the extension

When new versions of the extension files are released, copy the updated files into your io-extension folder (replacing the old ones), then go to chrome://extensions and click the refresh icon on the IO Marketing OS card. No need to re-install from scratch.

Getting Started · 01 of 03
Getting Started · 02

Permissions Explained

Chrome extensions require explicit permissions to function. The IO extension requests four — each with a specific, limited purpose. No data is sent to any external server without a deliberate user action.


activeTab · storage · scripting · contextMenus
Permission Reference
What Each Permission Does
PermissionWhat it accessesWhy it's neededWhat it cannot do
activeTabThe tab you are currently viewing, only when you click the extension iconReads the URL and title of the current tab to display in the popupCannot access any tab you haven't clicked the icon on; cannot run in background
storageChrome's local browser storage on your deviceSaves your capture library (up to 100 pages) locally without a server or accountStays on your machine; not synced to Google or any external service
scriptingAbility to run JavaScript on the active page when triggeredExtracts headings, body text, and word count from the current page when you click "Analyze"Only runs when you explicitly click Analyze; cannot run automatically
contextMenusThe right-click menu in ChromeAdds the "Analyze with IO Marketing OS" option to the right-click context menuOnly adds one menu item; cannot intercept other context menu actions
Privacy by design: The extension does not communicate with any external server. Your captured pages are stored only in Chrome's local storage on your device. Analysis happens when you paste a URL into the IO Platform — that action calls the Anthropic API, which you control.

The host_permissions field

The manifest includes "host_permissions": ["<all_urls>"]. This sounds broad — it means the extension can theoretically run on any URL — but in practice it is constrained by the other permissions. The scripting permission only executes when you click "Analyze This Page," and activeTab limits that to the tab you are currently looking at. The broad host permission is needed because the URLs of the sites you might want to analyze are not known in advance.

Reviewing what's stored

To see everything the extension has stored: open the Chrome DevTools console on any page, type chrome.storage.local.get(null, console.log), and press Enter. You will see the full contents of the local storage — your capture library and any pending analysis URLs. You can clear it all with chrome.storage.local.clear().

Getting Started · 02 of 03
Getting Started · 03

Your First Analysis

A complete walkthrough — from clicking the IO icon on a competitor's page to reading your first IO framework analysis in the Platform.


End-to-End Walkthrough · Extension → Platform → Insight

This walkthrough uses a real competitor's blog post as the example. The same flow works for any public webpage: a competitor's homepage, a piece of content you want to benchmark, a client's website, or an article you want to reverse-engineer.

The complete workflow

1
Navigate to the target page
Go to the competitor's blog post, homepage, or any page you want to analyze. In this example: a competitor's content marketing strategy page. Make sure the page has fully loaded — wait for all visible content to appear before proceeding.
2
Click the IO icon in the toolbar
Click the IO Marketing OS extension icon in the Chrome toolbar. The popup opens. You will see the current page's URL displayed at the top in grey monospace text, confirming the extension has recognized the page.
3
Click "Analyze This Page"
Click the primary black button — "Analyze This Page." The extension runs a content script that extracts the page's structure: title, meta description, H1 and H2 headings, and approximately the first 3,000 words of body text. This takes 1–2 seconds and happens entirely in your browser.
4
Read the capture summary
The popup displays a capture summary: the page's title, word count, H1 headings, and the top H2 headings — giving you an immediate structural sense of the content. The page is also saved to your capture library automatically.
5
Copy the URL and open the IO Platform
The popup shows the page's URL at the bottom of the capture summary. Copy it (it's also still in the browser address bar). Open the IO Platform in a new tab and go to URL Intelligence.
6
Paste the URL and choose your analysis mode
Paste the URL into the IO Platform's URL Intelligence input. Choose your analysis mode — Full IO Analysis, SEO+GEO Audit, Competitive Analysis, or Content Gap Finder. Click Analyze.
7
Read your IO framework analysis
In 15–20 seconds, the platform scrapes the URL and returns a structured IO framework analysis: fit score, content gaps, strongest elements, specific improvement recommendations, and the relevant IO series and articles. Copy the report or use it directly to brief your content team.

"The extension is not the analysis — it is the capture mechanism. The intelligence lives in the IO Platform. The extension makes capturing fast enough that it becomes a habit."

Getting Started · 03 of 03
Core Features · 04

Analyze This Page

The primary feature — one click extracts the complete structural content of any webpage and prepares it for IO framework analysis. Here is exactly what it captures and how.


Content Extraction · What Gets Captured · How the Script Works

When you click "Analyze This Page," the extension injects a short content script into the active tab. The script strips non-content elements (scripts, styles, navigation, footers, headers, sidebars), then extracts the meaningful content. The extraction runs in milliseconds in your browser — nothing is sent to a server at this stage.

What gets extracted

Always captured
Page URL
Document title (<title> tag)
Meta description
All H1 headings (up to 5)
First 12 H2 headings
First 10 H3 headings
Body text (first ~3,000 words)
Estimated word count
Stripped before capture
All <script> tags
All <style> tags
<nav> elements
<header> elements
<footer> elements
<aside> elements
role="navigation" elements
<noscript> blocks
Saved to library
URL + title
Timestamp (ISO format)
Source ("analyze" or "quick-save")
Stored in chrome.storage.local
Max 100 entries (FIFO)
Persists across browser sessions

The popup display after capture

After extraction, the popup shows a formatted summary in monospace text: the page title, word count, H1 headings, and the top five H2 headings. This gives you an immediate read on the page's structure before opening the IO Platform for full analysis. The URL is shown at the bottom — ready to copy.

What the capture does not do

The capture does not: access pages other than the one you are currently viewing; run without you clicking the button; log your browsing history; send any data to a server; capture paywalled or login-protected content (it reads only what the page renders publicly); or store images, CSS, or any non-text content.

Single-page applications: Some modern sites (React, Vue, Next.js) render content dynamically. If the capture returns minimal headings on a content-heavy page, scroll down to trigger lazy-loading, wait a moment, then click Analyze again. The script reads the current DOM state — it sees whatever the browser has rendered at the moment of click.
Core Features · 04 of 07
Core Features · 05

Save to Library

Quick-save any page to your local capture library without running a full extraction. Use it while browsing to bookmark pages for later analysis — build your competitive intelligence archive one click at a time.


Quick Save · Capture Library · Local Storage · 100 Pages

The "Save to Library" button is the lightweight alternative to "Analyze This Page." Where Analyze runs a full content script extraction, Save to Library records only the URL, tab title, and a timestamp — making it near-instant and usable even on pages where scripting is restricted.

Use it when: you are actively browsing and find a page worth analyzing later; you want to batch-collect competitor pages for a competitive intelligence sprint; or you are on a page where full extraction doesn't work but you want to remember the URL.

What gets saved

Storage Schema
Capture Library Entry Format
FieldValueSource
urlThe full page URL including query parameterschrome.tabs API
titleThe tab's title as shown in the browserchrome.tabs API
savedAtISO 8601 timestamp of when Save was clickednew Date().toISOString()
source"quick-save" (from button) or "analyze" (from full extraction)Extension logic

Library limits and rotation

The library holds up to 100 entries. When the limit is reached, the oldest entry is removed automatically (first-in, first-out). The library persists across browser sessions — it survives closing and reopening Chrome. It is cleared if you uninstall the extension or manually clear extension storage.

Accessing your library

The popup displays your current library count in the footer area ("12 pages in library"). To view the full library contents, open Chrome DevTools (F12) on any page, go to the Console tab, and type:

Chrome DevTools Console
chrome.storage.local.get(['io_captures'], (data) => {
  console.table(data.io_captures);
});

This outputs your full capture library as a formatted table in the console — sortable by URL, title, timestamp, or source. To clear the library: chrome.storage.local.remove(['io_captures']).

Core Features · 05 of 07
Core Features · 06

Right-Click Context Menu

Right-click any page, any link, or any selected text to trigger IO analysis without opening the toolbar popup. The fastest way to analyze a page you have not visited yet.


Context Menu · Right-Click · Background Service Worker · Link Analysis

The context menu integration is provided by the background service worker (background.js). When Chrome starts, the service worker registers an "Analyze with IO Marketing OS" option in the right-click context menu. This option appears in three contexts:

Right-click on page
Analyzes the current page
Same URL as the browser address bar
Saves URL for IO Platform analysis
Opens popup with result
Right-click on a link
Captures the link's href URL
Does not navigate to the link
Stores URL in io_pending_analysis
Opens popup for confirmation
Right-click on selection
Uses current page URL
Selection text not captured
Functions the same as page right-click
Future: selection analysis planned

The pending analysis flow

When you right-click a link and choose "Analyze with IO Marketing OS," the extension saves the link's URL to io_pending_analysis in local storage, then opens the popup. The next time you open the popup, it can read this pending URL and pre-populate the analysis. Copy the URL from the popup and paste it into the IO Platform URL Intelligence tool for full analysis.

Where the option appears

The context menu option appears on all pages by default — the extension does not filter by domain or content type. It does not appear on Chrome's internal pages (chrome:// URLs) or the Chrome Web Store, which are protected by the browser. On pages where the extension does not have permission to inject scripts (rare, for certain enterprise-managed pages), the menu item appears but the analyze action may fail gracefully.

Right-click on links to pre-capture competitor pages: If you are reading a roundup article that links to ten competitor tools, right-click each link → "Analyze with IO Marketing OS" → the URL is captured without navigating away. Batch-collect competitor URLs while staying on the source page.
Core Features · 06 of 07
Core Features · 07

The Capture Library

Your capture library is the persistent archive of every page you have saved or analyzed. It is stored locally in Chrome, survives browser restarts, and holds up to 100 entries — a rolling competitive intelligence queue.


Local Storage · 100-Entry Archive · Batch Analysis · Export

Think of the capture library as your IO analysis inbox. As you browse — reading competitors' blogs, checking backlink sources, reviewing industry publications — you save pages to the library. Later, in a dedicated analysis session, you open each saved URL in the IO Platform and run the analysis mode most relevant to that source.

Managing your library

Library Operations
Common Library Commands (Chrome DevTools Console)
OperationCommand
View all entrieschrome.storage.local.get(['io_captures'], d => console.table(d.io_captures))
Count entrieschrome.storage.local.get(['io_captures'], d => console.log(d.io_captures?.length))
Export as JSONchrome.storage.local.get(['io_captures'], d => console.log(JSON.stringify(d.io_captures, null, 2)))
Clear all entrieschrome.storage.local.remove(['io_captures'])
Remove one entrychrome.storage.local.get(['io_captures'], d => { d.io_captures.splice(0,1); chrome.storage.local.set({io_captures: d.io_captures}) })

Using the library for competitive sprints

A competitive intelligence sprint using the IO extension: over one browsing session, right-click and save 15–20 competitor pages, blog posts, and landing pages. End of the session: 20 entries in the library. Next day: open each URL in the IO Platform URL Intelligence tool, run Competitive Analysis mode, copy each report. In 30–45 minutes you have 20 structured IO framework analyses of your competitive landscape.

The 100-entry limit

Chrome's storage.local has a 5MB default quota. The 100-entry limit is a precautionary cap set in the extension code — at typical page metadata sizes, 100 entries uses roughly 50–100KB, well within the quota. If you need more than 100 entries, export the current library to JSON (using the command above), clear it, and continue capturing.

Core Features · 07 of 07
IO Platform Integration · 08

The Full Analysis Workflow

Extension and Platform are two parts of one workflow. Neither is the complete system on its own. This is how they work together — from browser toolbar to actionable IO framework insight.


Extension → IO Platform → Analysis Mode → Insight → Action

The extension handles capture: extracting URLs and basic structure from any page, anywhere on the web, with one click. The IO Platform handles intelligence: running the captured URL through the full IO framework using Claude Sonnet 4, producing structured analysis in one of four modes. The two tools are designed to be used in sequence, not in isolation.

The complete workflow

Workflow Reference
Extension → Platform → Action
StageToolActionOutput
CaptureChrome ExtensionClick icon → "Analyze This Page"Page URL + structural summary in popup
QueueChrome ExtensionRight-click → "Save to Library" while browsingURLs saved to local library for batch processing
ScrapeIO Platform · URL IntelligencePaste URL → click AnalyzeFull page content extraction via CORS proxy
AnalyzeIO Platform · Claude APISelect analysis mode → runStructured IO framework analysis (15–20 seconds)
ActIO Platform · Content BuilderUse gaps identified → generate contentIO-formatted article HTML ready to paste
Buildio-complete.htmlPaste generated HTMLNew content live in the editorial site

"The intelligence loop: capture with the extension, analyze in the platform, generate in the content builder, publish to the editorial site. Each stage feeds the next. The loop runs continuously."

Using analysis results to brief content production

The most productive use of a URL Intelligence analysis: take the "Content Gaps" section of the IO Full Analysis and paste it directly into the IO Platform Content Builder as the topic. The Content Builder receives the gap description and generates a complete IO-formatted article addressing that exact gap. From competitive intelligence to published content in under 30 minutes.

IO Platform · 08 of 10
IO Platform Integration · 09

The URL Intelligence Engine

The IO Platform's URL Intelligence tool scrapes any URL and maps its content to the IO Marketing OS framework. It is the destination for URLs captured by the extension.


CORS Proxy Scraping · Four Analysis Modes · Claude Sonnet 4 · Copy Reports

The URL Intelligence Engine uses allorigins.win as a CORS proxy to fetch public webpage content from the browser — bypassing the Same-Origin Policy that prevents direct browser-to-URL fetching. This means it works on any public URL without requiring a server. The fetched HTML is cleaned (scripts, styles, and navigation stripped), parsed into structural components, and sent to Claude Sonnet 4 along with the selected analysis mode's system prompt.

What the engine analyzes

The engine sends the following to Claude for analysis: the full page URL, the document title and meta description, all H1/H2/H3 headings, and up to 4,500 words of body content. This gives the model enough context to run a substantive IO framework analysis without hitting token limits.

Limitations of the CORS proxy approach

The proxy approach works on most public pages but has edge cases: heavily JavaScript-rendered sites may return incomplete HTML (the proxy sees server-rendered HTML, not post-JavaScript content); pages behind paywalls or login walls return only the gating content; some sites actively block proxy requests and return a 403 or a bot-detection page. For pages that fail, use the extension's extraction (which runs in your actual browser, past any rendering) and manually note the URL for analysis of the extracted content.

When scraping fails: Use the extension on the page directly (which runs in your logged-in browser, past any soft gates), copy the URL, and then note the extracted headings and content visible in the extension popup. Paste the URL into the IO Platform — even if the proxy scrape is thin, you can supplement the analysis by typing additional context into the directive field.
IO Platform · 09 of 10
IO Platform Integration · 10

The Four Analysis Modes

Each mode sends a different system prompt to Claude, framing the same page content through a different IO framework lens. Choose the mode that matches your intelligence objective before clicking Analyze.


Full Analysis · SEO+GEO · Competitive · Content Gap
Mode Reference
Analysis Mode Selection Guide
ModeBest used whenKey output sectionsPrimary IO series
Full IO AnalysisYou want a comprehensive first look at a page — overall fit, gaps, and recommendationsFit score · Content gaps · Strengths · Top 5 improvements · Relevant IO articlesAll 13 series
SEO + GEO AuditYou want to benchmark a page's search architecture and AI search readinessTechnical SEO rating · Topic cluster assessment · Entity SEO · GEO readiness · AEO coverageSeries 04 (seo1–seo9)
Competitive AnalysisYou are analyzing a competitor's page and want strategic counter-positioningTheir positioning · Content strategy · Channel mix · Weaknesses · 3 counter-movesSeries 07, 09, 12
Content Gap FinderYou want a specific list of missing content with IO article references for each gapCritical gaps · Thin content · Missing formats · Journey stage gaps · Quick wins vs strategic gapsSeries 01, 04, 05

Running multiple modes on the same URL

There is no cost to running multiple modes on the same URL — each call is a separate API request, and the URL is scraped fresh each time (the IO Platform does not cache scrape results). For a comprehensive competitive analysis, run both "Competitive Analysis" (for strategic positioning insights) and "Content Gap Finder" (for tactical content opportunities) on the same competitor URL. Copy both reports and cross-reference them.

Reading the fit score

The Full IO Analysis mode returns a fit score from 0–100 with a one-sentence rationale. This is Claude's assessment of how well the page's content architecture aligns with IO Marketing OS standards — it is a directional benchmark, not a precise metric. Pages scoring above 70 have strong content foundations; pages below 40 have significant structural gaps. Use the gap list, not the score, to prioritize action.

IO Platform · 10 of 10
UI Reference · 11

Popup UI Walkthrough

Every element of the extension popup — what it shows, what it does, and what the status messages mean.


Popup Anatomy · Status States · Button Behaviors · Error Messages

The popup is a 340px-wide HTML interface that opens when you click the IO icon. It is built from a single popup.html file and controlled by popup.js. Understanding each element prevents confusion when the popup behaves unexpectedly.

The popup UI — annotated

IO Marketing OS — Chrome Extension Popup
Project IO
IO Marketing OS
https://competitor.com/blog/content-marketing-2025
Analyze This Page
Save to Library
✓ Saved. Library: 8 pages.
CAPTURED FOR IO ANALYSIS ───────────────────── Title: The Complete Guide to Content Marketing Words: 3,421 H1: Content Marketing in 2025 Top H2s: · What is Content Marketing? · Building Your Strategy · Distribution Channels · Measuring Success → Paste this URL into IO Platform: https://competitor.com/blog/content-marketing-2025
8 pages saved in library
UI Element Reference
Every Element in the Popup
ElementWhat it showsState when empty / loading
Header "Project IO" labelStatic branding — always "Project IO" and "IO Marketing OS"Always visible
URL bar (grey monospace)The current tab's URL, truncated with ellipsis if longShows "Loading..." briefly on popup open
Analyze This Page (black button)Primary action — triggers full content extractionDisabled with opacity 0.4 while analysis is running
Save to Library (outlined button)Quick save — records URL and title onlyAlways enabled
Status line (amber text)Progress messages during analysis; confirmation after saveEmpty between actions
Result block (monospace box)The capture summary — title, word count, headings, URLHidden until first analysis
Library count (small grey footer)"N pages saved in library" — updates after save or analyzeHidden when library is empty

Status message guide

During analysis
"Extracting page content..." — script injecting
"Content captured — opening IO Platform..." — success
"Saved. Library: N pages." — after quick save
Error states
"Error: Cannot access chrome:// URLs" — Chrome internal page
"Error: Frame was removed" — page navigated during analysis
"Error: Extension context invalidated" — extension was reloaded; refresh and try again
UI Reference · 11 of 12
UI Reference · 12

Keyboard Shortcuts

Chrome extension keyboard shortcuts speed up capture during active research sessions. Most are Chrome defaults; one is IO-specific.


Keyboard Navigation · Custom Shortcuts · Chrome Defaults
Shortcut Reference
Keyboard Shortcuts
ActionMacWindows / LinuxSource
Open popup Shift ECtrl Shift EChrome default (last extension)
Open Extensions page Shift E (then click Manage)Ctrl Shift EChrome default
Open Chrome DevTools Option IF12Chrome default
Reload extension (after file update)Go to chrome://extensions → click ↻SameManual — no shortcut
Analyze current page (popup open)Tab to "Analyze" → EnterSameStandard HTML tab order
Save to library (popup open)TabTabEnterSameStandard HTML tab order

Setting a custom shortcut

Chrome allows custom keyboard shortcuts for extension actions. To set one: go to chrome://extensions/shortcuts, find "IO Marketing OS," and assign a shortcut for "Activate the extension." Recommended: +Shift+I (for "IO"). This opens the popup on any page with the shortcut.

How to add a shortcut command to manifest.json
// Add this to manifest.json (inside the root object)
"commands": {
  "_execute_action": {
    "suggested_key": {
      "default": "Ctrl+Shift+I",
      "mac": "Command+Shift+I"
    },
    "description": "Open IO Marketing OS"
  }
}

After adding this to manifest.json, reload the extension at chrome://extensions. The shortcut will be active on the next popup open.

UI Reference · 12 of 12
Troubleshooting · 13

Common Errors & Fixes

The ten errors that appear most frequently — each with a diagnosis and a specific fix, not generic troubleshooting steps.


Error Diagnosis · Specific Fixes · Edge Cases
Error Reference
Common Errors and Fixes
Error message / SymptomCauseFix
Extension icon is greyed outYou are on a chrome:// page, the Chrome Web Store, or a PDFNavigate to a normal webpage. Chrome disables extensions on its own pages by design.
"Extension context invalidated"The extension was reloaded (after a file update) but the popup was still openClose the popup, reload the page you were on, then click the icon again.
"Frame was removed"The page navigated away while the script was runningWait for the target page to fully load before clicking Analyze.
Popup opens but URL shows blankRace condition between tab query and popup render on very fast machinesClose and reopen the popup. The URL query runs on popup open; reopening triggers it again.
Analyze returns no headingsPage is client-rendered (React/Vue/Next.js) and headings aren't in the initial HTMLScroll the page to trigger rendering, wait 2 seconds, click Analyze again.
Result box shows generic contentSite uses anti-scraping that injects fake H2s or replaces body content with CAPTCHAThe extension captures what Chrome renders. If Chrome shows you the real content, the extension captures it. If Chrome shows a CAPTCHA, the extension captures that instead. Solve the CAPTCHA and retry.
IO Platform scrape returns 403The target site blocks the allorigins.win proxyUse the extension's popup summary (title, headings) as your analysis context instead. The extension runs in your browser and bypasses scraper blocks.
"Cannot access chrome:// URL"Expected — Chrome's protected pages are inaccessible to extensionsNavigate to a normal http:// or https:// page to use the extension.
Context menu option missingBackground service worker crashed or did not startGo to chrome://extensions → find IO Marketing OS → click the "Service Worker" link → if it shows an error, reload the extension.
Library count not updatingchrome.storage.local write failed (rare, usually quota-related)Open DevTools console → run chrome.storage.local.getBytesInUse(null, console.log) to check quota. If near 5MB, export and clear the library.

Checking the service worker health

If the context menu is missing or the extension behaves erratically, inspect the background service worker: go to chrome://extensions, find the IO Marketing OS card, and click the "Service Worker" link in the extension details. This opens a DevTools window for the service worker — the Console tab shows any errors. The most common: a syntax error in background.js from a copy-paste issue. Fix the file, reload the extension.

Troubleshooting · 13 of 15
Troubleshooting · 14

Site Compatibility

Not all websites work the same way. Here is how the extension handles the major website architectures it will encounter.


SSR vs CSR · Paywalls · SPAs · Enterprise Sites
Works fully
Standard HTML/CSS websites
WordPress blogs and sites
Server-rendered pages (SSR)
Substack and Ghost newsletters
LinkedIn public profiles and posts
Most marketing/landing pages
Documentation sites (GitBook, Readme)
Works partially
Next.js/Nuxt.js (SSR mode: full; CSR mode: partial)
React SPA after hydration (scroll to trigger)
Lazy-loaded content (scroll first)
Soft-gated content (captures above the fold)
Infinite scroll pages (captures only what's loaded)
Does not work
Chrome internal pages (chrome://)
Hard paywalls (NYT, WSJ, etc.)
Login-required pages (unless you are logged in)
Local files (file://)
PDF files opened in Chrome
Chrome Web Store pages

LinkedIn and social platforms

The extension works on LinkedIn public pages — company pages, public posts, public profiles — because Chrome renders the full content when you are logged in. It captures the visible text, headings, and structure. For Twitter/X and Facebook, it captures whatever the page renders before any "Show more" expansions. The captures may be shorter than the full content but are sufficient for structural analysis.

Handling soft paywalls

Many publications (Medium, Substack paid) allow a limited number of free reads. If you have access to a page (the full content is visible in your browser), the extension captures it — because it reads what your browser has rendered, not what the server would show to an anonymous request. The IO Platform's proxy scraper operates as an anonymous request and will see only the gating screen; the extension sees the full article. Use the extension for soft-gated content.

Troubleshooting · 14 of 15
Troubleshooting · 15

FAQ

Fifteen questions that come up consistently — about data, privacy, capabilities, and practical use.


Data · Privacy · Capabilities · Practical Use

Does the extension send my browsing history anywhere?

No. The extension only runs when you explicitly click a button. It does not monitor your browsing, does not send data in the background, and does not communicate with any external server. Your capture library stays on your machine in Chrome's local storage.

Does it work in Incognito mode?

Not by default. Chrome prevents extensions from running in Incognito unless you explicitly allow it. To enable: go to chrome://extensions → IO Marketing OS → Details → toggle "Allow in Incognito." Data saved in Incognito does not persist after the Incognito window closes.

Can I use it on multiple computers?

Yes, but the capture library does not sync between computers — it is stored in local Chrome storage, not synced Chrome storage. You would need to install the extension on each computer and maintain separate libraries. The captured URLs are the portable part: they work anywhere.

Will Chrome warn me that this extension can "read and change data on all websites"?

Yes. This warning appears because of the host_permissions: <all_urls> field in the manifest — Chrome warns users about extensions that can run on any site. This is the same warning shown for most developer extensions. The actual data read is limited to what you trigger manually. The warning is accurate but broad — it describes the potential permission, not the actual behavior.

How do I know the extension is not doing something I cannot see?

The extension's code is fully visible to you — it is the four files you installed. background.js only registers the context menu item. popup.js only runs when the popup is open and you click a button. You can inspect both files at any time. You can also monitor extension network activity in Chrome DevTools (Network tab) — you will see no requests initiated by the extension itself.

Can it capture PDFs?

No. Chrome renders PDFs through its built-in PDF viewer, which is treated as a protected context that extensions cannot inject scripts into. To analyze a PDF's content, download it, extract the text manually, and paste key sections into the IO Platform's Content Builder directive field.

Does it work on the IO Platform itself (recursive capture)?

Yes. You can click "Analyze This Page" on the IO Platform and the extension captures its structure. This is not particularly useful for analysis, but it works. The IO editorial site (io-complete.html) can also be analyzed if hosted at a public URL.

Why is the capture library limited to 100 entries?

Chrome's storage.local has a 5MB default quota. The 100-entry cap is conservative — a precautionary limit. At typical page metadata sizes, 100 entries uses roughly 50–100KB. If you regularly need more, export the library as JSON and clear it to reset. A future version may increase the limit or add export/import functionality.

Can I share my capture library with a colleague?

Not directly — the library is in Chrome's local storage, which is not accessible from outside the browser. To share: export the library as a JSON array (see the Library page), send the JSON file, and have your colleague import it. There is no native import function in the current version; they would run chrome.storage.local.set({io_captures: [paste JSON array here]}) in their DevTools console.

Does capturing a page trigger any analytics or notifications on the target site?

The extension reads the DOM as Chrome has already rendered it — it does not make additional requests to the server. From the target site's perspective, only the normal page load event occurred. The extraction is invisible to the target site's analytics.

Can I analyze pages that require login?

If you are logged in to a site in Chrome, the extension can capture that page's content — because Chrome has rendered the full authenticated view. The extension reads what you see. What it cannot do is log you in to a site automatically or capture content that requires authentication you do not have.

Will it work on the next version of Chrome?

The extension is built to Manifest V3, which is Chrome's current and long-term supported extension format. Chrome deprecated Manifest V2 in 2024. MV3 extensions will continue to be supported for the foreseeable future.

How long does the Analyze action take?

The content extraction (in the extension) takes under 2 seconds on most pages. The IO Platform analysis (Claude API call) takes 15–25 seconds depending on API load and response length. Total time from click to IO framework analysis: under 30 seconds.

Can I modify the extension for my own use?

Yes — the files are yours. Common modifications: add additional content extraction fields to popup.js, modify the context menu label in background.js, change the popup dimensions in popup.html, or add your own IO Platform URL to the context menu action. Reload the extension after any file change.

Does it work on Brave, Edge, or other Chromium browsers?

Yes. Brave, Microsoft Edge, Opera, and most other Chromium-based browsers support Chrome extensions. Load it the same way — Developer Mode → Load Unpacked. The extension uses standard Chrome Extension APIs that are supported across all Chromium browsers.

Troubleshooting · 15 of 15
Reference · 16

File Reference

Complete documentation for each of the four extension files — what each does, what each contains, and how they interact.


manifest.json · popup.html · popup.js · background.js
File Reference
The Four Extension Files
FilePurposeRuns whenCommunicates with
manifest.jsonExtension configuration — declares permissions, file references, metadata, and versionAt install time and on each Chrome restartChrome browser (configuration file, not executable)
popup.htmlThe UI markup — defines the visual structure of the popup windowLoaded when the popup opens (each click of the toolbar icon)Loads popup.js
popup.jsAll popup logic — tab URL display, content extraction, library save, status updatesExecutes when popup.html loads; runs for the duration the popup is openchrome.tabs, chrome.scripting, chrome.storage APIs
background.jsService worker — registers context menu item on install; handles context menu clicksOn Chrome startup; wakes on context menu click eventschrome.contextMenus, chrome.storage, chrome.tabs APIs

manifest.json — key fields explained

manifest.json — annotated
{
  "manifest_version": 3,          // MV3 — required by Chrome since 2024
  "name": "IO Marketing OS",        // Shown in toolbar tooltip and Extensions list
  "version": "1.0.0",               // SemVer — update when files change
  "description": "...",              // Shown in Extensions list
  "permissions": [                   // Explicit permission declarations
    "activeTab",                     // Current tab access (click-triggered only)
    "storage",                       // chrome.storage.local for library
    "scripting",                     // Inject content script for extraction
    "contextMenus"                   // Right-click menu item
  ],
  "host_permissions": ["<all_urls>"], // Required for scripting on unknown URLs
  "action": {
    "default_popup": "popup.html",  // The popup file
    "default_title": "..."           // Toolbar tooltip text
  },
  "background": {
    "service_worker": "background.js" // MV3 uses service workers, not background pages
  }
}

How the files interact

Chrome loads manifest.json at install time. It starts the background.js service worker. The service worker registers the context menu. When you click the IO icon, Chrome loads popup.html, which loads popup.js. When you click "Analyze This Page," popup.js calls chrome.scripting.executeScript to inject a content extraction function into the active tab. The extracted data is returned to popup.js, which displays the result in the popup UI and saves it to chrome.storage.local.

Reference · 16 of 17
Reference · 17

Changelog

Version history for the IO Chrome Extension — what changed, when, and why.


Version History · Breaking Changes · Deprecations
Version History
IO Chrome Extension Changelog
VersionDateChangesBreaking?
1.0.0March 2026Initial release. Four core features: Analyze This Page, Save to Library, Right-Click Context Menu, Capture Library. Manifest V3 architecture.

Planned for v1.1

  • Direct launch of IO Platform URL Intelligence from the popup (single-click flow)
  • Selected text capture — right-click a text selection to add it to your library as a quoted insight
  • Library export/import as JSON from within the popup
  • Custom keyboard shortcut pre-configured in manifest.json

Planned for v2.0

  • Embedded analysis result in the popup — run IO framework analysis without leaving the page
  • Site-wide crawl mode — save all links on a page to the library in one click
  • Integration with the IO Platform content builder — one-click from analysis to article generation

Updating from a previous version

When a new version is released, copy the updated files into your io-extension folder (replacing the old ones). Go to chrome://extensions and click the refresh icon on the IO Marketing OS card. The extension reloads without losing your capture library — library data is in chrome.storage.local, which persists across extension reloads. If a version includes a breaking change to the storage format, it will be noted here with migration instructions.

"Software versions exist because understanding improves. Version 1.0 is not the final word — it is the most honest representation of current knowledge."

Reference · 17 of 17 · Documentation Complete
Brand Guidelines · 18

Brand Overview

The IO Platform design system is built on one foundational decision: editorial clarity over interface decoration. Every visual choice serves legibility, hierarchy, and trust — not novelty.


Design Philosophy · Core Principles · Identity System · Voice

Project IO began as an editorial system — a library of marketing intelligence organized like a publication. The design follows that origin. The aesthetic is closer to a quality journal than a SaaS dashboard: generous whitespace, a serif-and-sans pairing that gives content typographic authority, a restrained color palette that reserves accent color for genuine information, and a layout system that makes long-form content readable at length.

The visual language is deliberately un-trendy. No gradients. No glassmorphism. No decorative animations. The system should look as correct in 2030 as it does today.

The five design principles

1 · Editorial first
Content is the interface
Typography does the organizing work
Whitespace is a structural element
Chrome recedes; content advances
2 · Hierarchy through type
Serif for body and authority
Sans-serif for labels and UI
Monospace for code and data
Size + weight carry structure
3 · Color as information
Amber is the only accent
Color encodes series identity
Saturation signals importance
No decoration-only color
4 · Borders as structure
1.5px solid rule as page boundary
1px rule for internal divisions
No box shadows for decoration
Border-right used for active state
5 · Motion with restraint
Transitions only where functional
Max duration: 280ms
Ease for panels; linear for scrolls
No animation for attention

What the IO brand is not

The IO brand is not a SaaS product brand. It does not use purple gradients, floating cards with drop shadows, or bold geometric illustration. It is not a startup brand — it does not chase trend cycles or use Figma-era sans-serif typefaces (Inter, Geist, DM Sans). It is not an agency brand — it does not use full-bleed black backgrounds with white-on-black type. It is a publication brand built for a long time horizon, designed to communicate depth and expertise through restraint and consistency.

"The best design systems are invisible. The interface disappears and the reader is left with the content. That is the goal."

Brand Guidelines · 18 of 23
Brand Guidelines · 19

The Color System

Thirteen CSS custom properties, one accent color, and a strict rule: color carries meaning. Never decoration.


CSS Variables · Palette · Usage Rules · Series Colors · Contrast

The core palette — CSS variables

Core palette — live swatches
--page
#fafaf8 · Page background
--surface
#ffffff · Cards, sidebar
--ink
#1a1a1a · Primary text
--ink-muted
#5a5a5a · Secondary text
--ink-faint
#999 · Labels, meta
--rule
#e8e6e0 · Borders
--amber
#c47b1a · The sole accent
--green
#1a9e5a · Success / S02

The 13 series colors

Each series in the IO Marketing OS has an assigned color. These colors are used exclusively for that series' sidebar dot, article number label, article index dot, and tag background. They are never mixed — the color belongs to the series, not to a semantic meaning.

Series color assignments — all 13
S01 · IO Marketing OS
#c47b1a
S02 · AI Agentic Layer
#b8961a
S03 · Nine Libraries
#ba7517
S04 · SEO & GEO
#0c7045
S05 · Creative Production
#b53060
S06 · Audience
#0080a0
S07 · Brand & Positioning
#9a7000
S08 · Influencer
#6a3fa0
S09 · Sales & Revenue
#8a1a2a
S10 · Platform Playbooks
#1a5fa0
S11 · PR & Earned Media
#2a4a6a
S12 · Product Marketing
#b05a00
S13 · Data & Privacy
#2a3a9a

Color usage rules

Color Governance
When to Use Each Category
Use caseColor to useNever use
Primary text--ink (#1a1a1a)Pure black (#000). Pure black reads as harsh; --ink is warm near-black.
Secondary / supporting text--ink-muted (#5a5a5a)Grey that is lighter than #5a5a5a — fails WCAG AA contrast on --page background.
Labels, overlines, meta text--ink-faint (#999)For body copy — too light for reading. Labels only.
Page background--page (#fafaf8)Pure white (#fff) as page bg — too stark. --page has a warm tint.
Surface (cards, sidebar)--surface (#ffffff)--page on cards — the distinction between page and surface creates visual depth.
Borders--rule (1px) or --ink (structural/brand borders)Color-family borders on non-series UI elements — borders carry structure, not decoration.
Accent / interactive / brand--amber (#c47b1a)Any other color as an interactive or accent color. Amber is the only accent.
Series identifier elementsThe assigned series colorUsing a series color for non-series UI elements — these colors are owned by their series.
Contrast compliance: All body text on --page background exceeds WCAG AA (4.5:1 ratio). --ink on --page = 16.5:1. --ink-muted on --page = 7.1:1. --ink-faint on --page = 2.9:1 — use for large text and labels only (WCAG AA large text threshold: 3:1).
Brand Guidelines · 19 of 23
Brand Guidelines · 20

Typography System

Three typefaces. A strict hierarchy. No custom fonts — the entire system runs on system-native typefaces available in every browser without a single font request.


Three Typefaces · Scale · Hierarchy · Usage Rules

The three typefaces

Serif — Georgia
The IO Marketing
Operating System
font-family: 'Georgia', 'Times New Roman', serif
Used for: page titles, article headlines, decks, body text, pull quotes
Weight: 400 (regular) only. No bold serif.
Role: authority, depth, readability at length
Sans — Helvetica Neue
SERIES · LABEL · UI
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif
Used for: sidebar items, labels, overlines, table headers, UI elements, buttons, stats
Weights: 400 (regular) and 700 (bold)
Role: structure, navigation, labeling
Mono — Courier New
manifest.json
chrome://extensions
--ink: #1a1a1a;
font-family: 'Courier New', Courier, monospace
Used for: code blocks, inline code, file names, CSS variables, keyboard shortcuts
Weight: 400 only
Role: code, technical strings, precision
Type Scale
Every Text Style in the System
ElementFontSizeWeightLetter-spacingUsed for
Page title (.masthead-title)Serifclamp(2.2rem, 5vw, 3.8rem)400−0.02emMasthead hero headlines
Article headline (.art-hl)Serif2.1rem400−0.02emArticle page titles
Article deck (.art-deck)Serif italic1.1rem400normalStandfirst / article sub-title
Body copy (.body p)Serif15px400normalAll long-form body text
Section heading (.body h3)Sans13px7000.08emIn-article section breaks, all-caps
Pull quote (.pull p)Serif italic1.08rem400normalHighlighted quotations
Sidebar item (.sb-item)Sans11.5px400 / 600 activenormalNavigation links
Section label (.sb-section)Sans8.5px7000.22emSidebar group headings, all-caps
Overline (.art-num, .series-label)Sans10–11px7000.15–0.22emSeries attribution, all-caps
Table header (.spec th)Sans9.5px7000.15emColumn headers, all-caps
Table body (.spec td)Sans12.5px400 / 600 .sknormalTable data
Inline code (.body code)Mono12.5px400normalCode, file names, CSS vars in prose
Code block (pre)Mono12.5px400normalFull code examples

Typography rules

  • Never use bold (font-weight: 700) in serif body text. Bold is reserved for the sans-serif labeling layer.
  • Never use italic in the sans-serif layer. Italic is reserved for serif body — specifically decks and pull quotes.
  • Letter-spacing is only applied to the sans-serif layer. Serif text always uses normal letter-spacing.
  • All-caps text is only used with the sans-serif, never with serif or mono.
  • Do not add intermediate sizes. The scale is defined — use the defined steps, do not interpolate.
  • Line-height: body text uses 1.82. Labels use 1.3. Navigation items use 1.3. Code uses 1.7.
Brand Guidelines · 20 of 23
Brand Guidelines · 22

Brand Voice & Tone

The IO editorial voice is expert, direct, and opinionated. It does not hedge. It does not use vague marketing language. It says what it means in the fewest words that still carry the full weight of the idea.


Voice Dimensions · Tone by Context · Dos and Don'ts · Writing Standards

The voice in four dimensions

Expert — not academic
Deep knowledge, light jargon
Industry terms used precisely
No jargon for its own sake
Assumes a smart reader
Never condescending
Direct — not blunt
Lead with the conclusion
No throat-clearing preamble
Short sentences in UI text
Long sentences only in body prose
One idea per sentence
Opinionated — not dogmatic
States positions clearly
Pull quotes are always a claim
Acknowledges counterarguments
Recommends — does not list options without guidance
Precise — not pedantic
Specific numbers over ranges
Named tools over generic categories
Action verbs over nominalisations
Active voice over passive
Voice Calibration
Before and After Examples
Off-voiceOn-voiceWhy
There are many approaches to considerUse this approach.The IO voice recommends. It does not list options without guidance.
Leveraging synergistic content strategiesPublishing content that earns backlinksReplace marketing nominalizations with specific actions.
It's important to note that results may varyResults vary by industry — B2B typically sees 3–6 months to first cluster rankingReplace hedging with a specific, useful qualifier.
This powerful tool helps you optimize your workflowThis tool cuts briefing time from 40 minutes to 8Replace marketing adjectives with measurable outcomes.
We recommend considering utilizing a structured approachUse a structured approach.Remove modal hedging and nominalizations simultaneously.
Content marketing is a complex disciplineMost content marketing fails because the brief comes before the audience researchReplace a generic truth with a specific, arguable claim.

Tone by context

The editorial voice does not change across contexts — the register adjusts. In long-form articles: full sentences, subordinate clauses, evidence-based argumentation, pull quotes that provoke. In UI labels: 2–4 words maximum, imperative verbs, no articles ("The" / "A") where they can be omitted. In error messages: state what happened, why, and what to do — in that order, in plain language, without blame. In section labels and overlines: all-caps, abbreviated, sparse — three words maximum.

The pull quote standard

Every article ends its major sections with a pull quote. The pull quote is always: (1) a complete, standalone sentence — it is not a teaser for the paragraph; (2) a claim, not a summary — it argues something, not just states it; (3) under 35 words; (4) set in the first person or present tense — "The brief is the most undervalued document in a marketing operation" not "Pull quotes should be statements."

"Write the pull quote first. If you cannot summarise the section's core argument in one opinionated sentence, the section does not have a clear argument yet."

Brand Guidelines · 22 of 23
Brand Guidelines · 23

Motion & Interaction

All motion in the IO system is functional. It communicates state change, confirms actions, or guides spatial orientation — never attracts attention or decorates.


Transitions · Easing · Hover States · Active States · Scroll
Motion Specification
All Transitions in the System
ElementPropertyDurationEasingPurpose
Sidebar (.sb-item)background, color100mslinearHover state feedback — fast, immediate
Sidebar collapse (.sb-sub)max-height280mseaseShows/hides sub-navigation naturally
Sidebar arrow (.arr)transform (rotate)180mslinearIndicates open/closed state of section
Mobile sidebar (#sidebar)transform (translateX)250mseaseSlide in/out on mobile
Index grid item (.ii)background120mslinearHover state on article grid cards
Article footer button (.afb)background120mslinearHover state on prev/next nav
Code copy buttonbackground, color150mslinearHover feedback on copy button
Page scroll (#main)scrollTopsmoothbrowser defaultSmooth scroll on navigation (scrollTo)

Hover state rules

  • All interactive elements have a visible hover state. There are no "guess what's clickable" patterns.
  • Hover background change: #f5f4f0 (slightly darker than --page). Used on sidebar items, index cards, arch cells.
  • Active / selected state: #f0ede6 (amber-tinted) with a right-hand 2px solid border in --ink. Used on sidebar items.
  • No scale transforms on hover. No float or elevation changes. No glow effects.
  • Cursor: pointer on all clickable elements without exception. The system never requires the user to guess.

What the system never does with motion

  • No loading spinners — use status text instead (e.g. "Running analysis...")
  • No entrance animations on panels — panels switch immediately
  • No parallax scrolling — the reading surface is flat and stable
  • No pulsing, bouncing, or attention-seeking animations of any kind
  • No transition on color changes that are not state-related

"Motion that the user notices is motion that failed. The goal is state change confirmation, not choreography."

Brand Guidelines · 23 of 23
Component Library · 24

Component Library Overview

Every reusable pattern in the IO design system — documented with its HTML structure, CSS class names, usage rules, and live examples. The library covers the full surface area of the editorial site, documentation site, and platform UI.


13 Component Categories · HTML Patterns · CSS Classes · Usage Rules

The IO component library is not a collection of React components or a Storybook — it is a set of well-defined HTML patterns and CSS class conventions that compose consistently into pages. Every component in the system is built from the same underlying CSS custom properties defined in :root. Changing a CSS variable updates the entire system simultaneously.

The library is organized by layer: navigation first, then page structure, then content blocks, then inline elements, then feedback patterns. Each section documents the exact HTML required, which CSS classes are available, and the usage rules that make the pattern work correctly.

25
Navigation Components
Sidebar, topbar, breadcrumb, home button — the complete navigation layer.
26
Masthead & Hero
Page-level hero pattern with title, subtitle, rule, and stats bar.
27
Article Structure
The standard article panel: art-num, art-hl, art-deck, art-div, and the .aw wrapper.
28
Body & Typography
Paragraphs, section headings, lists, inline code, links, and the pull quote.
29
Data Tables
The spec table — the system's primary data display pattern.
30
Cards & Grid Layouts
System card (.sc), channel columns (.ch-cols), index grid (.ig), and arch grid.
31
Notices & Callouts
Four notice types — tip, warn, info, caution — with icon and body.
32
Code Blocks
Dark-background code blocks with filename header, syntax highlighting, and copy button.
33
Tags & Badges
The full .tag/.c-* color class system for labeling and classification.
34
Step Flows
Numbered sequential process documentation with optional inline code blocks.
35
UI Mockup Frame
The browser-window mockup container for embedded interface demonstrations.
36
Article Footer Nav
The prev/next navigation footer at the bottom of every article panel.
Component Library · 24 of 36
Component Library · 25

Navigation Components

The complete navigation layer: the fixed sidebar with brand block, scroll area, section labels, toggle groups, and items — plus the sticky topbar with breadcrumb, and the hamburger for mobile.


#sidebar · .sb-* classes · #topbar · #ham · Responsive behavior

The sidebar anatomy

Sidebar Component Reference
Every .sb-* Class and Its Role
Class / IDElementPurposeKey CSS
#sidebarasideFull-height fixed panel, 268px wide on desktopposition:fixed; width:var(--sidebar-w); border-right:1.5px solid var(--ink)
.sb-branddivTop brand block — logo, name, subtitlepadding:1.4rem 1.2rem; border-bottom:2px solid var(--ink)
.sb-brand-overdivOverline: "Project IO" — namespace label9px sans; 700; 0.22em letter-spacing; --ink-faint
.sb-brand-titledivThe wordmarkGeorgia; 1.25rem; 400; --ink
.sb-brand-subdivContextual subtitle10px sans; --ink-faint
.sb-scrolldivScrollable nav area below the brand blockflex:1; overflow-y:auto; thin scrollbar
.sb-sectiondivGroup label (e.g. "Getting Started")8.5px sans; 700; all-caps; ::after rule line
.sb-itembuttonNavigation link11.5px sans; hover:#f5f4f0; active:.active class
.sb-item.activebutton stateCurrently viewed page indicatorbackground:#f0ede6; font-weight:600; border-right:2px solid var(--ink)
.sb-item.sb-homebutton variantHome / overview link — slightly larger12.5px; font-weight:600
.sb-dotspan inside .sb-itemSeries color indicator circle7px × 7px; border-radius:50%; background: series color
.sb-numspan inside .sb-itemArticle number label9px sans; 700; --ink-faint
.sb-togbuttonCollapsible group toggle (Series 01, etc.)11px sans; 700; all-caps; .arr arrow inside
.sb-subdivCollapsible sub-listmax-height:0 collapsed; max-height:800px open; 280ms ease
.sb-footerdivBottom attribution lineborder-top:1px solid var(--rule); 9.5px sans; --ink-faint

Standard .sb-item HTML pattern

Sidebar item with number and series dot
<!-- Standard sidebar navigation item -->
<button class="sb-item" onclick="go('panel-id',this,'Section Name','Article Title')">
  <span class="sb-num">01</span>
  <span class="sb-dot" style="background:#c47b1a"></span>
  Article Title
</button>

<!-- Section label -->
<div class="sb-section">Section Name</div>

<!-- Home / overview item (no dot, no number) -->
<button class="sb-item sb-home active" onclick="go('home',this,'Project IO','')">
  <span style="font-size:13px"></span> Home &middot; Full System
</button>

The topbar

The topbar is a sticky 40px-high bar at the top of the main content area. It displays a breadcrumb: "Project IO › Current Section › (Current Article)". The section segment is always shown; the article segment shows only when an article is active (controlled by the go() function's third and fourth arguments). On mobile, the topbar also shows the hamburger menu button (#ham).

Responsive behavior

Below 880px: the sidebar translates off-screen (transform: translateX(-100%)) and the hamburger appears. The sidebar slides in with a 250ms ease transition when .open class is added. An overlay (#overlay) covers the main content when the sidebar is open on mobile, clicking it closes the sidebar. Below 540px: additional content simplifications apply — masthead stats hidden, grid columns collapse to single column.

Component Library · 25 of 36
Component Library · 26

Masthead & Hero

The masthead is the full-width page header that appears at the top of index and overview panels. It contains the series label, page title, subtitle, a rule with tag line, and an optional stats bar.


.masthead · .series-label · .masthead-title · .masthead-rule · .masthead-stats
Complete masthead HTML
<div class="masthead">
  <!-- Overline: series / section context -->
  <div class="series-label">Project IO &middot; Series 04 of 13</div>

  <!-- The page title — Georgia, large, centered -->
  <h1 class="masthead-title">The SEO &amp; GEO<br>Architecture</h1>

  <!-- Subtitle: 14px sans, --ink-muted, max-width 620px -->
  <p class="masthead-sub">One sentence describing what the section covers.</p>

  <!-- Rule with tag line -->
  <div class="masthead-rule">
    <hr><span>Tag One &middot; Tag Two &middot; Tag Three</span><hr>
  </div>

  <!-- Stats bar — omit if not applicable -->
  <div class="masthead-stats">
    <div class="mstat">
      <span class="mstat-num">9</span>
      <span class="mstat-label">Articles</span>
    </div>
  </div>
</div>

Usage rules

  • The masthead only appears on index/overview panels. Individual article panels use the .art-num + .art-hl + .art-deck pattern instead.
  • The <br> in the title is intentional — masthead titles are often two lines for visual balance. Do not force all titles to one line.
  • The .masthead-sub subtitle has a max-width of 620px and is centered. It should be a single sentence — no longer.
  • The .masthead-stats bar is optional. Use it only when you have 3–7 meaningful quantitative stats for the section. Do not pad with weak stats.
  • The masthead has a border-bottom: 2px solid var(--ink) — the same 2px weight used in the sidebar brand block. This creates visual consistency between the two structural anchors.
Component Library · 26 of 36
Component Library · 27

Article Structure

Every article panel in the IO system follows the same structural template: panel wrapper, content wrapper, article number, headline, deck, divider line, body content, and footer navigation.


.panel · .aw · .art-num · .art-hl · .art-deck · .art-div
Complete article panel template
<!-- The panel div — id must match go() calls -->
<div class="panel" id="panel-{id}">

  <!-- Content wrapper: max-width 800px, centered, padded -->
  <div class="aw">

    <!-- Overline: series context, colored by series -->
    <div class="art-num" style="color:{series-hex}">
      Series 04 &middot; Article III of IX
    </div>

    <!-- Article headline: Georgia, 2.1rem -->
    <h1 class="art-hl">Technical SEO Infrastructure</h1>

    <!-- Deck: italic Georgia, muted, standfirst -->
    <p class="art-deck">One compelling standfirst sentence.</p>

    <!-- Divider with topic tags -->
    <div class="art-div">
      <hr>
      <span>Topic &middot; Topic &middot; Topic</span>
      <hr>
    </div>

    <!-- Body content -->
    <div class="body">
      <p>Body text...</p>
      <h3>Section Heading</h3>
      <p>More body text...</p>
    </div>

    <!-- Pull quote -->
    <div class="pull"><p>"Pull quote here."</p></div>

    <!-- Article footer navigation -->
    <div class="af">
      <button class="afb" onclick="go('prev-id',null,'S','Prev')">&larr; Prev</button>
      <div class="af-issue">Article III of IX &middot; Series 04</div>
      <button class="afb" onclick="go('next-id',null,'S','Next')">Next &rarr;</button>
    </div>

  </div><!-- /.aw -->
</div><!-- /.panel -->

The .art-div divider

The .art-div is a horizontal rule with a centered text label. The two <hr> elements grow to fill the available width using flex:1. The <span> contains 2–5 topic tags separated by &middot; (·). These tags describe the article's key concepts — they appear only once, in the divider, and nowhere else in the article.

Panels vs. the .aw wrapper

The .panel div is the visibility container — it is display:none by default and display:block when the .active class is added by the go() function. The .aw div is the content wrapper — it sets max-width:800px, margin:0 auto, and the consistent padding. Every article panel has both layers. Index and overview panels may use the masthead outside the .aw wrapper (before it), then the .aw for the body content below.

Component Library · 27 of 36
Component Library · 28

Body & Typography

All text elements inside the .body wrapper — paragraphs, section headings, lists, inline code, links — and the pull quote component that lives between body and footer.


.body p · .body h3 · .body ul/ol · .body code · .pull
Body Element Reference
Every Element Inside .body
ElementRendered asKey stylesUsage rule
.body pGeorgia 15px, 1.82 line-height, --inkmargin-bottom:1.2remDefault body text. Never use div for prose.
.body h3Helvetica 13px, 700, all-caps, 0.08em spacingmargin:2rem 0 0.7remSection headings only. No h2 or h4 in body content.
.body h4Georgia italic 1.05remmargin:1.5rem 0 0.5remSub-section headings when h3 would be too heavy.
.body ul liGeorgia 15px, 1.7 line-height, disc markermargin-left:1.4remUnordered lists. Use for non-sequential collections.
.body ol liGeorgia 15px, 1.7 line-height, decimal markermargin-left:1.4remOrdered lists. Use only for sequential steps.
.body a--amber color, border-bottom: 1px solid --ambertext-decoration:none; hover: opacity:.75Inline links in body prose. Use sparingly.
.body codeCourier New 12.5px, #f0ede6 backgroundpadding:1px 5px; border-radius:3pxInline code, file names, CSS vars in prose.
.body strongfont-weight:700 (sans context: sans bold; serif context: serif bold)Use rarely — emphasis loses power when overused.

The pull quote

The pull quote (.pull) lives outside the .body wrapper, between a content section and the next section or the footer. It is always the last element before the .af footer. The pull quote has a 3px amber left border and an amber-tinted background. The text inside is Georgia italic.

Pull quote HTML
<div class="pull">
  <p>"Pull quote text — one sentence, a claim, under 35 words."</p>
</div>
Do not nest .body inside .body. All body prose elements sit directly in a single .body div. The .body class applies Georgia and line-height through descendant selectors — nesting creates specificity conflicts.
Component Library · 28 of 36
Component Library · 29

Data Tables

The spec table is the primary data display pattern. It handles reference tables, comparison matrices, configuration guides, and specification sheets — always inside the system card container.


.sc · .spec · .sk · .sv · .sc-label · .sc-title
Complete system card with spec table
<!-- The .sc container wraps every spec table -->
<div class="sc">
  <!-- Small uppercase label above the title -->
  <div class="sc-label">Reference</div>
  <!-- Georgia title for the table -->
  <div class="sc-title">Table Title Here</div>
  <table class="spec">
    <thead>
      <tr>
        <th>Column A</th>
        <th>Column B</th>
        <th>Column C</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <!-- .sk: key cell — bold, --ink, nowrap -->
        <td class="sk">Row key</td>
        <!-- .sv: value cells — --ink-muted -->
        <td class="sv">Value one</td>
        <td class="sv">Value two</td>
      </tr>
    </tbody>
  </table>
</div>

Table design rules

  • Always wrap spec tables in a .sc system card. A bare table without the .sc wrapper lacks the visual container that gives it separation from body text.
  • The first column always gets .sk (key). It is bold, --ink, and white-space:nowrap. All other columns get .sv (value).
  • Column headers (th) are automatically styled: 9.5px sans-serif, 700, all-caps, 0.15em letter-spacing, --ink-muted, with a 1.5px solid var(--ink) bottom border.
  • Rows have a hover state: background:#f5f4f0 on all cells in the hovered row.
  • Tables should have 3–7 columns maximum. Beyond 7 columns, readability degrades. Split into two tables or simplify.
  • Row count: 4–12 rows is the sweet spot. Below 4: use a list instead. Above 12: consider splitting into sections.
Component Library · 29 of 36
Component Library · 30

Cards & Grid Layouts

Four grid and card patterns cover all multi-column layout needs: the system card for contained content blocks, the channel columns grid for feature comparison, the index grid for article listings, and the architecture grid for section overviews.


.ch-cols · .ig · .arch-grid · .sc · CSS Grid · auto-fit
Grid Pattern Reference
Four Grid Systems Compared
PatternClassesgrid-template-columnsUse for
Channel Columns.ch-cols → .ch-col → .ch-head + .ch-itemrepeat(auto-fit, minmax(140px, 1fr))Feature comparison, property lists, multi-column attribute groups. 3–5 columns typical.
Index Grid.ig → .ii → .ii-num + .ii-name + .ii-subrepeat(auto-fill, minmax(210px, 1fr))Article listings, overview index cards. Each card is clickable and navigates to its panel.
Architecture Grid.arch-grid → .arch-cell → .ac-over + .ac-title + .ac-descrepeat(3, 1fr) — or inline overrideSeries overview cards on the home panel. Separated by 1px rules with the grid gap as the rule.
System Card.sc → .sc-label + .sc-title + (table or content)N/A — block layoutWraps spec tables, config examples, and any contained reference block.
Channel columns (.ch-cols) — most common grid pattern
<div class="ch-cols">
  <div class="ch-col">
    <!-- .ch-head uses inline style for color: background + color -->
    <div class="ch-head" style="background:#faeeda;color:#412402">Column Title</div>
    <div class="ch-item">Item one</div>
    <div class="ch-item">Item two</div>
    <div class="ch-item">Item three</div>
  </div>
  <!-- repeat for each column -->
</div>

<!-- Index grid (.ig) -->
<div class="ig">
  <div class="ii" onclick="go('panel-id',null,'Section','Title')">
    <div class="ii-num">
      <span class="iddot" style="background:{series-color}"></span>Article I
    </div>
    <div class="ii-name">Article Title</div>
    <div class="ii-sub">One sentence description.</div>
  </div>
</div>

The .ig gap trick

The index grid uses gap:1px; background:var(--rule) on the container, with background:var(--surface) on each .ii card. This creates 1px grid lines between cards using the gap color — no borders needed on individual cards. The result is a seamless grid that maintains the dividing lines without doubling border thickness at the joins.

Component Library · 30 of 36
Component Library · 31

Notices & Callouts

Four notice types for contextual information that sits outside the regular flow: tips, warnings, informational notes, and cautions. Each has a distinct left border color, background tint, and icon.


.notice · .notice.tip · .notice.warn · .notice.info · .notice.caution
.notice.tip — Positive guidance, best practices, recommended approaches. Green left border (#1a9e5a). Use the ✓ icon.
.notice.info — Neutral additional context, definitions, cross-references. Blue left border (#185fa5). Use the ℹ icon.
.notice.warn — Important caveats, edge cases, common mistakes to avoid. Amber left border (#c47b1a). Use the ⚠ icon.
!
.notice.caution — Destructive or irreversible actions, critical warnings. Coral left border (#c94f35). Use the ! icon.
Notice HTML pattern
<!-- Replace class "tip" with: info | warn | caution -->
<div class="notice tip">
  <!-- Icon: ✓ (tip) · ℹ (info) · ⚠ (warn) · ! (caution) -->
  <span class="notice-icon"></span>
  <div class="notice-body">
    <!-- Optional strong lead-in -->
    <strong>Lead-in label:</strong> Notice body text here.
  </div>
</div>
Notice Usage Guide
When to Use Each Notice Type
TypeWhen to useWhen not to use
tipBest practices, "pro tip" guidance, recommended patterns, positive reinforcementDo not use for neutral information — that's info. Do not use to compliment the reader.
infoDefinitions, background context, cross-references, "before you start" prerequisitesDo not use for warnings or best practices — specificity matters.
warnCommon mistakes, edge cases that break things, "note that" qualifications, gotchasDo not use for normal caveats in body prose — reserve warn for genuinely important qualifications.
cautionIrreversible actions (deleting data, clearing library), security risks, breaking changesDo not overuse — caution loses impact if it appears more than once per article.
Component Library · 31 of 36
Component Library · 32

Code Blocks

The dark-background code block with filename header, syntax highlighting classes, and an interactive copy button. Used for multi-line code examples, configuration files, and shell commands.


.codeblock · .codeblock-head · .codeblock-copy · .kw .st .cm .fn .nm
The code block — self-documenting example
<div class="codeblock">
  <div class="codeblock-head">
    <!-- Left: filename or description -->
    <span>manifest.json</span>
    <!-- Right: copy button — calls copyCode(this) -->
    <button class="codeblock-copy" onclick="copyCode(this)">Copy</button>
  </div>
  <pre>
    <!-- Syntax highlighting classes: -->
    <!-- .kw  = keyword / HTML tag  → amber #c47b1a -->
    <!-- .st  = string / value      → green #7ab87a -->
    <!-- .cm  = comment             → grey #666, italic -->
    <!-- .fn  = function / attr     → blue #88aadd -->
    <!-- .nm  = number / special    → purple #dda0dd -->
    <span class="kw">&lt;div&gt;</span>example<span class="kw">&lt;/div&gt;</span>
  </pre>
</div>

The copyCode() function

The global copyCode(btn, text) function handles copy button behavior. It accepts the button element and an optional text string. If text is provided, it copies that string. If not, it reads the inner text of the nearest pre element (the code block's content). After copying, it temporarily changes the button label to "Copied!" for 1.8 seconds, then resets. All copy buttons in the system use this same function — it is defined once in the page-level script block.

When to use a code block vs inline code

Inline code (.body code) is for short strings in prose: file names, CSS class names, CSS variables, short commands. The dark code block is for: anything multi-line, anything the user needs to copy in full, configuration files, shell commands, and full HTML patterns. The rule: if it needs a copy button, it needs a code block.

Component Library · 32 of 36
Component Library · 33

Tags & Badges

The tag system provides colored labels for classification, status indication, and topic marking. Sixteen color classes cover the full palette — each with a matching background tint, text color, and border.


.tag · .c-amber · .c-green · .c-blue · .c-coral · all 16 classes
c-amber c-green c-blue c-coral c-pink c-purple c-red c-teal c-gray c-orange c-cyan c-gold c-violet c-indigo c-rose
Tag HTML pattern
<!-- Tags container -->
<div class="tags">
  <span class="tag c-amber">Tag label</span>
  <span class="tag c-green">Another tag</span>
  <span class="tag c-blue">Third tag</span>
</div>
Tag Color Reference
All 15 Color Classes — Background, Text, Border
ClassBackgroundTextBorderUse for
.c-amber#faeeda#412402#ba7517S01 · Primary accent · Featured items
.c-green#eaf3de#173404#3b6d11S02 · Success · Active · Enabled
.c-coral#faece7#4a1b0c#d85a30S03 · Warning · Changed · Modified
.c-pink#fbeaf0#4b1528#993556S04 variant · Highlighted
.c-blue#e6f1fb#042c53#185fa5S10 · Informational · Link-adjacent
.c-purple#eeedfe#26215c#534ab7S08 · Component library · UI elements
.c-red#fcebeb#501313#a32d2dError · Destructive · Danger · S09
.c-teal#e1f5ee#04342c#0f6e56S02 variant · Selected · Active state
.c-gray#f1efe8#2c2c2a#5f5e5aNeutral · Archived · Disabled
.c-orange#fef0e6#4a1800#c94f35S12 · Pending · In-progress
.c-cyan#e1f7fc#002a35#0088aaS06 · Audience · Community
.c-gold#fdf6e0#3d2600#b8961aS07 · Brand · Premium
.c-violet#f5eafe#330052#7a2fa5S08 variant · Creative
.c-indigo#e8ecfe#060d33#1a3fa5S13 · Data · Technical
.c-rose#fce8ef#450020#b53060S05 · Creative Production
Component Library · 33 of 36
Component Library · 34

Step Flows

The step flow pattern documents sequential processes. It uses amber numerals for orientation, step titles in the sans-serif labeling system, and step descriptions in body prose — with optional inline code blocks beneath each step.


.steps · .step · .step-num · .step-title · .step-desc · .step-code
Step flow HTML pattern
<div class="steps">
  <div class="step">
    <!-- Amber numeral: 22px Georgia, right-aligned, 32px wide -->
    <div class="step-num">1</div>
    <div class="step-body">
      <!-- Title: 13px sans, 700, all-caps -->
      <div class="step-title">Step Title Here</div>
      <!-- Description: Georgia 14.5px prose -->
      <div class="step-desc">Description of what to do in this step.</div>
      <!-- Optional: inline code example -->
      <code class="step-code">$ command --flag value</code>
    </div>
  </div>
  <!-- Repeat .step for each step. Last step has no border-bottom. -->
</div>

Step flow design rules

  • Steps are separated by a 1px --rule border-bottom. The last step has no border — CSS's :last-child selector handles this automatically in the .step rule.
  • Step numbers are always numerals (1, 2, 3...) — never letters, Roman numerals, or bullets. The amber color from --amber gives them visual weight without competing with body text.
  • Step titles are short (3–6 words), all-caps, sans-serif — they function as commands, not descriptions.
  • The .step-code element is an inline <code> with a block display style: grey background, monospace, padded. Use it for single commands. For multi-line code, use a full .codeblock after the .step-body.
  • Maximum 8–10 steps per flow. Beyond that, split into phases or use a different pattern.
Component Library · 34 of 36
Component Library · 35

The UI Mockup Frame

A browser-window frame for embedding interface demonstrations in documentation. It provides a chrome bar with traffic light dots and a title, creating the visual context of "this is a UI screenshot" without requiring actual images.


.ui-mock · .ui-mock-bar · .ui-dot · .ui-mock-title · .ui-mock-body
IO Marketing OS — Example popup or UI
UI content goes here — extension popup, settings screen,
dashboard widget, or any interface element.
UI mockup frame HTML
<div class="ui-mock">
  <!-- Browser chrome bar -->
  <div class="ui-mock-bar">
    <!-- Traffic light dots: always these three colors -->
    <div class="ui-dot" style="background:#ff5f57"></div>
    <div class="ui-dot" style="background:#ffbd2e"></div>
    <div class="ui-dot" style="background:#28c940"></div>
    <!-- Window / tab title -->
    <span class="ui-mock-title">Window title</span>
  </div>
  <!-- Content area — no padding applied; add inline -->
  <div class="ui-mock-body">
    <!-- Your UI content here -->
  </div>
</div>

Usage rules

  • The traffic light colors are always the exact macOS values — #ff5f57, #ffbd2e, #28c940. Do not substitute other reds/yellows/greens.
  • The .ui-mock-body has no default padding — add it inline on the body element to match the UI being demonstrated.
  • The .ui-mock container has a 1.5px solid var(--ink) border and a subtle box-shadow. Do not add additional borders or backgrounds to the container.
  • Use this pattern only when showing a UI as an example or annotation. Do not use it as a decorative container for non-UI content.
  • For extension popup mockups specifically: set the .ui-mock-body content width to 340px to match the actual popup dimensions.
Component Library · 35 of 36