Build cross-browser extensions with Google Antigravity IDE
# Browser Extension Development for Google Antigravity
Create powerful browser extensions using modern web technologies with Google Antigravity IDE.
## Manifest V3 Configuration
```json
{
"manifest_version": 3,
"name": "My Extension",
"version": "1.0.0",
"description": "A browser extension built with Google Antigravity",
"permissions": ["storage", "activeTab", "scripting", "alarms"],
"host_permissions": ["https://*.example.com/*"],
"action": {
"default_popup": "popup.html",
"default_icon": { "16": "icons/16.png", "32": "icons/32.png", "48": "icons/48.png", "128": "icons/128.png" }
},
"background": { "service_worker": "background.js", "type": "module" },
"content_scripts": [{
"matches": ["https://*.example.com/*"],
"js": ["content.js"],
"css": ["content.css"],
"run_at": "document_idle"
}],
"options_page": "options.html",
"icons": { "16": "icons/16.png", "48": "icons/48.png", "128": "icons/128.png" }
}
```
## Background Service Worker
```typescript
// src/background.ts
import { MessageType, Message, StorageData } from "./types";
// Extension lifecycle
chrome.runtime.onInstalled.addListener(async (details) => {
if (details.reason === "install") {
await chrome.storage.local.set({ settings: { enabled: true, theme: "auto" } });
chrome.tabs.create({ url: chrome.runtime.getURL("welcome.html") });
} else if (details.reason === "update") {
console.log("Extension updated to version", chrome.runtime.getManifest().version);
}
});
// Message handling
chrome.runtime.onMessage.addListener((message: Message, sender, sendResponse) => {
handleMessage(message, sender).then(sendResponse);
return true; // Keep channel open for async response
});
async function handleMessage(message: Message, sender: chrome.runtime.MessageSender) {
switch (message.type) {
case MessageType.GET_DATA:
const data = await chrome.storage.local.get("data");
return { success: true, data: data.data };
case MessageType.SAVE_DATA:
await chrome.storage.local.set({ data: message.payload });
return { success: true };
case MessageType.INJECT_SCRIPT:
if (sender.tab?.id) {
await chrome.scripting.executeScript({
target: { tabId: sender.tab.id },
files: ["injected.js"]
});
}
return { success: true };
default:
return { success: false, error: "Unknown message type" };
}
}
// Alarm handling for periodic tasks
chrome.alarms.onAlarm.addListener(async (alarm) => {
if (alarm.name === "sync-data") {
await syncDataWithServer();
}
});
chrome.alarms.create("sync-data", { periodInMinutes: 30 });
async function syncDataWithServer() {
const { data } = await chrome.storage.local.get("data");
if (data) {
try {
await fetch("https://api.example.com/sync", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
} catch (error) {
console.error("Sync failed:", error);
}
}
}
```
## Content Script
```typescript
// src/content.ts
import { MessageType, Message } from "./types";
class ContentScript {
private observer: MutationObserver | null = null;
async init() {
await this.injectUI();
this.setupMessageListener();
this.observeDOM();
}
private async injectUI() {
const container = document.createElement("div");
container.id = "my-extension-root";
container.attachShadow({ mode: "open" });
const styles = document.createElement("style");
styles.textContent = await this.getStyles();
container.shadowRoot!.appendChild(styles);
document.body.appendChild(container);
}
private setupMessageListener() {
chrome.runtime.onMessage.addListener((message: Message, sender, sendResponse) => {
if (message.type === MessageType.UPDATE_UI) {
this.updateUI(message.payload);
sendResponse({ success: true });
}
return true;
});
}
private observeDOM() {
this.observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === "childList") {
this.handleDOMChanges(mutation);
}
}
});
this.observer.observe(document.body, { childList: true, subtree: true });
}
private handleDOMChanges(mutation: MutationRecord) {
mutation.addedNodes.forEach((node) => {
if (node instanceof HTMLElement && node.matches(".target-element")) {
this.enhanceElement(node);
}
});
}
private enhanceElement(element: HTMLElement) {
const button = document.createElement("button");
button.textContent = "Enhanced";
button.onclick = () => this.sendToBackground({ type: MessageType.ELEMENT_CLICKED, payload: element.id });
element.appendChild(button);
}
private async sendToBackground(message: Message) {
return chrome.runtime.sendMessage(message);
}
private updateUI(data: unknown) {
const root = document.getElementById("my-extension-root");
if (root?.shadowRoot) {
// Update shadow DOM content
}
}
private async getStyles(): Promise<string> {
const response = await fetch(chrome.runtime.getURL("content.css"));
return response.text();
}
destroy() {
this.observer?.disconnect();
document.getElementById("my-extension-root")?.remove();
}
}
const contentScript = new ContentScript();
contentScript.init();
```
## Popup Component
```typescript
// src/popup/App.tsx
import { useState, useEffect } from "react";
import { MessageType } from "../types";
export function Popup() {
const [enabled, setEnabled] = useState(true);
const [stats, setStats] = useState({ processed: 0, saved: 0 });
useEffect(() => {
loadSettings();
}, []);
const loadSettings = async () => {
const { settings } = await chrome.storage.local.get("settings");
if (settings) setEnabled(settings.enabled);
const { stats } = await chrome.storage.local.get("stats");
if (stats) setStats(stats);
};
const toggleEnabled = async () => {
const newValue = !enabled;
setEnabled(newValue);
await chrome.storage.local.set({ settings: { enabled: newValue } });
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (tab.id) {
await chrome.tabs.sendMessage(tab.id, { type: MessageType.TOGGLE, payload: newValue });
}
};
return (
<div className="popup">
<h1>My Extension</h1>
<button onClick={toggleEnabled}>{enabled ? "Disable" : "Enable"}</button>
<div className="stats">
<p>Processed: {stats.processed}</p>
<p>Saved: {stats.saved}</p>
</div>
</div>
);
}
```
## Best Practices
1. **Use Manifest V3** for future compatibility
2. **Minimize permissions** to required only
3. **Use Shadow DOM** for isolated styling
4. **Handle extension lifecycle** events properly
5. **Implement proper error handling** in message passing
6. **Test across browsers** with polyfills
7. **Follow store guidelines** for approval
Google Antigravity streamlines browser extension development with intelligent code generation and cross-browser compatibility suggestions.This browser-extension prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their browser-extension implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For browser-extension projects, consider mentioning your framework version, coding style, and any specific libraries you're using.