AI Chrome Browser Extension Development
A Chrome Extension with AI enables adding LLM capabilities directly to the browser: page and article summarization, translation of selected text, AI assistant for form filling, content analysis on any website. Works through Service Worker (background) + Content Script + Popup UI.
Extension Structure
// manifest.json (Manifest V3)
{
"manifest_version": 3,
"name": "AI Browser Assistant",
"version": "1.0.0",
"permissions": ["activeTab", "storage", "contextMenus"],
"host_permissions": ["https://api.anthropic.com/*"],
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": ["content.css"]
}],
"action": {
"default_popup": "popup.html",
"default_icon": "icon.png"
}
}
Service Worker (background.js)
// background.js — central logic
const ANTHROPIC_API = 'https://api.anthropic.com/v1/messages';
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'AI_REQUEST') {
handleAIRequest(request.data).then(sendResponse);
return true; // Async response
}
});
async function handleAIRequest({ prompt, system, stream }) {
const { apiKey } = await chrome.storage.sync.get('apiKey');
if (!apiKey) return { error: 'API key not set' };
const response = await fetch(ANTHROPIC_API, {
method: 'POST',
headers: {
'x-api-key': apiKey,
'anthropic-version': '2023-06-01',
'content-type': 'application/json',
},
body: JSON.stringify({
model: 'claude-haiku-4-5',
max_tokens: 1024,
system: system || '',
messages: [{ role: 'user', content: prompt }],
}),
});
const data = await response.json();
return { result: data.content?.[0]?.text || '' };
}
// Context menu
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'ai-summarize',
title: 'AI: Summarize selected',
contexts: ['selection'],
});
chrome.contextMenus.create({
id: 'ai-translate',
title: 'AI: Translate to English',
contexts: ['selection'],
});
});
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.menuItemId === 'ai-summarize') {
chrome.tabs.sendMessage(tab.id, {
type: 'SHOW_AI_RESULT',
action: 'summarize',
text: info.selectionText,
});
}
});
Content Script (content.js)
// content.js — injected into pages
let aiPanel = null;
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
if (request.type === 'SHOW_AI_RESULT') {
showFloatingPanel(request.action, request.text);
}
});
function showFloatingPanel(action, text) {
// Create floating panel
if (!aiPanel) {
aiPanel = document.createElement('div');
aiPanel.id = 'ai-extension-panel';
aiPanel.innerHTML = `
<div class="ai-panel-header">
AI Assistant
<button class="ai-close">×</button>
</div>
<div class="ai-panel-content">
<div class="ai-loading">Loading...</div>
</div>
`;
document.body.appendChild(aiPanel);
aiPanel.querySelector('.ai-close').onclick = () => {
aiPanel.style.display = 'none';
};
}
aiPanel.style.display = 'block';
const systemPrompts = {
summarize: 'Summarize the text in 3-5 sentences in English.',
translate: 'Translate to English.',
};
chrome.runtime.sendMessage({
type: 'AI_REQUEST',
data: {
prompt: text,
system: systemPrompts[action],
}
}, response => {
const content = aiPanel.querySelector('.ai-panel-content');
content.innerHTML = response.result || response.error;
});
}
// "Summarize page" button appears on hover
document.addEventListener('mouseup', () => {
const selected = window.getSelection().toString().trim();
if (selected.length > 50) {
showSelectionTooltip(selected);
}
});
Popup UI
<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
<style>
body { width: 380px; min-height: 200px; padding: 16px; font-family: system-ui; }
textarea { width: 100%; height: 80px; }
button { width: 100%; margin-top: 8px; padding: 8px; }
</style>
</head>
<body>
<h3>AI Assistant</h3>
<button id="summarize-page">Summarize page</button>
<textarea id="custom-prompt" placeholder="Your question..."></textarea>
<button id="ask">Ask AI</button>
<div id="result"></div>
<script>
document.getElementById('summarize-page').onclick = async () => {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
// Get page text
const [{ result: pageText }] = await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => document.body.innerText.slice(0, 3000),
});
const response = await chrome.runtime.sendMessage({
type: 'AI_REQUEST',
data: {
prompt: pageText,
system: 'Summarize this web page in 5 key points.',
}
});
document.getElementById('result').textContent = response.result;
};
</script>
</body>
</html>
Timeline
- Basic extension (context menu + popup): 3–5 days
- Floating panel with streaming: 1 week
- Chrome Web Store publication: 3–7 days (Google review)







