Building Chrome extensions with Svelte gives you a powerful combination: Svelte’s reactive framework for creating responsive UI, and Chrome’s extension APIs for browser functionality. This guide walks you through setting up a Chrome extension with Svelte and using devtools effectively during development.
Why Svelte for Chrome Extensions?
Svelte compiles your components to vanilla JavaScript, which means smaller bundle sizes and faster execution—critical when Chrome enforces strict limits on extension package sizes. Unlike React or Vue, Svelte doesn’t require a runtime, reducing memory overhead in the browser context.
The reactive nature of Svelte works naturally with Chrome’s event-driven API model. When you listen to browser events like chrome.tabs.onUpdated or chrome.runtime.onMessage, Svelte stores can immediately reflect those changes in your popup or options page UI.
Setting Up Your Project
Create a new Svelte project using Vite, then configure it for Chrome extension development:
npm create vite@latest my-extension -- --template svelte
cd my-extension
npm install
Modify your vite.config.js to output to a Chrome-compatible format:
import { defineConfig } from 'vite';
import svelte from '@sveltejs/vite-plugin-svelte';
export default defineConfig({
plugins: [svelte()],
build: {
outDir: 'dist',
rollupOptions: {
output: {
entryFileNames: 'src/[name].js',
chunkFileNames: 'src/[name].js',
assetFileNames: 'src/[name].[ext]'
}
}
},
base: '.'
});
Create your manifest.json in the public folder:
{
"manifest_version": 3,
"name": "My Svelte Extension",
"version": "1.0.0",
"description": "A Chrome extension built with Svelte",
"action": {
"default_popup": "index.html",
"default_title": "Open Extension"
},
"permissions": ["tabs", "storage"],
"host_permissions": ["<all_urls>"]
}
Build your project with npm run build, then load the dist folder as an unpacked extension in Chrome’s chrome://extensions page.
Connecting DevTools to Your Extension
Chrome provides several devtools pages for debugging extensions. Access them through View > Developer > Developer Tools, then select your extension context from the dropdown.
Popup DevTools
When your popup is open, right-click and select Inspect to open DevTools specifically for the popup context. This is where you’ll debug your Svelte components, inspect reactive state, and trace event handlers.
Background Script Debugging
Navigate to chrome://extensions and click the “service worker” link under your extension. This opens DevTools for the background context where chrome.runtime listeners operate. Your Svelte app’s initialization logic runs here if you’re building a full-page extension.
Content Script Debugging
Content scripts run in the context of web pages. Set breakpoints in DevTools by navigating to the Sources panel and expanding the “Content Scripts” section. You’ll see your bundled content script there alongside the page’s own scripts.
Using Svelte Stores with Chrome APIs
Svelte stores provide an elegant way to bridge Chrome’s asynchronous APIs with reactive UI. Here’s a pattern for managing tab state:
// stores/tabs.js
import { writable } from 'svelte/store';
export const currentTab = writable(null);
export const tabHistory = writable([]);
export function initTabListener() {
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete' && tab.active) {
currentTab.set(tab);
tabHistory.update(history => [...history.slice(-9), tab]);
}
});
}
In your Svelte component, use the store to automatically reflect Chrome state:
<script>
import { currentTab, tabHistory } from '../stores/tabs.js';
import { onMount } from 'svelte';
onMount(() => {
initTabListener();
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
currentTab.set(tabs[0]);
});
});
</script>
<div class="tab-info">
<h3>Current Tab</h3>
<p>{$currentTab?.title || 'No active tab'}</p>
<p class="url">{$currentTab?.url || ''}</p>
</div>
<style>
.url {
font-size: 0.8em;
color: #666;
word-break: break-all;
}
</style>
Debugging Common Issues
Hot Reload Problems
During development, Chrome caches your extension files. After making changes:
- Click the reload icon in
chrome://extensions - Close and reopen your popup
- Check “Allow in incognito” if testing there
For faster iteration, use Chrome’s Watch mode in DevTools or configure Vite’s server to proxy requests.
Message Passing Failures
When communication between content scripts and background scripts fails, verify your message structure:
// Content script sends message
chrome.runtime.sendMessage({
type: 'FETCH_DATA',
payload: { url: window.location.href }
});
// Background script receives
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'FETCH_DATA') {
// Handle the message
fetchData(message.payload.url).then(sendResponse);
return true; // Keep message channel open for async response
}
});
The return true is critical for asynchronous responses. Without it, Chrome closes the channel before your async operation completes.
State Not Updating
If your Svelte store updates but the UI doesn’t reflect changes, verify you’re accessing the store with the $ prefix in your template. This triggers Svelte’s subscription mechanism.
Performance Optimization
Chrome extensions have resource limits. Svelte helps by producing minimal JavaScript, but follow these practices:
- Lazy-load non-critical components using Svelte’s dynamic imports
- Use
chrome.storage.sessionfor ephemeral data instead of in-memory variables that get cleared - Avoid polling—use event listeners instead of
setIntervalfor checking state
Building for Production
When ready to publish, create a production build that minimizes bundle size:
npm run build -- --minify
This produces optimized output in your dist folder. Test the unpacked version thoroughly before packaging with Chrome’s “Pack extension” button or using npm run build with a packaging tool.
Your extension is now ready for the Chrome Web Store. The combination of Svelte’s developer experience and Chrome’s powerful APIs enables you to build sophisticated browser tools with minimal overhead.
Related Reading
- Claude Code for Beginners: Complete Getting Started Guide
- Best Claude Skills for Developers in 2026
- Claude Skills Guides Hub
Built by theluckystrike — More at zovo.one